mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Add support of Object.hashCode
This commit is contained in:
parent
8c6cf1840b
commit
35b59ed916
|
@ -49,6 +49,7 @@ import org.teavm.javascript.spi.Injector;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.CallLocation;
|
import org.teavm.model.CallLocation;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.InstructionLocation;
|
import org.teavm.model.InstructionLocation;
|
||||||
import org.teavm.model.ListableClassHolderSource;
|
import org.teavm.model.ListableClassHolderSource;
|
||||||
|
@ -82,6 +83,11 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
private final Set<MethodReference> asyncMethods = new HashSet<>();
|
private final Set<MethodReference> asyncMethods = new HashSet<>();
|
||||||
private final Set<MethodReference> asyncFamilyMethods = new HashSet<>();
|
private final Set<MethodReference> asyncFamilyMethods = new HashSet<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ClassHolderTransformer> getTransformers() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setController(TeaVMTargetController controller) {
|
public void setController(TeaVMTargetController controller) {
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.runtime;
|
package org.teavm.runtime;
|
||||||
|
|
||||||
public class RuntimeArray extends RuntimeObject {
|
public class RuntimeArray extends RuntimeJavaObject {
|
||||||
RuntimeObject monitor;
|
|
||||||
int size;
|
int size;
|
||||||
}
|
}
|
||||||
|
|
21
core/src/main/java/org/teavm/runtime/RuntimeJavaObject.java
Normal file
21
core/src/main/java/org/teavm/runtime/RuntimeJavaObject.java
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* 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.runtime;
|
||||||
|
|
||||||
|
public class RuntimeJavaObject extends RuntimeObject {
|
||||||
|
public static int nextId = 1;
|
||||||
|
public RuntimeObject monitor;
|
||||||
|
}
|
|
@ -18,5 +18,8 @@ package org.teavm.runtime;
|
||||||
import org.teavm.interop.Structure;
|
import org.teavm.interop.Structure;
|
||||||
|
|
||||||
public class RuntimeObject extends Structure {
|
public class RuntimeObject extends Structure {
|
||||||
|
public static final int GC_MARKED = 0x80000000;
|
||||||
|
public static final int MONITOR_EXISTS = 0x20000000;
|
||||||
|
|
||||||
public int classReference;
|
public int classReference;
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,10 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for (ClassHolderTransformer transformer : target.getTransformers()) {
|
||||||
|
dependencyChecker.addClassTransformer(transformer);
|
||||||
|
}
|
||||||
|
|
||||||
for (TeaVMHostExtension extension : target.getHostExtensions()) {
|
for (TeaVMHostExtension extension : target.getHostExtensions()) {
|
||||||
for (Class<?> extensionType : getExtensionTypes(extension)) {
|
for (Class<?> extensionType : getExtensionTypes(extension)) {
|
||||||
extensions.put(extensionType, extension);
|
extensions.put(extensionType, extension);
|
||||||
|
|
|
@ -18,10 +18,13 @@ package org.teavm.vm;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.teavm.dependency.DependencyChecker;
|
import org.teavm.dependency.DependencyChecker;
|
||||||
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.ListableClassHolderSource;
|
import org.teavm.model.ListableClassHolderSource;
|
||||||
import org.teavm.vm.spi.TeaVMHostExtension;
|
import org.teavm.vm.spi.TeaVMHostExtension;
|
||||||
|
|
||||||
public interface TeaVMTarget {
|
public interface TeaVMTarget {
|
||||||
|
List<ClassHolderTransformer> getTransformers();
|
||||||
|
|
||||||
void setController(TeaVMTargetController controller);
|
void setController(TeaVMTargetController controller);
|
||||||
|
|
||||||
List<TeaVMHostExtension> getHostExtensions();
|
List<TeaVMHostExtension> getHostExtensions();
|
||||||
|
|
|
@ -60,6 +60,12 @@ public final class Example {
|
||||||
Initialized.foo();
|
Initialized.foo();
|
||||||
Initialized.foo();
|
Initialized.foo();
|
||||||
Initialized.foo();
|
Initialized.foo();
|
||||||
|
|
||||||
|
Object o = new Object();
|
||||||
|
WasmRuntime.print(o.hashCode());
|
||||||
|
WasmRuntime.print(o.hashCode());
|
||||||
|
WasmRuntime.print(new Object().hashCode());
|
||||||
|
WasmRuntime.print(new Object().hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Base instance(int index) {
|
private static Base instance(int index) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -33,6 +34,7 @@ import org.teavm.interop.StaticInit;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.CallLocation;
|
import org.teavm.model.CallLocation;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
|
@ -84,6 +86,7 @@ import org.teavm.wasm.model.expression.WasmIntType;
|
||||||
import org.teavm.wasm.model.expression.WasmLoadInt32;
|
import org.teavm.wasm.model.expression.WasmLoadInt32;
|
||||||
import org.teavm.wasm.model.expression.WasmReturn;
|
import org.teavm.wasm.model.expression.WasmReturn;
|
||||||
import org.teavm.wasm.model.expression.WasmStoreInt32;
|
import org.teavm.wasm.model.expression.WasmStoreInt32;
|
||||||
|
import org.teavm.wasm.patches.ObjectPatch;
|
||||||
import org.teavm.wasm.render.WasmRenderer;
|
import org.teavm.wasm.render.WasmRenderer;
|
||||||
|
|
||||||
public class WasmTarget implements TeaVMTarget {
|
public class WasmTarget implements TeaVMTarget {
|
||||||
|
@ -104,6 +107,13 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ClassHolderTransformer> getTransformers() {
|
||||||
|
List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||||
|
transformers.add(new ObjectPatch());
|
||||||
|
return transformers;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contributeDependencies(DependencyChecker dependencyChecker) {
|
public void contributeDependencies(DependencyChecker dependencyChecker) {
|
||||||
for (Class type : Arrays.asList(int.class, long.class, float.class, double.class)) {
|
for (Class type : Arrays.asList(int.class, long.class, float.class, double.class)) {
|
||||||
|
|
|
@ -62,9 +62,7 @@ import org.teavm.ast.UnwrapArrayExpr;
|
||||||
import org.teavm.ast.VariableExpr;
|
import org.teavm.ast.VariableExpr;
|
||||||
import org.teavm.ast.WhileStatement;
|
import org.teavm.ast.WhileStatement;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.model.ClassReader;
|
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodDescriptor;
|
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.classes.TagRegistry;
|
import org.teavm.model.classes.TagRegistry;
|
||||||
|
@ -111,6 +109,7 @@ import org.teavm.wasm.model.expression.WasmStoreFloat64;
|
||||||
import org.teavm.wasm.model.expression.WasmStoreInt32;
|
import org.teavm.wasm.model.expression.WasmStoreInt32;
|
||||||
import org.teavm.wasm.model.expression.WasmStoreInt64;
|
import org.teavm.wasm.model.expression.WasmStoreInt64;
|
||||||
import org.teavm.wasm.model.expression.WasmSwitch;
|
import org.teavm.wasm.model.expression.WasmSwitch;
|
||||||
|
import org.teavm.wasm.model.expression.WasmUnreachable;
|
||||||
|
|
||||||
class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
private WasmGenerationContext context;
|
private WasmGenerationContext context;
|
||||||
|
@ -735,6 +734,23 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
call.getArguments().add(result);
|
call.getArguments().add(result);
|
||||||
}
|
}
|
||||||
result = call;
|
result = call;
|
||||||
|
} else if (expr.getType() == InvocationType.CONSTRUCTOR) {
|
||||||
|
WasmBlock block = new WasmBlock(false);
|
||||||
|
WasmLocal tmp = function.getLocalVariables().get(getTemporaryInt32());
|
||||||
|
block.getBody().add(new WasmSetLocal(tmp, allocateObject(expr.getMethod().getClassName())));
|
||||||
|
|
||||||
|
String methodName = WasmMangling.mangleMethod(expr.getMethod());
|
||||||
|
WasmCall call = new WasmCall(methodName);
|
||||||
|
call.getArguments().add(new WasmGetLocal(tmp));
|
||||||
|
for (Expr argument : expr.getArguments()) {
|
||||||
|
argument.acceptVisitor(this);
|
||||||
|
call.getArguments().add(result);
|
||||||
|
}
|
||||||
|
block.getBody().add(call);
|
||||||
|
|
||||||
|
block.getBody().add(new WasmGetLocal(tmp));
|
||||||
|
|
||||||
|
result = block;
|
||||||
} else {
|
} else {
|
||||||
expr.getArguments().get(0).acceptVisitor(this);
|
expr.getArguments().get(0).acceptVisitor(this);
|
||||||
WasmExpression instance = result;
|
WasmExpression instance = result;
|
||||||
|
@ -860,12 +876,16 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NewExpr expr) {
|
public void visit(NewExpr expr) {
|
||||||
int tag = classGenerator.getClassPointer(ValueType.object(expr.getConstructedClass()));
|
result = allocateObject(expr.getConstructedClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmExpression allocateObject(String className) {
|
||||||
|
int tag = classGenerator.getClassPointer(ValueType.object(className));
|
||||||
String allocName = WasmMangling.mangleMethod(new MethodReference(Allocator.class, "allocate",
|
String allocName = WasmMangling.mangleMethod(new MethodReference(Allocator.class, "allocate",
|
||||||
RuntimeClass.class, Address.class));
|
RuntimeClass.class, Address.class));
|
||||||
WasmCall call = new WasmCall(allocName);
|
WasmCall call = new WasmCall(allocName);
|
||||||
call.getArguments().add(new WasmInt32Constant(tag));
|
call.getArguments().add(new WasmInt32Constant(tag));
|
||||||
result = call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -952,7 +972,13 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ThrowStatement statement) {
|
public void visit(ThrowStatement statement) {
|
||||||
|
WasmBlock block = new WasmBlock(false);
|
||||||
|
statement.getException().acceptVisitor(this);
|
||||||
|
block.getBody().add(result);
|
||||||
|
|
||||||
|
block.getBody().add(new WasmUnreachable());
|
||||||
|
|
||||||
|
result = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -53,6 +53,7 @@ public class WasmAddressIntrinsic implements WasmIntrinsic {
|
||||||
return new WasmConversion(WasmType.INT32, WasmType.INT64, false, value);
|
return new WasmConversion(WasmType.INT32, WasmType.INT64, false, value);
|
||||||
}
|
}
|
||||||
case "fromInt":
|
case "fromInt":
|
||||||
|
case "ofObject":
|
||||||
return manager.generate(invocation.getArguments().get(0));
|
return manager.generate(invocation.getArguments().get(0));
|
||||||
case "fromLong": {
|
case "fromLong": {
|
||||||
WasmExpression value = manager.generate(invocation.getArguments().get(0));
|
WasmExpression value = manager.generate(invocation.getArguments().get(0));
|
||||||
|
|
59
core/src/main/java/org/teavm/wasm/patches/ObjectPatch.java
Normal file
59
core/src/main/java/org/teavm/wasm/patches/ObjectPatch.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* 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.wasm.patches;
|
||||||
|
|
||||||
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
|
import org.teavm.interop.Address;
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
import org.teavm.model.Program;
|
||||||
|
import org.teavm.model.util.ProgramUtils;
|
||||||
|
import org.teavm.runtime.RuntimeJavaObject;
|
||||||
|
import org.teavm.runtime.RuntimeObject;
|
||||||
|
|
||||||
|
public class ObjectPatch implements ClassHolderTransformer {
|
||||||
|
@Override
|
||||||
|
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||||
|
if (!cls.getName().equals("java.lang.Object")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodHolder method = cls.getMethod(new MethodDescriptor("identity", int.class));
|
||||||
|
Program patchedProgram = ProgramUtils.copy(innerSource.get(ObjectPatch.class.getName())
|
||||||
|
.getMethod(new MethodDescriptor("patchedIdentity", int.class)).getProgram());
|
||||||
|
method.setProgram(patchedProgram);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private int patchedIdentity() {
|
||||||
|
RuntimeJavaObject object = Address.ofObject(this).toStructure();
|
||||||
|
if ((object.classReference & RuntimeObject.MONITOR_EXISTS) != 0) {
|
||||||
|
object = (RuntimeJavaObject) object.monitor;
|
||||||
|
}
|
||||||
|
int result = object.monitor.toAddress().toInt();
|
||||||
|
if (result == 0) {
|
||||||
|
result = RuntimeJavaObject.nextId++;
|
||||||
|
if (result == 0) {
|
||||||
|
result = RuntimeJavaObject.nextId++;
|
||||||
|
}
|
||||||
|
object.monitor = Address.fromInt(result).toStructure();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,4 +57,6 @@ public final class Address {
|
||||||
public static native Address fromInt(int value);
|
public static native Address fromInt(int value);
|
||||||
|
|
||||||
public static native Address fromLong(long value);
|
public static native Address fromLong(long value);
|
||||||
|
|
||||||
|
public static native Address ofObject(Object obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,6 @@ package org.teavm.interop;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
|
@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
|
||||||
public @interface Rename {
|
public @interface Rename {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user