mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -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,
|
String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class,
|
||||||
CallSite.class), new LambdaMetafactorySubstitutor());
|
CallSite.class), new LambdaMetafactorySubstitutor());
|
||||||
host.add(new ScalaHacks());
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.backend.javascript.spi.GeneratorContext;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class LongNativeGenerator implements Generator {
|
public class LongNativeGenerator implements Generator {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
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(", ")
|
writer.append("return Long_compare(").append(context.getParameterName(1)).append(", ")
|
||||||
.append(context.getParameterName(2)).append(");").softNewLine();
|
.append(context.getParameterName(2)).append(");").softNewLine();
|
||||||
break;
|
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;
|
return (int) (h >>> 32) ^ (int) h;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int compare(double a, double b) {
|
public static native int compare(double a, double b);
|
||||||
return a > b ? 1 : a < b ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(TDouble other) {
|
public int compareTo(TDouble other) {
|
||||||
|
|
|
@ -230,9 +230,7 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
||||||
return isInfinite(value);
|
return isInfinite(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int compare(float f1, float f2) {
|
public static native int compare(float f1, float f2);
|
||||||
return f1 > f2 ? 1 : f2 < f1 ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(TFloat other) {
|
public int compareTo(TFloat other) {
|
||||||
|
|
|
@ -244,9 +244,7 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
|
||||||
return compare(value, other.value);
|
return compare(value, other.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int compare(int x, int y) {
|
public static native int compare(int x, int y);
|
||||||
return x > y ? 1 : x < y ? -1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int numberOfLeadingZeros(int i) {
|
public static int numberOfLeadingZeros(int i) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
import org.teavm.backend.javascript.spi.GeneratedBy;
|
|
||||||
|
|
||||||
public class TLong extends TNumber implements TComparable<TLong> {
|
public class TLong extends TNumber implements TComparable<TLong> {
|
||||||
public static final long MIN_VALUE = -0x8000000000000000L;
|
public static final long MIN_VALUE = -0x8000000000000000L;
|
||||||
public static final long MAX_VALUE = 0x7FFFFFFFFFFFFFFFL;
|
public static final long MAX_VALUE = 0x7FFFFFFFFFFFFFFFL;
|
||||||
|
@ -199,8 +197,9 @@ public class TLong extends TNumber implements TComparable<TLong> {
|
||||||
return hashCode(value);
|
return hashCode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GeneratedBy(LongNativeGenerator.class)
|
private static int hashCode(long value) {
|
||||||
private static native int hashCode(long value);
|
return (int) (value ^ (value >>> 32));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
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;
|
return other instanceof TLong && ((TLong) other).value == value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GeneratedBy(LongNativeGenerator.class)
|
|
||||||
public static native int compare(long a, long b);
|
public static native int compare(long a, long b);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -86,4 +86,11 @@ public class DoubleTest {
|
||||||
assertEquals("0x0.8p-1022", Double.toHexString(0x0.8p-1022));
|
assertEquals("0x0.8p-1022", Double.toHexString(0x0.8p-1022));
|
||||||
assertEquals("0x0.001p-1022", Double.toHexString(0x0.001p-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("0x1.0p-126", Float.toHexString((float)Math.pow(2, -126)));
|
||||||
assertEquals("0x0.001p-126", Float.toHexString(0x0.001p-126f));
|
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(0xFFFFFFFF, Integer.reverse(0xFFFFFFFF));
|
||||||
assertEquals(0xF63BA000, Integer.reverse(0x5DC6F));
|
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