mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 08:34:11 -08:00
Add support for Class.isAssignableFrom
This commit is contained in:
parent
bb4040af23
commit
26749150f6
|
@ -18,6 +18,7 @@ package org.teavm.backend.wasm;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
public final class Example {
|
public final class Example {
|
||||||
private Example() {
|
private Example() {
|
||||||
|
@ -34,6 +35,7 @@ public final class Example {
|
||||||
testArrayList();
|
testArrayList();
|
||||||
testArrayCopy();
|
testArrayCopy();
|
||||||
testArrayIsObject();
|
testArrayIsObject();
|
||||||
|
testIsAssignableFrom();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testFibonacci() {
|
private static void testFibonacci() {
|
||||||
|
@ -131,6 +133,15 @@ public final class Example {
|
||||||
println("array.equals(copy) = " + array.equals(copy));
|
println("array.equals(copy) = " + array.equals(copy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void testIsAssignableFrom() {
|
||||||
|
println("Object.isAssignableFrom(byte[]) = " + Object.class.isAssignableFrom(new byte[0].getClass()));
|
||||||
|
println("Object[].isAssignableFrom(Integer[]) = " + Object[].class.isAssignableFrom(new Integer[0].getClass()));
|
||||||
|
println("Object[].isAssignableFrom(Integer) = " + Object[].class.isAssignableFrom(Integer.class));
|
||||||
|
println("byte[].isAssignableFrom(Object) = " + byte[].class.isAssignableFrom(ValueType.Object.class));
|
||||||
|
println("Base.isAssignableFrom(Derived1) = " + Base.class.isAssignableFrom(Derived1.class));
|
||||||
|
println("Base.isAssignableFrom(A) = " + Base.class.isAssignableFrom(A.class));
|
||||||
|
}
|
||||||
|
|
||||||
private static Base instance(int index) {
|
private static Base instance(int index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -51,6 +52,7 @@ 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.WasmConditional;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmDrop;
|
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.WasmGetLocal;
|
||||||
|
@ -61,6 +63,7 @@ import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmLoadInt32;
|
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.WasmSetLocal;
|
||||||
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.render.WasmCRenderer;
|
import org.teavm.backend.wasm.render.WasmCRenderer;
|
||||||
|
@ -216,60 +219,8 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
WasmGenerator generator = new WasmGenerator(decompiler, classes, context, classGenerator);
|
WasmGenerator generator = new WasmGenerator(decompiler, classes, context, classGenerator);
|
||||||
|
|
||||||
module.setMemorySize(64);
|
module.setMemorySize(64);
|
||||||
|
generateMethods(classes, context, generator, module);
|
||||||
for (String className : classes.getClassNames()) {
|
generateIsSupertypeFunctions(tagRegistry, module, classGenerator);
|
||||||
ClassHolder cls = classes.get(className);
|
|
||||||
for (MethodHolder method : cls.getMethods()) {
|
|
||||||
if (method.getOwnerName().equals(Allocator.class.getName())
|
|
||||||
&& method.getName().equals("initialize")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (context.getIntrinsic(method.getReference()) != null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodHolder implementor = method;
|
|
||||||
AnnotationHolder delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName());
|
|
||||||
if (delegateAnnot != null) {
|
|
||||||
String methodName = delegateAnnot.getValue("value").getString();
|
|
||||||
boolean found = false;
|
|
||||||
for (MethodHolder candidate : cls.getMethods()) {
|
|
||||||
if (candidate.getName().equals(methodName)) {
|
|
||||||
if (found) {
|
|
||||||
controller.getDiagnostics().error(new CallLocation(method.getReference()),
|
|
||||||
"Method is delegated to " + methodName + " but several implementations "
|
|
||||||
+ "found");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
implementor = candidate;
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (implementor.hasModifier(ElementModifier.NATIVE)) {
|
|
||||||
if (context.getImportedMethod(method.getReference()) == null) {
|
|
||||||
CallLocation location = new CallLocation(method.getReference());
|
|
||||||
controller.getDiagnostics().error(location, "Method {{m0}} is native but "
|
|
||||||
+ "has no {{c1}} annotation on it", method.getReference(), Import.class.getName());
|
|
||||||
}
|
|
||||||
module.add(generator.generateNative(method.getReference()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (implementor.getProgram() == null || implementor.getProgram().basicBlockCount() == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (method == implementor) {
|
|
||||||
module.add(generator.generate(method.getReference(), implementor));
|
|
||||||
} else {
|
|
||||||
module.add(generateStub(method, implementor));
|
|
||||||
}
|
|
||||||
if (controller.wasCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
classGenerator.postProcess();
|
classGenerator.postProcess();
|
||||||
|
|
||||||
WasmMemorySegment dataSegment = new WasmMemorySegment();
|
WasmMemorySegment dataSegment = new WasmMemorySegment();
|
||||||
|
@ -334,6 +285,163 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateMethods(ListableClassHolderSource classes, WasmGenerationContext context,
|
||||||
|
WasmGenerator generator, WasmModule module) {
|
||||||
|
for (String className : classes.getClassNames()) {
|
||||||
|
ClassHolder cls = classes.get(className);
|
||||||
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
|
if (method.getOwnerName().equals(Allocator.class.getName())
|
||||||
|
&& method.getName().equals("initialize")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (context.getIntrinsic(method.getReference()) != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodHolder implementor = method;
|
||||||
|
AnnotationHolder delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName());
|
||||||
|
if (delegateAnnot != null) {
|
||||||
|
String methodName = delegateAnnot.getValue("value").getString();
|
||||||
|
boolean found = false;
|
||||||
|
for (MethodHolder candidate : cls.getMethods()) {
|
||||||
|
if (candidate.getName().equals(methodName)) {
|
||||||
|
if (found) {
|
||||||
|
controller.getDiagnostics().error(new CallLocation(method.getReference()),
|
||||||
|
"Method is delegated to " + methodName + " but several implementations "
|
||||||
|
+ "found");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
implementor = candidate;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (implementor.hasModifier(ElementModifier.NATIVE)) {
|
||||||
|
if (context.getImportedMethod(method.getReference()) == null) {
|
||||||
|
CallLocation location = new CallLocation(method.getReference());
|
||||||
|
controller.getDiagnostics().error(location, "Method {{m0}} is native but "
|
||||||
|
+ "has no {{c1}} annotation on it", method.getReference(), Import.class.getName());
|
||||||
|
}
|
||||||
|
module.add(generator.generateNative(method.getReference()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (implementor.getProgram() == null || implementor.getProgram().basicBlockCount() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (method == implementor) {
|
||||||
|
module.add(generator.generate(method.getReference(), implementor));
|
||||||
|
} else {
|
||||||
|
module.add(generateStub(method, implementor));
|
||||||
|
}
|
||||||
|
if (controller.wasCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateIsSupertypeFunctions(TagRegistry tagRegistry, WasmModule module,
|
||||||
|
WasmClassGenerator classGenerator) {
|
||||||
|
for (ValueType type : classGenerator.getRegisteredClasses()) {
|
||||||
|
WasmFunction function = new WasmFunction(WasmMangling.mangeIsSupertype(type));
|
||||||
|
function.getParameters().add(WasmType.INT32);
|
||||||
|
function.setResult(WasmType.INT32);
|
||||||
|
module.add(function);
|
||||||
|
|
||||||
|
WasmLocal subtypeVar = new WasmLocal(WasmType.INT32, "subtype");
|
||||||
|
function.add(subtypeVar);
|
||||||
|
|
||||||
|
if (type instanceof ValueType.Object) {
|
||||||
|
String className = ((ValueType.Object) type).getClassName();
|
||||||
|
generateIsClass(subtypeVar, classGenerator, tagRegistry, className, function.getBody());
|
||||||
|
} else if (type instanceof ValueType.Array) {
|
||||||
|
ValueType itemType = ((ValueType.Array) type).getItemType();
|
||||||
|
generateIsArray(subtypeVar, classGenerator, itemType, function.getBody());
|
||||||
|
} else {
|
||||||
|
int expected = classGenerator.getClassPointer(type);
|
||||||
|
WasmExpression condition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(expected));
|
||||||
|
function.getBody().add(new WasmReturn(condition));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateIsClass(WasmLocal subtypeVar, WasmClassGenerator classGenerator, TagRegistry tagRegistry,
|
||||||
|
String className, List<WasmExpression> body) {
|
||||||
|
List<TagRegistry.Range> ranges = tagRegistry.getRanges(className);
|
||||||
|
if (ranges.isEmpty()) {
|
||||||
|
body.add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tagOffset = classGenerator.getFieldOffset(new FieldReference(RuntimeClass.class.getName(), "tag"));
|
||||||
|
|
||||||
|
WasmExpression tagExpression = new WasmGetLocal(subtypeVar);
|
||||||
|
tagExpression = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, tagExpression,
|
||||||
|
new WasmInt32Constant(tagOffset));
|
||||||
|
tagExpression = new WasmLoadInt32(4, tagExpression, WasmInt32Subtype.INT32);
|
||||||
|
body.add(new WasmSetLocal(subtypeVar, tagExpression));
|
||||||
|
|
||||||
|
Collections.sort(ranges, Comparator.comparingInt(range -> range.lower));
|
||||||
|
|
||||||
|
int lower = ranges.get(0).lower;
|
||||||
|
int upper = ranges.get(ranges.size() - 1).upper;
|
||||||
|
|
||||||
|
WasmExpression lowerCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.LT_SIGNED,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(lower));
|
||||||
|
WasmConditional testLower = new WasmConditional(lowerCondition);
|
||||||
|
testLower.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
|
body.add(testLower);
|
||||||
|
|
||||||
|
WasmExpression upperCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.GT_SIGNED,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(upper));
|
||||||
|
WasmConditional testUpper = new WasmConditional(upperCondition);
|
||||||
|
testUpper.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
|
body.add(testUpper);
|
||||||
|
|
||||||
|
for (int i = 1; i < ranges.size(); ++i) {
|
||||||
|
int lowerHole = ranges.get(i - 1).upper;
|
||||||
|
int upperHole = ranges.get(i).lower;
|
||||||
|
|
||||||
|
lowerCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.GT_SIGNED,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(lowerHole));
|
||||||
|
testLower = new WasmConditional(lowerCondition);
|
||||||
|
body.add(testLower);
|
||||||
|
|
||||||
|
upperCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.LT_SIGNED,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(upperHole));
|
||||||
|
testUpper = new WasmConditional(upperCondition);
|
||||||
|
testUpper.getThenBlock().getBody().add(new WasmReturn(new WasmInt32Constant(0)));
|
||||||
|
|
||||||
|
testLower.getThenBlock().getBody().add(testUpper);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.add(new WasmReturn(new WasmInt32Constant(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateIsArray(WasmLocal subtypeVar, WasmClassGenerator classGenerator, ValueType itemType,
|
||||||
|
List<WasmExpression> body) {
|
||||||
|
int itemOffset = classGenerator.getFieldOffset(new FieldReference(RuntimeClass.class.getName(), "itemType"));
|
||||||
|
|
||||||
|
WasmExpression itemExpression = new WasmGetLocal(subtypeVar);
|
||||||
|
itemExpression = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, itemExpression,
|
||||||
|
new WasmInt32Constant(itemOffset));
|
||||||
|
itemExpression = new WasmLoadInt32(4, itemExpression, WasmInt32Subtype.INT32);
|
||||||
|
body.add(new WasmSetLocal(subtypeVar, itemExpression));
|
||||||
|
|
||||||
|
WasmExpression itemCondition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ,
|
||||||
|
new WasmGetLocal(subtypeVar), new WasmInt32Constant(0));
|
||||||
|
WasmConditional itemTest = new WasmConditional(itemCondition);
|
||||||
|
itemTest.getThenBlock().getBody().add(new WasmInt32Constant(0));
|
||||||
|
|
||||||
|
WasmCall delegateToItem = new WasmCall(WasmMangling.mangeIsSupertype(itemType));
|
||||||
|
delegateToItem.getArguments().add(new WasmGetLocal(subtypeVar));
|
||||||
|
itemTest.getElseBlock().getBody().add(delegateToItem);
|
||||||
|
|
||||||
|
body.add(new WasmReturn(itemTest));
|
||||||
|
}
|
||||||
|
|
||||||
private WasmFunction generateStub(MethodHolder method, MethodHolder implementor) {
|
private WasmFunction generateStub(MethodHolder method, MethodHolder implementor) {
|
||||||
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(method.getReference()));
|
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(method.getReference()));
|
||||||
if (!method.hasModifier(ElementModifier.STATIC)) {
|
if (!method.hasModifier(ElementModifier.STATIC)) {
|
||||||
|
@ -363,7 +471,11 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
|
|
||||||
private void renderClinit(ListableClassReaderSource classes, WasmClassGenerator classGenerator,
|
private void renderClinit(ListableClassReaderSource classes, WasmClassGenerator classGenerator,
|
||||||
WasmModule module) {
|
WasmModule module) {
|
||||||
for (String className : classes.getClassNames()) {
|
for (ValueType type : classGenerator.getRegisteredClasses()) {
|
||||||
|
if (!(type instanceof ValueType.Object)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String className = ((ValueType.Object) type).getClassName();
|
||||||
if (classGenerator.isStructure(className)) {
|
if (classGenerator.isStructure(className)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.backend.wasm.generate;
|
||||||
import com.carrotsearch.hppc.ObjectIntMap;
|
import com.carrotsearch.hppc.ObjectIntMap;
|
||||||
import com.carrotsearch.hppc.ObjectIntOpenHashMap;
|
import com.carrotsearch.hppc.ObjectIntOpenHashMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -53,6 +54,7 @@ public class WasmClassGenerator {
|
||||||
private List<String> functionTable = new ArrayList<>();
|
private List<String> functionTable = new ArrayList<>();
|
||||||
private VirtualTableProvider vtableProvider;
|
private VirtualTableProvider vtableProvider;
|
||||||
private TagRegistry tagRegistry;
|
private TagRegistry tagRegistry;
|
||||||
|
private boolean isSubtypeGenerated;
|
||||||
private DataStructure objectStructure = new DataStructure((byte) 0,
|
private DataStructure objectStructure = new DataStructure((byte) 0,
|
||||||
DataPrimitives.INT, /* class */
|
DataPrimitives.INT, /* class */
|
||||||
DataPrimitives.ADDRESS /* monitor/hash code */);
|
DataPrimitives.ADDRESS /* monitor/hash code */);
|
||||||
|
@ -105,10 +107,10 @@ public class WasmClassGenerator {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
binaryData.data = createPrimitiveClassData(size);
|
binaryData.data = createPrimitiveClassData(size, type);
|
||||||
binaryData.start = binaryWriter.append(binaryData.data);
|
binaryData.start = binaryWriter.append(binaryData.data);
|
||||||
} else if (type == ValueType.VOID) {
|
} else if (type == ValueType.VOID) {
|
||||||
binaryData.data = createPrimitiveClassData(0);
|
binaryData.data = createPrimitiveClassData(0, type);
|
||||||
binaryData.start = binaryWriter.append(binaryData.data);
|
binaryData.start = binaryWriter.append(binaryData.data);
|
||||||
} else if (type instanceof ValueType.Object) {
|
} else if (type instanceof ValueType.Object) {
|
||||||
String className = ((ValueType.Object) type).getClassName();
|
String className = ((ValueType.Object) type).getClassName();
|
||||||
|
@ -136,16 +138,20 @@ public class WasmClassGenerator {
|
||||||
binaryData.data = wrapper.getValue(0);
|
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.data.setInt(7, functionTable.size());
|
||||||
|
functionTable.add(WasmMangling.mangeIsSupertype(type));
|
||||||
binaryData.start = binaryWriter.append(vtableSize > 0 ? wrapper : binaryData.data);
|
binaryData.start = binaryWriter.append(vtableSize > 0 ? wrapper : binaryData.data);
|
||||||
|
|
||||||
itemBinaryData.data.setAddress(6, binaryData.start);
|
itemBinaryData.data.setAddress(6, binaryData.start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataValue createPrimitiveClassData(int size) {
|
private DataValue createPrimitiveClassData(int size, ValueType type) {
|
||||||
DataValue value = classStructure.createValue();
|
DataValue value = classStructure.createValue();
|
||||||
value.setInt(1, size);
|
value.setInt(1, size);
|
||||||
value.setInt(2, RuntimeClass.PRIMITIVE);
|
value.setInt(2, RuntimeClass.PRIMITIVE);
|
||||||
|
value.setInt(7, functionTable.size());
|
||||||
|
functionTable.add(WasmMangling.mangeIsSupertype(type));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +176,8 @@ 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));
|
||||||
|
header.setInt(7, functionTable.size());
|
||||||
|
functionTable.add(WasmMangling.mangeIsSupertype(ValueType.object(name)));
|
||||||
|
|
||||||
if (vtable != null) {
|
if (vtable != null) {
|
||||||
fillVirtualTable(vtable, array);
|
fillVirtualTable(vtable, array);
|
||||||
|
@ -196,6 +204,10 @@ public class WasmClassGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<ValueType> getRegisteredClasses() {
|
||||||
|
return binaryDataMap.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
public int getClassPointer(ValueType type) {
|
public int getClassPointer(ValueType type) {
|
||||||
addClass(type);
|
addClass(type);
|
||||||
ClassBinaryData data = binaryDataMap.get(type);
|
ClassBinaryData data = binaryDataMap.get(type);
|
||||||
|
|
|
@ -24,6 +24,10 @@ public final class WasmMangling {
|
||||||
private WasmMangling() {
|
private WasmMangling() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String mangeIsSupertype(ValueType type) {
|
||||||
|
return "isSupertype$" + mangleType(type);
|
||||||
|
}
|
||||||
|
|
||||||
public static String mangleMethod(MethodReference method) {
|
public static String mangleMethod(MethodReference method) {
|
||||||
String className = method.getClassName().length() + mangleString(method.getClassName());
|
String className = method.getClassName().length() + mangleString(method.getClassName());
|
||||||
StringBuilder sb = new StringBuilder("method$" + className + "_");
|
StringBuilder sb = new StringBuilder("method$" + className + "_");
|
||||||
|
|
|
@ -64,6 +64,7 @@ public class WasmCRenderer {
|
||||||
|
|
||||||
renderFunctionDeclarations(module);
|
renderFunctionDeclarations(module);
|
||||||
line("static int8_t *wasm_heap;");
|
line("static int8_t *wasm_heap;");
|
||||||
|
line("static int32_t wasm_heap_size;");
|
||||||
renderFunctionTable(module);
|
renderFunctionTable(module);
|
||||||
|
|
||||||
for (WasmFunction function : module.getFunctions().values()) {
|
for (WasmFunction function : module.getFunctions().values()) {
|
||||||
|
@ -91,7 +92,8 @@ public class WasmCRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderHeap(WasmModule module) {
|
private void renderHeap(WasmModule module) {
|
||||||
line("wasm_heap = malloc(" + 65535 * module.getMemorySize() + ");");
|
line("wasm_heap_size = " + 65536 * module.getMemorySize() + ";");
|
||||||
|
line("wasm_heap = malloc(" + 65536 * module.getMemorySize() + ");");
|
||||||
for (WasmMemorySegment segment : module.getSegments()) {
|
for (WasmMemorySegment segment : module.getSegments()) {
|
||||||
line("memcpy(wasm_heap + " + segment.getOffset() + ",");
|
line("memcpy(wasm_heap + " + segment.getOffset() + ",");
|
||||||
indent();
|
indent();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user