mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fix bugs
This commit is contained in:
parent
1ae683ead3
commit
bb4040af23
|
@ -15,8 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.interop.Async;
|
import org.teavm.interop.Async;
|
||||||
|
import org.teavm.interop.DelegateTo;
|
||||||
import org.teavm.interop.Rename;
|
import org.teavm.interop.Rename;
|
||||||
|
import org.teavm.interop.Structure;
|
||||||
import org.teavm.interop.Superclass;
|
import org.teavm.interop.Superclass;
|
||||||
import org.teavm.interop.Sync;
|
import org.teavm.interop.Sync;
|
||||||
import org.teavm.jso.browser.TimerHandler;
|
import org.teavm.jso.browser.TimerHandler;
|
||||||
|
@ -25,6 +28,11 @@ import org.teavm.platform.PlatformObject;
|
||||||
import org.teavm.platform.PlatformQueue;
|
import org.teavm.platform.PlatformQueue;
|
||||||
import org.teavm.platform.PlatformRunnable;
|
import org.teavm.platform.PlatformRunnable;
|
||||||
import org.teavm.platform.async.AsyncCallback;
|
import org.teavm.platform.async.AsyncCallback;
|
||||||
|
import org.teavm.runtime.Allocator;
|
||||||
|
import org.teavm.runtime.RuntimeArray;
|
||||||
|
import org.teavm.runtime.RuntimeClass;
|
||||||
|
import org.teavm.runtime.RuntimeJavaObject;
|
||||||
|
import org.teavm.runtime.RuntimeObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -191,6 +199,7 @@ public class TObject {
|
||||||
return getClass().getName() + "@" + TInteger.toHexString(identity());
|
return getClass().getName() + "@" + TInteger.toHexString(identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DelegateTo("identityLowLevel")
|
||||||
int identity() {
|
int identity() {
|
||||||
PlatformObject platformThis = Platform.getPlatformObject(this);
|
PlatformObject platformThis = Platform.getPlatformObject(this);
|
||||||
if (platformThis.getId() == 0) {
|
if (platformThis.getId() == 0) {
|
||||||
|
@ -199,7 +208,24 @@ public class TObject {
|
||||||
return Platform.getPlatformObject(this).getId();
|
return Platform.getPlatformObject(this).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static int identityLowLevel(RuntimeJavaObject object) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@DelegateTo("cloneLowLevel")
|
||||||
protected Object clone() throws TCloneNotSupportedException {
|
protected Object clone() throws TCloneNotSupportedException {
|
||||||
if (!(this instanceof TCloneable) && Platform.getPlatformObject(this)
|
if (!(this instanceof TCloneable) && Platform.getPlatformObject(this)
|
||||||
.getPlatformClass().getMetadata().getArrayItem() == null) {
|
.getPlatformClass().getMetadata().getArrayItem() == null) {
|
||||||
|
@ -210,6 +236,28 @@ public class TObject {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static RuntimeJavaObject cloneLowLevel(RuntimeJavaObject self) {
|
||||||
|
RuntimeClass cls = RuntimeClass.getClass(self);
|
||||||
|
int skip = Structure.sizeOf(RuntimeJavaObject.class);
|
||||||
|
int size;
|
||||||
|
RuntimeJavaObject copy;
|
||||||
|
if (cls.itemType == null) {
|
||||||
|
copy = Allocator.allocate(cls).toStructure();
|
||||||
|
size = cls.size;
|
||||||
|
} else {
|
||||||
|
RuntimeArray array = (RuntimeArray) self;
|
||||||
|
copy = Allocator.allocateArray(cls, array.size).toStructure();
|
||||||
|
int itemSize = (cls.itemType.flags & RuntimeClass.PRIMITIVE) == 0 ? 4 : cls.itemType.size;
|
||||||
|
Address headerSize = Address.align(Address.fromInt(Structure.sizeOf(RuntimeArray.class)), itemSize);
|
||||||
|
size = itemSize * array.size + headerSize.toInt();
|
||||||
|
}
|
||||||
|
if (size > skip) {
|
||||||
|
Allocator.moveMemoryBlock(self.toAddress().add(skip), copy.toAddress().add(skip), size - skip);
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
@Sync
|
@Sync
|
||||||
@Rename("notify")
|
@Rename("notify")
|
||||||
public final void notify0() {
|
public final void notify0() {
|
||||||
|
|
|
@ -33,6 +33,7 @@ public final class Example {
|
||||||
testHashCode();
|
testHashCode();
|
||||||
testArrayList();
|
testArrayList();
|
||||||
testArrayCopy();
|
testArrayCopy();
|
||||||
|
testArrayIsObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testFibonacci() {
|
private static void testFibonacci() {
|
||||||
|
@ -121,6 +122,15 @@ public final class Example {
|
||||||
println(sb.toString());
|
println(sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void testArrayIsObject() {
|
||||||
|
byte[] array = new byte[] { 1, 2, 3 };
|
||||||
|
byte[] copy = array.clone();
|
||||||
|
println("array.hashCode() = " + array.hashCode());
|
||||||
|
println("copy.hashCode() = " + copy.hashCode());
|
||||||
|
println("array.equals(array) = " + array.equals(array));
|
||||||
|
println("array.equals(copy) = " + array.equals(copy));
|
||||||
|
}
|
||||||
|
|
||||||
private static Base instance(int index) {
|
private static Base instance(int index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.teavm.backend.wasm.generate.WasmClassGenerator;
|
||||||
import org.teavm.backend.wasm.generate.WasmDependencyListener;
|
import org.teavm.backend.wasm.generate.WasmDependencyListener;
|
||||||
import org.teavm.backend.wasm.generate.WasmGenerationContext;
|
import org.teavm.backend.wasm.generate.WasmGenerationContext;
|
||||||
import org.teavm.backend.wasm.generate.WasmGenerator;
|
import org.teavm.backend.wasm.generate.WasmGenerator;
|
||||||
|
import org.teavm.backend.wasm.generate.WasmGeneratorUtil;
|
||||||
import org.teavm.backend.wasm.generate.WasmMangling;
|
import org.teavm.backend.wasm.generate.WasmMangling;
|
||||||
import org.teavm.backend.wasm.generate.WasmStringPool;
|
import org.teavm.backend.wasm.generate.WasmStringPool;
|
||||||
import org.teavm.backend.wasm.intrinsics.AddressIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.AddressIntrinsic;
|
||||||
|
@ -43,13 +44,16 @@ import org.teavm.backend.wasm.intrinsics.PlatformObjectIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.StructureIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.StructureIntrinsic;
|
||||||
import org.teavm.backend.wasm.intrinsics.WasmRuntimeIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.WasmRuntimeIntrinsic;
|
||||||
import org.teavm.backend.wasm.model.WasmFunction;
|
import org.teavm.backend.wasm.model.WasmFunction;
|
||||||
|
import org.teavm.backend.wasm.model.WasmLocal;
|
||||||
import org.teavm.backend.wasm.model.WasmMemorySegment;
|
import org.teavm.backend.wasm.model.WasmMemorySegment;
|
||||||
import org.teavm.backend.wasm.model.WasmModule;
|
import org.teavm.backend.wasm.model.WasmModule;
|
||||||
import org.teavm.backend.wasm.model.WasmType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmDrop;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt32Subtype;
|
import org.teavm.backend.wasm.model.expression.WasmInt32Subtype;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
|
@ -59,7 +63,6 @@ import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
import org.teavm.backend.wasm.patches.ClassPatch;
|
import org.teavm.backend.wasm.patches.ClassPatch;
|
||||||
import org.teavm.backend.wasm.patches.ObjectPatch;
|
|
||||||
import org.teavm.backend.wasm.render.WasmCRenderer;
|
import org.teavm.backend.wasm.render.WasmCRenderer;
|
||||||
import org.teavm.dependency.ClassDependency;
|
import org.teavm.dependency.ClassDependency;
|
||||||
import org.teavm.dependency.DependencyChecker;
|
import org.teavm.dependency.DependencyChecker;
|
||||||
|
@ -124,7 +127,6 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
@Override
|
@Override
|
||||||
public List<ClassHolderTransformer> getTransformers() {
|
public List<ClassHolderTransformer> getTransformers() {
|
||||||
List<ClassHolderTransformer> transformers = new ArrayList<>();
|
List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||||
transformers.add(new ObjectPatch());
|
|
||||||
transformers.add(new ClassPatch());
|
transformers.add(new ClassPatch());
|
||||||
transformers.add(new WasmDependencyListener());
|
transformers.add(new WasmDependencyListener());
|
||||||
return transformers;
|
return transformers;
|
||||||
|
@ -257,7 +259,11 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
if (implementor.getProgram() == null || implementor.getProgram().basicBlockCount() == 0) {
|
if (implementor.getProgram() == null || implementor.getProgram().basicBlockCount() == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
module.add(generator.generate(method.getReference(), implementor));
|
if (method == implementor) {
|
||||||
|
module.add(generator.generate(method.getReference(), implementor));
|
||||||
|
} else {
|
||||||
|
module.add(generateStub(method, implementor));
|
||||||
|
}
|
||||||
if (controller.wasCancelled()) {
|
if (controller.wasCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -328,6 +334,33 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WasmFunction generateStub(MethodHolder method, MethodHolder implementor) {
|
||||||
|
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(method.getReference()));
|
||||||
|
if (!method.hasModifier(ElementModifier.STATIC)) {
|
||||||
|
function.getParameters().add(WasmType.INT32);
|
||||||
|
}
|
||||||
|
ValueType[] parameterTypes = method.getParameterTypes();
|
||||||
|
for (ValueType parameterType : parameterTypes) {
|
||||||
|
function.getParameters().add(WasmGeneratorUtil.mapType(parameterType));
|
||||||
|
}
|
||||||
|
|
||||||
|
WasmCall call = new WasmCall(WasmMangling.mangleMethod(implementor.getReference()));
|
||||||
|
for (WasmType param : function.getParameters()) {
|
||||||
|
WasmLocal local = new WasmLocal(param);
|
||||||
|
function.add(local);
|
||||||
|
call.getArguments().add(new WasmGetLocal(local));
|
||||||
|
}
|
||||||
|
|
||||||
|
function.setResult(WasmGeneratorUtil.mapType(method.getResultType()));
|
||||||
|
|
||||||
|
if (method.getResultType() == ValueType.VOID) {
|
||||||
|
function.getBody().add(new WasmDrop(call));
|
||||||
|
} else {
|
||||||
|
function.getBody().add(new WasmReturn(call));
|
||||||
|
}
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
private void renderClinit(ListableClassReaderSource classes, WasmClassGenerator classGenerator,
|
private void renderClinit(ListableClassReaderSource classes, WasmClassGenerator classGenerator,
|
||||||
WasmModule module) {
|
WasmModule module) {
|
||||||
for (String className : classes.getClassNames()) {
|
for (String className : classes.getClassNames()) {
|
||||||
|
|
|
@ -123,11 +123,20 @@ public class WasmClassGenerator {
|
||||||
addClass(itemType);
|
addClass(itemType);
|
||||||
ClassBinaryData itemBinaryData = binaryDataMap.get(itemType);
|
ClassBinaryData itemBinaryData = binaryDataMap.get(itemType);
|
||||||
|
|
||||||
|
VirtualTable vtable = vtableProvider.lookup("java.lang.Object");
|
||||||
|
int vtableSize = vtable != null ? vtable.getEntries().size() : 0;
|
||||||
|
DataType arrayType = new DataArray(DataPrimitives.INT, vtableSize);
|
||||||
|
DataValue wrapper = new DataStructure((byte) 0, classStructure, arrayType).createValue();
|
||||||
|
|
||||||
|
if (vtableSize > 0) {
|
||||||
|
fillVirtualTable(vtable, wrapper.getValue(1));
|
||||||
|
}
|
||||||
|
|
||||||
binaryData.size = 4;
|
binaryData.size = 4;
|
||||||
binaryData.data = classStructure.createValue();
|
binaryData.data = wrapper.getValue(0);
|
||||||
binaryData.data.setInt(1, 4);
|
binaryData.data.setInt(1, 4);
|
||||||
binaryData.data.setAddress(5, itemBinaryData.start);
|
binaryData.data.setAddress(5, itemBinaryData.start);
|
||||||
binaryData.start = binaryWriter.append(binaryData.data);
|
binaryData.start = binaryWriter.append(vtableSize > 0 ? wrapper : binaryData.data);
|
||||||
|
|
||||||
itemBinaryData.data.setAddress(6, binaryData.start);
|
itemBinaryData.data.setAddress(6, binaryData.start);
|
||||||
}
|
}
|
||||||
|
@ -161,10 +170,15 @@ public class WasmClassGenerator {
|
||||||
int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0);
|
int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0);
|
||||||
header.setInt(3, tag);
|
header.setInt(3, tag);
|
||||||
header.setInt(4, RuntimeClass.computeCanary(binaryData.size, tag));
|
header.setInt(4, RuntimeClass.computeCanary(binaryData.size, tag));
|
||||||
if (vtable == null) {
|
|
||||||
return header;
|
if (vtable != null) {
|
||||||
|
fillVirtualTable(vtable, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return vtable != null ? wrapper : header;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillVirtualTable(VirtualTable vtable, DataValue array) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (VirtualTableEntry vtableEntry : vtable.getEntries().values()) {
|
for (VirtualTableEntry vtableEntry : vtable.getEntries().values()) {
|
||||||
int methodIndex;
|
int methodIndex;
|
||||||
|
@ -180,8 +194,6 @@ public class WasmClassGenerator {
|
||||||
|
|
||||||
array.setInt(index++, methodIndex);
|
array.setInt(index++, methodIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wrapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getClassPointer(ValueType type) {
|
public int getClassPointer(ValueType type) {
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class ClassPatch implements ClassHolderTransformer {
|
||||||
if (!cls.getName().equals("java.lang.Class")) {
|
if (!cls.getName().equals("java.lang.Class")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MethodHolder method : cls.getMethods()) {
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
patchProgram(method.getProgram());
|
patchProgram(method.getProgram());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.backend.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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -121,7 +121,7 @@ public class WasmCRenderer {
|
||||||
indent();
|
indent();
|
||||||
for (int i = 0; i < module.getFunctionTable().size() - 1; ++i) {
|
for (int i = 0; i < module.getFunctionTable().size() - 1; ++i) {
|
||||||
WasmFunction function = module.getFunctionTable().get(i);
|
WasmFunction function = module.getFunctionTable().get(i);
|
||||||
line(function.getName() + ",");
|
line((function != null ? function.getName() : "unknown") + ",");
|
||||||
}
|
}
|
||||||
line(module.getFunctionTable().get(module.getFunctionTable().size() - 1).getName());
|
line(module.getFunctionTable().get(module.getFunctionTable().size() - 1).getName());
|
||||||
outdent();
|
outdent();
|
||||||
|
|
|
@ -643,6 +643,11 @@ class DependencyGraphBuilder {
|
||||||
arrayNode.addConsumer(receiverNode::propagate);
|
arrayNode.addConsumer(receiverNode::propagate);
|
||||||
arrayNode.getArrayItem().connect(receiverNode.getArrayItem());
|
arrayNode.getArrayItem().connect(receiverNode.getArrayItem());
|
||||||
}
|
}
|
||||||
|
MethodDependency cloneDep = dependencyChecker.linkMethod(
|
||||||
|
new MethodReference(Object.class, "clone", Object.class),
|
||||||
|
new CallLocation(caller.getMethod(), currentLocation));
|
||||||
|
arrayNode.connect(cloneDep.getVariable(0));
|
||||||
|
cloneDep.use();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue
Block a user