mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Fix bugs
This commit is contained in:
parent
1ae683ead3
commit
bb4040af23
|
@ -15,8 +15,11 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Async;
|
||||
import org.teavm.interop.DelegateTo;
|
||||
import org.teavm.interop.Rename;
|
||||
import org.teavm.interop.Structure;
|
||||
import org.teavm.interop.Superclass;
|
||||
import org.teavm.interop.Sync;
|
||||
import org.teavm.jso.browser.TimerHandler;
|
||||
|
@ -25,6 +28,11 @@ import org.teavm.platform.PlatformObject;
|
|||
import org.teavm.platform.PlatformQueue;
|
||||
import org.teavm.platform.PlatformRunnable;
|
||||
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());
|
||||
}
|
||||
|
||||
@DelegateTo("identityLowLevel")
|
||||
int identity() {
|
||||
PlatformObject platformThis = Platform.getPlatformObject(this);
|
||||
if (platformThis.getId() == 0) {
|
||||
|
@ -199,7 +208,24 @@ public class TObject {
|
|||
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
|
||||
@DelegateTo("cloneLowLevel")
|
||||
protected Object clone() throws TCloneNotSupportedException {
|
||||
if (!(this instanceof TCloneable) && Platform.getPlatformObject(this)
|
||||
.getPlatformClass().getMetadata().getArrayItem() == null) {
|
||||
|
@ -210,6 +236,28 @@ public class TObject {
|
|||
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
|
||||
@Rename("notify")
|
||||
public final void notify0() {
|
||||
|
|
|
@ -33,6 +33,7 @@ public final class Example {
|
|||
testHashCode();
|
||||
testArrayList();
|
||||
testArrayCopy();
|
||||
testArrayIsObject();
|
||||
}
|
||||
|
||||
private static void testFibonacci() {
|
||||
|
@ -121,6 +122,15 @@ public final class Example {
|
|||
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) {
|
||||
switch (index) {
|
||||
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.WasmGenerationContext;
|
||||
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.WasmStringPool;
|
||||
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.WasmRuntimeIntrinsic;
|
||||
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.WasmModule;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||
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.WasmGetLocal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmInt32Subtype;
|
||||
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.WasmStoreInt32;
|
||||
import org.teavm.backend.wasm.patches.ClassPatch;
|
||||
import org.teavm.backend.wasm.patches.ObjectPatch;
|
||||
import org.teavm.backend.wasm.render.WasmCRenderer;
|
||||
import org.teavm.dependency.ClassDependency;
|
||||
import org.teavm.dependency.DependencyChecker;
|
||||
|
@ -124,7 +127,6 @@ public class WasmTarget implements TeaVMTarget {
|
|||
@Override
|
||||
public List<ClassHolderTransformer> getTransformers() {
|
||||
List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||
transformers.add(new ObjectPatch());
|
||||
transformers.add(new ClassPatch());
|
||||
transformers.add(new WasmDependencyListener());
|
||||
return transformers;
|
||||
|
@ -257,7 +259,11 @@ public class WasmTarget implements TeaVMTarget {
|
|||
if (implementor.getProgram() == null || implementor.getProgram().basicBlockCount() == 0) {
|
||||
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()) {
|
||||
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,
|
||||
WasmModule module) {
|
||||
for (String className : classes.getClassNames()) {
|
||||
|
|
|
@ -123,11 +123,20 @@ public class WasmClassGenerator {
|
|||
addClass(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.data = classStructure.createValue();
|
||||
binaryData.data = wrapper.getValue(0);
|
||||
binaryData.data.setInt(1, 4);
|
||||
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);
|
||||
}
|
||||
|
@ -161,10 +170,15 @@ public class WasmClassGenerator {
|
|||
int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0);
|
||||
header.setInt(3, 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;
|
||||
for (VirtualTableEntry vtableEntry : vtable.getEntries().values()) {
|
||||
int methodIndex;
|
||||
|
@ -180,8 +194,6 @@ public class WasmClassGenerator {
|
|||
|
||||
array.setInt(index++, methodIndex);
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
public int getClassPointer(ValueType type) {
|
||||
|
|
|
@ -37,7 +37,6 @@ public class ClassPatch implements ClassHolderTransformer {
|
|||
if (!cls.getName().equals("java.lang.Class")) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
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();
|
||||
for (int i = 0; i < module.getFunctionTable().size() - 1; ++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());
|
||||
outdent();
|
||||
|
|
|
@ -643,6 +643,11 @@ class DependencyGraphBuilder {
|
|||
arrayNode.addConsumer(receiverNode::propagate);
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue
Block a user