mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-27 01:30:35 +08:00
Make Long/Float/Double/Integer compare/hashCode methods cross-platform
This commit is contained in:
parent
e884bb35c9
commit
48d14570b2
@ -53,5 +53,7 @@ public class JCLPlugin implements TeaVMPlugin {
|
||||
String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class,
|
||||
CallSite.class), new LambdaMetafactorySubstitutor());
|
||||
host.add(new ScalaHacks());
|
||||
|
||||
host.add(new NumericClassTransformer());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2017 konsoletyper.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.impl;
|
||||
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.BinaryInstruction;
|
||||
import org.teavm.model.instructions.BinaryOperation;
|
||||
import org.teavm.model.instructions.ExitInstruction;
|
||||
import org.teavm.model.instructions.NumericOperandType;
|
||||
|
||||
public class NumericClassTransformer implements ClassHolderTransformer {
|
||||
@Override
|
||||
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||
switch (cls.getName()) {
|
||||
case "java.lang.Integer":
|
||||
transformInteger(cls);
|
||||
break;
|
||||
case "java.lang.Long":
|
||||
transformLong(cls);
|
||||
break;
|
||||
case "java.lang.Float":
|
||||
transformFloat(cls);
|
||||
break;
|
||||
case "java.lang.Double":
|
||||
transformDouble(cls);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void transformInteger(ClassHolder cls) {
|
||||
transformCompareMethod(cls, ValueType.INTEGER, NumericOperandType.INT);
|
||||
}
|
||||
|
||||
private void transformLong(ClassHolder cls) {
|
||||
transformCompareMethod(cls, ValueType.LONG, NumericOperandType.LONG);
|
||||
}
|
||||
|
||||
private void transformFloat(ClassHolder cls) {
|
||||
transformCompareMethod(cls, ValueType.FLOAT, NumericOperandType.FLOAT);
|
||||
}
|
||||
|
||||
private void transformDouble(ClassHolder cls) {
|
||||
transformCompareMethod(cls, ValueType.DOUBLE, NumericOperandType.DOUBLE);
|
||||
}
|
||||
|
||||
private void transformCompareMethod(ClassHolder cls, ValueType type, NumericOperandType insnType) {
|
||||
MethodHolder method = cls.getMethod(new MethodDescriptor("compare", type, type, ValueType.INTEGER));
|
||||
Program program = new Program();
|
||||
|
||||
program.createVariable();
|
||||
Variable firstArg = program.createVariable();
|
||||
Variable secondArg = program.createVariable();
|
||||
Variable result = program.createVariable();
|
||||
|
||||
BasicBlock block = program.createBasicBlock();
|
||||
|
||||
BinaryInstruction insn = new BinaryInstruction(BinaryOperation.COMPARE, insnType);
|
||||
insn.setFirstOperand(firstArg);
|
||||
insn.setSecondOperand(secondArg);
|
||||
insn.setReceiver(result);
|
||||
block.add(insn);
|
||||
|
||||
ExitInstruction exit = new ExitInstruction();
|
||||
exit.setValueToReturn(result);
|
||||
block.add(exit);
|
||||
|
||||
method.setProgram(program);
|
||||
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,10 +21,6 @@ import org.teavm.backend.javascript.spi.Generator;
|
||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class LongNativeGenerator implements Generator {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
@ -33,10 +29,6 @@ public class LongNativeGenerator implements Generator {
|
||||
writer.append("return Long_compare(").append(context.getParameterName(1)).append(", ")
|
||||
.append(context.getParameterName(2)).append(");").softNewLine();
|
||||
break;
|
||||
case "hashCode":
|
||||
writer.append("return ").append(context.getParameterName(1)).append(".hi ^ ")
|
||||
.append(context.getParameterName(1)).append(".lo;").softNewLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,9 +203,7 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||
return (int) (h >>> 32) ^ (int) h;
|
||||
}
|
||||
|
||||
public static int compare(double a, double b) {
|
||||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
}
|
||||
public static native int compare(double a, double b);
|
||||
|
||||
@Override
|
||||
public int compareTo(TDouble other) {
|
||||
|
@ -230,9 +230,7 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||
return isInfinite(value);
|
||||
}
|
||||
|
||||
public static int compare(float f1, float f2) {
|
||||
return f1 > f2 ? 1 : f2 < f1 ? -1 : 0;
|
||||
}
|
||||
public static native int compare(float f1, float f2);
|
||||
|
||||
@Override
|
||||
public int compareTo(TFloat other) {
|
||||
|
@ -244,9 +244,7 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
|
||||
return compare(value, other.value);
|
||||
}
|
||||
|
||||
public static int compare(int x, int y) {
|
||||
return x > y ? 1 : x < y ? -1 : 0;
|
||||
}
|
||||
public static native int compare(int x, int y);
|
||||
|
||||
public static int numberOfLeadingZeros(int i) {
|
||||
if (i == 0) {
|
||||
|
@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import org.teavm.backend.javascript.spi.GeneratedBy;
|
||||
|
||||
public class TLong extends TNumber implements TComparable<TLong> {
|
||||
public static final long MIN_VALUE = -0x8000000000000000L;
|
||||
public static final long MAX_VALUE = 0x7FFFFFFFFFFFFFFFL;
|
||||
@ -199,8 +197,9 @@ public class TLong extends TNumber implements TComparable<TLong> {
|
||||
return hashCode(value);
|
||||
}
|
||||
|
||||
@GeneratedBy(LongNativeGenerator.class)
|
||||
private static native int hashCode(long value);
|
||||
private static int hashCode(long value) {
|
||||
return (int) (value ^ (value >>> 32));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
@ -210,7 +209,6 @@ public class TLong extends TNumber implements TComparable<TLong> {
|
||||
return other instanceof TLong && ((TLong) other).value == value;
|
||||
}
|
||||
|
||||
@GeneratedBy(LongNativeGenerator.class)
|
||||
public static native int compare(long a, long b);
|
||||
|
||||
@Override
|
||||
|
@ -86,4 +86,11 @@ public class DoubleTest {
|
||||
assertEquals("0x0.8p-1022", Double.toHexString(0x0.8p-1022));
|
||||
assertEquals("0x0.001p-1022", Double.toHexString(0x0.001p-1022));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compares() {
|
||||
assertTrue(Double.compare(10, 5) > 0);
|
||||
assertTrue(Double.compare(5, 10) < 0);
|
||||
assertTrue(Double.compare(5, 5) == 0);
|
||||
}
|
||||
}
|
||||
|
@ -85,4 +85,11 @@ public class FloatTest {
|
||||
assertEquals("0x1.0p-126", Float.toHexString((float)Math.pow(2, -126)));
|
||||
assertEquals("0x0.001p-126", Float.toHexString(0x0.001p-126f));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compares() {
|
||||
assertTrue(Float.compare(10, 5) > 0);
|
||||
assertTrue(Float.compare(5, 10) < 0);
|
||||
assertTrue(Float.compare(5, 5) == 0);
|
||||
}
|
||||
}
|
||||
|
@ -127,4 +127,13 @@ public class IntegerTest {
|
||||
assertEquals(0xFFFFFFFF, Integer.reverse(0xFFFFFFFF));
|
||||
assertEquals(0xF63BA000, Integer.reverse(0x5DC6F));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compares() {
|
||||
assertTrue(Integer.compare(10, 5) > 0);
|
||||
assertTrue(Integer.compare(5, 10) < 0);
|
||||
assertTrue(Integer.compare(5, 5) == 0);
|
||||
assertTrue(Integer.compare(Integer.MAX_VALUE, Integer.MIN_VALUE) > 0);
|
||||
assertTrue(Integer.compare(Integer.MIN_VALUE, Integer.MAX_VALUE) < 0);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2017 konsoletyper.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
public class LongTest {
|
||||
@Test
|
||||
public void compares() {
|
||||
assertTrue(Long.compare(10, 5) > 0);
|
||||
assertTrue(Long.compare(5, 10) < 0);
|
||||
assertTrue(Long.compare(5, 5) == 0);
|
||||
assertTrue(Long.compare(Long.MAX_VALUE, Long.MIN_VALUE) > 0);
|
||||
assertTrue(Long.compare(Long.MIN_VALUE, Long.MAX_VALUE) < 0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user