Wasm: fix bugs

This commit is contained in:
Alexey Andreev 2019-05-23 23:38:10 +03:00
parent 871e9a0113
commit 28c0cc6ef2
7 changed files with 120 additions and 49 deletions

View File

@ -518,7 +518,8 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
for (String className : classes.getClassNames()) {
ClassHolder cls = classes.get(className);
for (MethodHolder method : cls.getMethods()) {
if (context.getIntrinsic(method.getReference()) != null) {
if (method.hasModifier(ElementModifier.ABSTRACT)
|| context.getIntrinsic(method.getReference()) != null) {
continue;
}
module.add(generator.generateDefinition(method.getReference()));

View File

@ -15,10 +15,11 @@
*/
package org.teavm.backend.wasm.generate;
import com.carrotsearch.hppc.ObjectIntHashMap;
import com.carrotsearch.hppc.ObjectIntMap;
import java.util.ArrayList;
import java.util.HashMap;
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.DataPrimitives;
import org.teavm.backend.wasm.binary.DataStructure;
@ -29,28 +30,31 @@ import org.teavm.model.lowlevel.CallSiteLocation;
import org.teavm.model.lowlevel.ExceptionHandlerDescriptor;
public class CallSiteBinaryGenerator {
private static final int CALL_SITE_HANDLER_COUNT = 0;
private static final int CALL_SITE_FIRST_HANDLER = 1;
private static final int CALL_SITE_LOCATION = 2;
private static final int CALL_SITE_FIRST_HANDLER = 0;
private static final int CALL_SITE_LOCATION = 1;
private static final int EXCEPTION_HANDLER_ID = 0;
private static final int EXCEPTION_HANDLER_CLASS = 1;
private static final int LOCATION_FILE = 0;
private static final int LOCATION_CLASS = 1;
private static final int LOCATION_METHOD = 2;
private static final int LOCATION_LINE_NUMBER = 3;
private static final int EXCEPTION_HANDLER_NEXT = 2;
private static final int LOCATION_METHOD = 0;
private static final int LOCATION_LINE = 1;
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,
DataPrimitives.INT,
DataPrimitives.ADDRESS,
DataPrimitives.ADDRESS);
private DataStructure exceptionHandlerStructure = new DataStructure((byte) 0,
DataPrimitives.INT,
DataPrimitives.ADDRESS,
DataPrimitives.ADDRESS);
private DataStructure locationStructure = new DataStructure((byte) 0,
DataPrimitives.ADDRESS,
DataPrimitives.ADDRESS,
DataPrimitives.ADDRESS,
DataPrimitives.INT);
private DataStructure methodLocationStructure = new DataStructure((byte) 0,
DataPrimitives.ADDRESS,
DataPrimitives.ADDRESS,
DataPrimitives.ADDRESS);
private BinaryWriter writer;
private WasmClassGenerator classGenerator;
@ -78,12 +82,12 @@ public class CallSiteBinaryGenerator {
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) {
DataValue binaryCallSite = binaryCallSites.get(callSiteId);
CallSiteDescriptor callSite = callSites.get(callSiteId);
binaryCallSite.setInt(CALL_SITE_HANDLER_COUNT, callSite.getHandlers().size());
boolean firstHandlerSet = false;
List<DataValue> binaryExceptionHandlers = new ArrayList<>();
@ -98,6 +102,9 @@ public class CallSiteBinaryGenerator {
binaryCallSite.setAddress(CALL_SITE_FIRST_HANDLER, address);
firstHandlerSet = true;
}
if (i > 0) {
binaryExceptionHandlers.get(i - 1).setAddress(EXCEPTION_HANDLER_NEXT, address);
}
}
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();
int address = writer.append(binaryLocation);
locationAddress = writer.append(binaryLocation);
locationCache.put(location, locationAddress);
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) {
binaryLocation.setAddress(LOCATION_FILE, stringPool.getStringPointer(location.getFileName()));
binaryMethodLocation.setAddress(METHOD_LOCATION_FILE,
stringPool.getStringPointer(location.getFileName()));
}
if (location.getClassName() != null) {
binaryLocation.setAddress(LOCATION_CLASS, stringPool.getStringPointer(location.getClassName()));
binaryMethodLocation.setAddress(METHOD_LOCATION_CLASS,
stringPool.getStringPointer(location.getClassName()));
}
if (location.getMethodName() != null) {
binaryLocation.setAddress(LOCATION_METHOD, stringPool.getStringPointer(location.getMethodName()));
binaryMethodLocation.setAddress(METHOD_LOCATION_METHOD,
stringPool.getStringPointer(location.getMethodName()));
}
}
binaryLocation.setAddress(LOCATION_METHOD, methodLocationAddress);
binaryLocation.setInt(LOCATION_LINE, location.getLineNumber());
}
binaryLocation.setInt(LOCATION_LINE_NUMBER, location.getLineNumber());
return address;
});
binaryCallSite.setAddress(CALL_SITE_LOCATION, locationAddress);
}
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);
}
}
}

View File

@ -76,6 +76,8 @@ public class WasmClassGenerator {
DataPrimitives.INT, /* isInstance function */
DataPrimitives.INT, /* init function */
DataPrimitives.ADDRESS, /* parent */
DataPrimitives.INT, /* interface count */
DataPrimitives.ADDRESS, /* interfaces */
DataPrimitives.ADDRESS, /* enum values */
DataPrimitives.ADDRESS, /* layout */
DataPrimitives.ADDRESS /* simple name */);
@ -92,9 +94,9 @@ public class WasmClassGenerator {
private static final int CLASS_IS_INSTANCE = 8;
private static final int CLASS_INIT = 9;
private static final int CLASS_PARENT = 10;
private static final int CLASS_ENUM_VALUES = 11;
private static final int CLASS_LAYOUT = 12;
private static final int CLASS_SIMPLE_NAME = 13;
private static final int CLASS_ENUM_VALUES = 13;
private static final int CLASS_LAYOUT = 14;
private static final int CLASS_SIMPLE_NAME = 15;
public WasmClassGenerator(ClassReaderSource processedClassSource, ClassReaderSource classSource,
VirtualTableProvider vtableProvider, TagRegistry tagRegistry, BinaryWriter binaryWriter,
@ -377,13 +379,13 @@ public class WasmClassGenerator {
private void fillVirtualTable(VirtualTable vtable, DataValue array) {
int index = 0;
List<VirtualTable> tables = new ArrayList<>();
while (vtable != null) {
tables.add(vtable);
vtable = vtable.getParent();
VirtualTable vt = vtable;
while (vt != null) {
tables.add(vt);
vt = vt.getParent();
}
for (int i = tables.size() - 1; i >= 0; --i) {
vtable = tables.get(i);
for (MethodDescriptor method : vtable.getMethods()) {
for (MethodDescriptor method : tables.get(i).getMethods()) {
int methodIndex = -1;
if (method != null) {
VirtualTableEntry entry = vtable.getEntry(method);

View File

@ -110,10 +110,11 @@ import org.teavm.backend.wasm.render.WasmTypeInference;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.interop.Address;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReader;
import org.teavm.model.MethodReference;
import org.teavm.model.TextLocation;
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.RuntimeArray;
import org.teavm.runtime.RuntimeClass;
@ -909,10 +910,12 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
}
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);
if (context.getImportedMethod(expr.getMethod()) != null) {
if (context.getImportedMethod(reference) != null) {
call.setImported(true);
}
for (Expr argument : expr.getArguments()) {
@ -942,23 +945,31 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
result = block;
} else {
MethodReference reference = expr.getMethod();
accept(expr.getArguments().get(0));
WasmExpression instance = result;
WasmBlock block = new WasmBlock(false);
block.setType(WasmGeneratorUtil.mapType(expr.getMethod().getReturnType()));
block.setType(WasmGeneratorUtil.mapType(reference.getReturnType()));
WasmLocal instanceVar = getTemporary(WasmType.INT32);
block.getBody().add(new WasmSetLocal(instanceVar, instance));
instance = new WasmGetLocal(instanceVar);
int vtableOffset = classGenerator.getClassSize(RuntimeClass.class.getName());
VirtualTableEntry vtableEntry = context.getVirtualTableProvider().lookup(expr.getMethod());
if (vtableEntry == null) {
VirtualTable vtable = context.getVirtualTableProvider().lookup(reference.getClassName());
if (vtable != null) {
vtable = vtable.findMethodContainer(reference.getDescriptor());
}
if (vtable == null) {
result = new WasmUnreachable();
return;
}
int vtableIndex = vtable.getMethods().indexOf(reference.getDescriptor());
if (vtable.getParent() != null) {
vtableIndex += vtable.getParent().size();
}
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);
WasmIndirectCall call = new WasmIndirectCall(methodIndex);

View File

@ -333,13 +333,10 @@ public class WasmBinaryRenderer {
WasmBinaryWriter functionsSubsection = new WasmBinaryWriter();
Collection<WasmFunction> functions = module.getFunctions().values();
functions = functions.stream().filter(f -> f.getImportName() != null).collect(Collectors.toList());
functionsSubsection.writeLEB(functions.size());
for (WasmFunction function : functions) {
if (function.getImportName() != null) {
continue;
}
functionsSubsection.writeLEB(functionIndexes.get(function.getName()));
functionsSubsection.writeAsciiString(function.getName());
}

View File

@ -41,3 +41,12 @@ inline static float reinterpret_int32(int32_t v) {
reinterpret_union_32.i = v;
return reinterpret_union_32.f;
}
static void logOutOfMemory() {
abort();
}
static void logString(int32_t v) {
}
static void logInt(int32_t v) {
}

View File

@ -154,7 +154,6 @@
<optimizationLevel>FULL</optimizationLevel>
</configuration>
</execution>
<!--
<execution>
<id>wasm-client</id>
<goals>
@ -169,7 +168,6 @@
<heapSize>8</heapSize>
</configuration>
</execution>
-->
<execution>
<id>native-client</id>
<goals>