mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Wasm: fix bugs
This commit is contained in:
parent
871e9a0113
commit
28c0cc6ef2
|
@ -518,7 +518,8 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
for (String className : classes.getClassNames()) {
|
for (String className : classes.getClassNames()) {
|
||||||
ClassHolder cls = classes.get(className);
|
ClassHolder cls = classes.get(className);
|
||||||
for (MethodHolder method : cls.getMethods()) {
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
if (context.getIntrinsic(method.getReference()) != null) {
|
if (method.hasModifier(ElementModifier.ABSTRACT)
|
||||||
|
|| context.getIntrinsic(method.getReference()) != null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
module.add(generator.generateDefinition(method.getReference()));
|
module.add(generator.generateDefinition(method.getReference()));
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.generate;
|
package org.teavm.backend.wasm.generate;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.ObjectIntHashMap;
|
||||||
|
import com.carrotsearch.hppc.ObjectIntMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Objects;
|
||||||
import org.teavm.backend.wasm.binary.BinaryWriter;
|
import org.teavm.backend.wasm.binary.BinaryWriter;
|
||||||
import org.teavm.backend.wasm.binary.DataPrimitives;
|
import org.teavm.backend.wasm.binary.DataPrimitives;
|
||||||
import org.teavm.backend.wasm.binary.DataStructure;
|
import org.teavm.backend.wasm.binary.DataStructure;
|
||||||
|
@ -29,28 +30,31 @@ import org.teavm.model.lowlevel.CallSiteLocation;
|
||||||
import org.teavm.model.lowlevel.ExceptionHandlerDescriptor;
|
import org.teavm.model.lowlevel.ExceptionHandlerDescriptor;
|
||||||
|
|
||||||
public class CallSiteBinaryGenerator {
|
public class CallSiteBinaryGenerator {
|
||||||
private static final int CALL_SITE_HANDLER_COUNT = 0;
|
private static final int CALL_SITE_FIRST_HANDLER = 0;
|
||||||
private static final int CALL_SITE_FIRST_HANDLER = 1;
|
private static final int CALL_SITE_LOCATION = 1;
|
||||||
private static final int CALL_SITE_LOCATION = 2;
|
|
||||||
private static final int EXCEPTION_HANDLER_ID = 0;
|
private static final int EXCEPTION_HANDLER_ID = 0;
|
||||||
private static final int EXCEPTION_HANDLER_CLASS = 1;
|
private static final int EXCEPTION_HANDLER_CLASS = 1;
|
||||||
private static final int LOCATION_FILE = 0;
|
private static final int EXCEPTION_HANDLER_NEXT = 2;
|
||||||
private static final int LOCATION_CLASS = 1;
|
private static final int LOCATION_METHOD = 0;
|
||||||
private static final int LOCATION_METHOD = 2;
|
private static final int LOCATION_LINE = 1;
|
||||||
private static final int LOCATION_LINE_NUMBER = 3;
|
private static final int METHOD_LOCATION_FILE = 0;
|
||||||
|
private static final int METHOD_LOCATION_CLASS = 1;
|
||||||
|
private static final int METHOD_LOCATION_METHOD = 2;
|
||||||
|
|
||||||
private DataStructure callSiteStructure = new DataStructure((byte) 0,
|
private DataStructure callSiteStructure = new DataStructure((byte) 0,
|
||||||
DataPrimitives.INT,
|
|
||||||
DataPrimitives.ADDRESS,
|
DataPrimitives.ADDRESS,
|
||||||
DataPrimitives.ADDRESS);
|
DataPrimitives.ADDRESS);
|
||||||
private DataStructure exceptionHandlerStructure = new DataStructure((byte) 0,
|
private DataStructure exceptionHandlerStructure = new DataStructure((byte) 0,
|
||||||
DataPrimitives.INT,
|
DataPrimitives.INT,
|
||||||
|
DataPrimitives.ADDRESS,
|
||||||
DataPrimitives.ADDRESS);
|
DataPrimitives.ADDRESS);
|
||||||
private DataStructure locationStructure = new DataStructure((byte) 0,
|
private DataStructure locationStructure = new DataStructure((byte) 0,
|
||||||
DataPrimitives.ADDRESS,
|
|
||||||
DataPrimitives.ADDRESS,
|
|
||||||
DataPrimitives.ADDRESS,
|
DataPrimitives.ADDRESS,
|
||||||
DataPrimitives.INT);
|
DataPrimitives.INT);
|
||||||
|
private DataStructure methodLocationStructure = new DataStructure((byte) 0,
|
||||||
|
DataPrimitives.ADDRESS,
|
||||||
|
DataPrimitives.ADDRESS,
|
||||||
|
DataPrimitives.ADDRESS);
|
||||||
|
|
||||||
private BinaryWriter writer;
|
private BinaryWriter writer;
|
||||||
private WasmClassGenerator classGenerator;
|
private WasmClassGenerator classGenerator;
|
||||||
|
@ -78,12 +82,12 @@ public class CallSiteBinaryGenerator {
|
||||||
binaryCallSites.add(binaryCallSite);
|
binaryCallSites.add(binaryCallSite);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<CallSiteLocation, Integer> locationCache = new HashMap<>();
|
ObjectIntMap<CallSiteLocation> locationCache = new ObjectIntHashMap<>();
|
||||||
|
ObjectIntMap<MethodLocation> methodLocationCache = new ObjectIntHashMap<>();
|
||||||
|
|
||||||
for (int callSiteId = 0; callSiteId < callSites.size(); ++callSiteId) {
|
for (int callSiteId = 0; callSiteId < callSites.size(); ++callSiteId) {
|
||||||
DataValue binaryCallSite = binaryCallSites.get(callSiteId);
|
DataValue binaryCallSite = binaryCallSites.get(callSiteId);
|
||||||
CallSiteDescriptor callSite = callSites.get(callSiteId);
|
CallSiteDescriptor callSite = callSites.get(callSiteId);
|
||||||
binaryCallSite.setInt(CALL_SITE_HANDLER_COUNT, callSite.getHandlers().size());
|
|
||||||
|
|
||||||
boolean firstHandlerSet = false;
|
boolean firstHandlerSet = false;
|
||||||
List<DataValue> binaryExceptionHandlers = new ArrayList<>();
|
List<DataValue> binaryExceptionHandlers = new ArrayList<>();
|
||||||
|
@ -98,6 +102,9 @@ public class CallSiteBinaryGenerator {
|
||||||
binaryCallSite.setAddress(CALL_SITE_FIRST_HANDLER, address);
|
binaryCallSite.setAddress(CALL_SITE_FIRST_HANDLER, address);
|
||||||
firstHandlerSet = true;
|
firstHandlerSet = true;
|
||||||
}
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
binaryExceptionHandlers.get(i - 1).setAddress(EXCEPTION_HANDLER_NEXT, address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < callSite.getHandlers().size(); ++i) {
|
for (int i = 0; i < callSite.getHandlers().size(); ++i) {
|
||||||
|
@ -110,24 +117,70 @@ public class CallSiteBinaryGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int locationAddress = locationCache.computeIfAbsent(callSite.getLocation(), location -> {
|
CallSiteLocation location = callSite.getLocation();
|
||||||
|
int locationAddress = locationCache.getOrDefault(location, -1);
|
||||||
|
if (locationAddress < 0) {
|
||||||
DataValue binaryLocation = locationStructure.createValue();
|
DataValue binaryLocation = locationStructure.createValue();
|
||||||
int address = writer.append(binaryLocation);
|
locationAddress = writer.append(binaryLocation);
|
||||||
if (location.getFileName() != null) {
|
locationCache.put(location, locationAddress);
|
||||||
binaryLocation.setAddress(LOCATION_FILE, stringPool.getStringPointer(location.getFileName()));
|
MethodLocation methodLocation = new MethodLocation(location.getFileName(), location.getClassName(),
|
||||||
|
location.getMethodName());
|
||||||
|
int methodLocationAddress = methodLocationCache.getOrDefault(methodLocation, -1);
|
||||||
|
if (methodLocationAddress < 0) {
|
||||||
|
DataValue binaryMethodLocation = methodLocationStructure.createValue();
|
||||||
|
methodLocationAddress = writer.append(binaryMethodLocation);
|
||||||
|
methodLocationCache.put(methodLocation, methodLocationAddress);
|
||||||
|
if (location.getFileName() != null) {
|
||||||
|
binaryMethodLocation.setAddress(METHOD_LOCATION_FILE,
|
||||||
|
stringPool.getStringPointer(location.getFileName()));
|
||||||
|
}
|
||||||
|
if (location.getClassName() != null) {
|
||||||
|
binaryMethodLocation.setAddress(METHOD_LOCATION_CLASS,
|
||||||
|
stringPool.getStringPointer(location.getClassName()));
|
||||||
|
}
|
||||||
|
if (location.getMethodName() != null) {
|
||||||
|
binaryMethodLocation.setAddress(METHOD_LOCATION_METHOD,
|
||||||
|
stringPool.getStringPointer(location.getMethodName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (location.getClassName() != null) {
|
|
||||||
binaryLocation.setAddress(LOCATION_CLASS, stringPool.getStringPointer(location.getClassName()));
|
binaryLocation.setAddress(LOCATION_METHOD, methodLocationAddress);
|
||||||
}
|
binaryLocation.setInt(LOCATION_LINE, location.getLineNumber());
|
||||||
if (location.getMethodName() != null) {
|
}
|
||||||
binaryLocation.setAddress(LOCATION_METHOD, stringPool.getStringPointer(location.getMethodName()));
|
|
||||||
}
|
|
||||||
binaryLocation.setInt(LOCATION_LINE_NUMBER, location.getLineNumber());
|
|
||||||
return address;
|
|
||||||
});
|
|
||||||
binaryCallSite.setAddress(CALL_SITE_LOCATION, locationAddress);
|
binaryCallSite.setAddress(CALL_SITE_LOCATION, locationAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstCallSite;
|
return firstCallSite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final static class MethodLocation {
|
||||||
|
final String file;
|
||||||
|
final String className;
|
||||||
|
final String methodName;
|
||||||
|
|
||||||
|
MethodLocation(String file, String className, String methodName) {
|
||||||
|
this.file = file;
|
||||||
|
this.className = className;
|
||||||
|
this.methodName = methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof MethodLocation)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MethodLocation that = (MethodLocation) o;
|
||||||
|
return Objects.equals(file, that.file)
|
||||||
|
&& Objects.equals(className, that.className)
|
||||||
|
&& Objects.equals(methodName, that.methodName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(file, className, methodName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,8 @@ public class WasmClassGenerator {
|
||||||
DataPrimitives.INT, /* isInstance function */
|
DataPrimitives.INT, /* isInstance function */
|
||||||
DataPrimitives.INT, /* init function */
|
DataPrimitives.INT, /* init function */
|
||||||
DataPrimitives.ADDRESS, /* parent */
|
DataPrimitives.ADDRESS, /* parent */
|
||||||
|
DataPrimitives.INT, /* interface count */
|
||||||
|
DataPrimitives.ADDRESS, /* interfaces */
|
||||||
DataPrimitives.ADDRESS, /* enum values */
|
DataPrimitives.ADDRESS, /* enum values */
|
||||||
DataPrimitives.ADDRESS, /* layout */
|
DataPrimitives.ADDRESS, /* layout */
|
||||||
DataPrimitives.ADDRESS /* simple name */);
|
DataPrimitives.ADDRESS /* simple name */);
|
||||||
|
@ -92,9 +94,9 @@ public class WasmClassGenerator {
|
||||||
private static final int CLASS_IS_INSTANCE = 8;
|
private static final int CLASS_IS_INSTANCE = 8;
|
||||||
private static final int CLASS_INIT = 9;
|
private static final int CLASS_INIT = 9;
|
||||||
private static final int CLASS_PARENT = 10;
|
private static final int CLASS_PARENT = 10;
|
||||||
private static final int CLASS_ENUM_VALUES = 11;
|
private static final int CLASS_ENUM_VALUES = 13;
|
||||||
private static final int CLASS_LAYOUT = 12;
|
private static final int CLASS_LAYOUT = 14;
|
||||||
private static final int CLASS_SIMPLE_NAME = 13;
|
private static final int CLASS_SIMPLE_NAME = 15;
|
||||||
|
|
||||||
public WasmClassGenerator(ClassReaderSource processedClassSource, ClassReaderSource classSource,
|
public WasmClassGenerator(ClassReaderSource processedClassSource, ClassReaderSource classSource,
|
||||||
VirtualTableProvider vtableProvider, TagRegistry tagRegistry, BinaryWriter binaryWriter,
|
VirtualTableProvider vtableProvider, TagRegistry tagRegistry, BinaryWriter binaryWriter,
|
||||||
|
@ -377,13 +379,13 @@ public class WasmClassGenerator {
|
||||||
private void fillVirtualTable(VirtualTable vtable, DataValue array) {
|
private void fillVirtualTable(VirtualTable vtable, DataValue array) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
List<VirtualTable> tables = new ArrayList<>();
|
List<VirtualTable> tables = new ArrayList<>();
|
||||||
while (vtable != null) {
|
VirtualTable vt = vtable;
|
||||||
tables.add(vtable);
|
while (vt != null) {
|
||||||
vtable = vtable.getParent();
|
tables.add(vt);
|
||||||
|
vt = vt.getParent();
|
||||||
}
|
}
|
||||||
for (int i = tables.size() - 1; i >= 0; --i) {
|
for (int i = tables.size() - 1; i >= 0; --i) {
|
||||||
vtable = tables.get(i);
|
for (MethodDescriptor method : tables.get(i).getMethods()) {
|
||||||
for (MethodDescriptor method : vtable.getMethods()) {
|
|
||||||
int methodIndex = -1;
|
int methodIndex = -1;
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
VirtualTableEntry entry = vtable.getEntry(method);
|
VirtualTableEntry entry = vtable.getEntry(method);
|
||||||
|
|
|
@ -110,10 +110,11 @@ import org.teavm.backend.wasm.render.WasmTypeInference;
|
||||||
import org.teavm.diagnostics.Diagnostics;
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.classes.VirtualTableEntry;
|
import org.teavm.model.classes.VirtualTable;
|
||||||
import org.teavm.runtime.Allocator;
|
import org.teavm.runtime.Allocator;
|
||||||
import org.teavm.runtime.RuntimeArray;
|
import org.teavm.runtime.RuntimeArray;
|
||||||
import org.teavm.runtime.RuntimeClass;
|
import org.teavm.runtime.RuntimeClass;
|
||||||
|
@ -909,10 +910,12 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr.getType() == InvocationType.STATIC || expr.getType() == InvocationType.SPECIAL) {
|
if (expr.getType() == InvocationType.STATIC || expr.getType() == InvocationType.SPECIAL) {
|
||||||
String methodName = context.names.forMethod(expr.getMethod());
|
MethodReader method = context.getClassSource().resolve(expr.getMethod());
|
||||||
|
MethodReference reference = method != null ? method.getReference() : expr.getMethod();
|
||||||
|
String methodName = context.names.forMethod(reference);
|
||||||
|
|
||||||
WasmCall call = new WasmCall(methodName);
|
WasmCall call = new WasmCall(methodName);
|
||||||
if (context.getImportedMethod(expr.getMethod()) != null) {
|
if (context.getImportedMethod(reference) != null) {
|
||||||
call.setImported(true);
|
call.setImported(true);
|
||||||
}
|
}
|
||||||
for (Expr argument : expr.getArguments()) {
|
for (Expr argument : expr.getArguments()) {
|
||||||
|
@ -942,23 +945,31 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
|
|
||||||
result = block;
|
result = block;
|
||||||
} else {
|
} else {
|
||||||
|
MethodReference reference = expr.getMethod();
|
||||||
accept(expr.getArguments().get(0));
|
accept(expr.getArguments().get(0));
|
||||||
WasmExpression instance = result;
|
WasmExpression instance = result;
|
||||||
WasmBlock block = new WasmBlock(false);
|
WasmBlock block = new WasmBlock(false);
|
||||||
block.setType(WasmGeneratorUtil.mapType(expr.getMethod().getReturnType()));
|
block.setType(WasmGeneratorUtil.mapType(reference.getReturnType()));
|
||||||
|
|
||||||
WasmLocal instanceVar = getTemporary(WasmType.INT32);
|
WasmLocal instanceVar = getTemporary(WasmType.INT32);
|
||||||
block.getBody().add(new WasmSetLocal(instanceVar, instance));
|
block.getBody().add(new WasmSetLocal(instanceVar, instance));
|
||||||
instance = new WasmGetLocal(instanceVar);
|
instance = new WasmGetLocal(instanceVar);
|
||||||
|
|
||||||
int vtableOffset = classGenerator.getClassSize(RuntimeClass.class.getName());
|
int vtableOffset = classGenerator.getClassSize(RuntimeClass.class.getName());
|
||||||
VirtualTableEntry vtableEntry = context.getVirtualTableProvider().lookup(expr.getMethod());
|
VirtualTable vtable = context.getVirtualTableProvider().lookup(reference.getClassName());
|
||||||
if (vtableEntry == null) {
|
if (vtable != null) {
|
||||||
|
vtable = vtable.findMethodContainer(reference.getDescriptor());
|
||||||
|
}
|
||||||
|
if (vtable == null) {
|
||||||
result = new WasmUnreachable();
|
result = new WasmUnreachable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int vtableIndex = vtable.getMethods().indexOf(reference.getDescriptor());
|
||||||
|
if (vtable.getParent() != null) {
|
||||||
|
vtableIndex += vtable.getParent().size();
|
||||||
|
}
|
||||||
WasmExpression methodIndex = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
|
WasmExpression methodIndex = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
|
||||||
getReferenceToClass(instance), new WasmInt32Constant(vtableEntry.getIndex() * 4 + vtableOffset));
|
getReferenceToClass(instance), new WasmInt32Constant(vtableIndex * 4 + vtableOffset));
|
||||||
methodIndex = new WasmLoadInt32(4, methodIndex, WasmInt32Subtype.INT32);
|
methodIndex = new WasmLoadInt32(4, methodIndex, WasmInt32Subtype.INT32);
|
||||||
|
|
||||||
WasmIndirectCall call = new WasmIndirectCall(methodIndex);
|
WasmIndirectCall call = new WasmIndirectCall(methodIndex);
|
||||||
|
|
|
@ -333,13 +333,10 @@ public class WasmBinaryRenderer {
|
||||||
|
|
||||||
WasmBinaryWriter functionsSubsection = new WasmBinaryWriter();
|
WasmBinaryWriter functionsSubsection = new WasmBinaryWriter();
|
||||||
Collection<WasmFunction> functions = module.getFunctions().values();
|
Collection<WasmFunction> functions = module.getFunctions().values();
|
||||||
|
functions = functions.stream().filter(f -> f.getImportName() != null).collect(Collectors.toList());
|
||||||
functionsSubsection.writeLEB(functions.size());
|
functionsSubsection.writeLEB(functions.size());
|
||||||
|
|
||||||
for (WasmFunction function : functions) {
|
for (WasmFunction function : functions) {
|
||||||
if (function.getImportName() != null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
functionsSubsection.writeLEB(functionIndexes.get(function.getName()));
|
functionsSubsection.writeLEB(functionIndexes.get(function.getName()));
|
||||||
functionsSubsection.writeAsciiString(function.getName());
|
functionsSubsection.writeAsciiString(function.getName());
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,3 +41,12 @@ inline static float reinterpret_int32(int32_t v) {
|
||||||
reinterpret_union_32.i = v;
|
reinterpret_union_32.i = v;
|
||||||
return reinterpret_union_32.f;
|
return reinterpret_union_32.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void logOutOfMemory() {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void logString(int32_t v) {
|
||||||
|
}
|
||||||
|
static void logInt(int32_t v) {
|
||||||
|
}
|
|
@ -154,7 +154,6 @@
|
||||||
<optimizationLevel>FULL</optimizationLevel>
|
<optimizationLevel>FULL</optimizationLevel>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<!--
|
|
||||||
<execution>
|
<execution>
|
||||||
<id>wasm-client</id>
|
<id>wasm-client</id>
|
||||||
<goals>
|
<goals>
|
||||||
|
@ -169,7 +168,6 @@
|
||||||
<heapSize>8</heapSize>
|
<heapSize>8</heapSize>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
-->
|
|
||||||
<execution>
|
<execution>
|
||||||
<id>native-client</id>
|
<id>native-client</id>
|
||||||
<goals>
|
<goals>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user