mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: fix support of class initialization, inherit arrays from Object, add support for clone in arrays
This commit is contained in:
parent
335e2da4cf
commit
3e19ca341e
|
@ -343,6 +343,9 @@ public class TObject {
|
||||||
@DelegateTo("cloneLowLevel")
|
@DelegateTo("cloneLowLevel")
|
||||||
@PluggableDependency(ObjectDependencyPlugin.class)
|
@PluggableDependency(ObjectDependencyPlugin.class)
|
||||||
protected Object clone() throws TCloneNotSupportedException {
|
protected Object clone() throws TCloneNotSupportedException {
|
||||||
|
if (PlatformDetector.isWebAssemblyGC()) {
|
||||||
|
throw new TCloneNotSupportedException();
|
||||||
|
}
|
||||||
if (!(this instanceof TCloneable) && Platform.getPlatformObject(this)
|
if (!(this instanceof TCloneable) && Platform.getPlatformObject(this)
|
||||||
.getPlatformClass().getMetadata().getArrayItem() == null) {
|
.getPlatformClass().getMetadata().getArrayItem() == null) {
|
||||||
throw new TCloneNotSupportedException();
|
throw new TCloneNotSupportedException();
|
||||||
|
|
|
@ -131,7 +131,7 @@ public class WasmGCDeclarationsGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static WasmGCVirtualTableProvider createVirtualTableProvider(ListableClassHolderSource classes) {
|
private static WasmGCVirtualTableProvider createVirtualTableProvider(ListableClassHolderSource classes) {
|
||||||
return new WasmGCVirtualTableProvider(classes, VirtualTableBuilder.getMethodsUsedOnCallSites(classes, false));
|
return new WasmGCVirtualTableProvider(classes, VirtualTableBuilder.getMethodsUsedOnCallSites(classes, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmFunction dummyInitializer() {
|
public WasmFunction dummyInitializer() {
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.teavm.backend.lowlevel.generate.NameProvider;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||||
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTable;
|
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTable;
|
||||||
|
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableEntry;
|
||||||
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.WasmGCInitializerContributor;
|
import org.teavm.backend.wasm.generate.gc.WasmGCInitializerContributor;
|
||||||
import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringPool;
|
import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringPool;
|
||||||
|
@ -42,19 +43,27 @@ import org.teavm.backend.wasm.model.WasmModule;
|
||||||
import org.teavm.backend.wasm.model.WasmStorageType;
|
import org.teavm.backend.wasm.model.WasmStorageType;
|
||||||
import org.teavm.backend.wasm.model.WasmStructure;
|
import org.teavm.backend.wasm.model.WasmStructure;
|
||||||
import org.teavm.backend.wasm.model.WasmType;
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmArrayCopy;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmArrayLength;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmArrayNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFloat32Constant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmFloat64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
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.WasmInt64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
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.WasmNullConstant;
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
@ -70,6 +79,8 @@ import org.teavm.model.util.ReflectionUtil;
|
||||||
|
|
||||||
public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInitializerContributor {
|
public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInitializerContributor {
|
||||||
private static final MethodDescriptor CLINIT_METHOD_DESC = new MethodDescriptor("<clinit>", ValueType.VOID);
|
private static final MethodDescriptor CLINIT_METHOD_DESC = new MethodDescriptor("<clinit>", ValueType.VOID);
|
||||||
|
private static final MethodDescriptor CLONE_METHOD_DESC = new MethodDescriptor("clone",
|
||||||
|
ValueType.object("java.lang.Object"));
|
||||||
private static final MethodDescriptor GET_CLASS_METHOD = new MethodDescriptor("getClass",
|
private static final MethodDescriptor GET_CLASS_METHOD = new MethodDescriptor("getClass",
|
||||||
ValueType.parse(Class.class));
|
ValueType.parse(Class.class));
|
||||||
private static final FieldReference FAKE_CLASS_FIELD = new FieldReference(Object.class.getName(), "class");
|
private static final FieldReference FAKE_CLASS_FIELD = new FieldReference(Object.class.getName(), "class");
|
||||||
|
@ -213,14 +224,6 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
}
|
}
|
||||||
function.getBody().add(setClassField(classInfo, CLASS_FIELD_OFFSET,
|
function.getBody().add(setClassField(classInfo, CLASS_FIELD_OFFSET,
|
||||||
new WasmGetGlobal(classClass.pointer)));
|
new WasmGetGlobal(classClass.pointer)));
|
||||||
if (classInfo.initializerPointer != null) {
|
|
||||||
var className = ((ValueType.Object) classInfo.getValueType()).getClassName();
|
|
||||||
var initFunction = functionProvider.forStaticMethod(new MethodReference(className,
|
|
||||||
CLINIT_METHOD_DESC));
|
|
||||||
initFunction.setReferenced(true);
|
|
||||||
function.getBody().add(new WasmSetGlobal(classInfo.initializerPointer,
|
|
||||||
new WasmFunctionReference(initFunction)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (var consumer : staticFieldInitializers) {
|
for (var consumer : staticFieldInitializers) {
|
||||||
consumer.accept(function);
|
consumer.accept(function);
|
||||||
|
@ -245,7 +248,9 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
isInterface = true;
|
isInterface = true;
|
||||||
classInfo.structure = standardClasses.objectClass().structure;
|
classInfo.structure = standardClasses.objectClass().structure;
|
||||||
} else {
|
} else {
|
||||||
classInfo.structure = new WasmStructure(name != null ? names.forClass(name) : null);
|
var finalClassInfo = classInfo;
|
||||||
|
classInfo.structure = new WasmStructure(name != null ? names.forClass(name) : null,
|
||||||
|
fields -> fillFields(finalClassInfo, fields, type));
|
||||||
module.types.add(classInfo.structure);
|
module.types.add(classInfo.structure);
|
||||||
}
|
}
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
|
@ -256,17 +261,23 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
classInfo.structure.setSupertype(getClassInfo(classReader.getParent()).structure);
|
classInfo.structure.setSupertype(getClassInfo(classReader.getParent()).structure);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
virtualTable = virtualTables.lookup("java.lang.Object");
|
||||||
classInfo.structure.setSupertype(standardClasses.objectClass().structure);
|
classInfo.structure.setSupertype(standardClasses.objectClass().structure);
|
||||||
}
|
}
|
||||||
if (!isInterface) {
|
|
||||||
fillFields(classInfo, type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var pointerName = names.forClassInstance(type);
|
var pointerName = names.forClassInstance(type);
|
||||||
classInfo.hasOwnVirtualTable = virtualTable != null && !virtualTable.getEntries().isEmpty();
|
classInfo.hasOwnVirtualTable = virtualTable != null && !virtualTable.getEntries().isEmpty();
|
||||||
var classStructure = classInfo.hasOwnVirtualTable
|
WasmStructure classStructure;
|
||||||
? initRegularClassStructure(((ValueType.Object) type).getClassName())
|
if (classInfo.hasOwnVirtualTable) {
|
||||||
: standardClasses.classClass().getStructure();
|
if (type instanceof ValueType.Object) {
|
||||||
|
classStructure = initRegularClassStructure(((ValueType.Object) type).getClassName());
|
||||||
|
} else {
|
||||||
|
classStructure = standardClasses.objectClass().getVirtualTableStructure();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
classStructure = standardClasses.classClass().getStructure();
|
||||||
|
}
|
||||||
|
|
||||||
classInfo.virtualTableStructure = classStructure;
|
classInfo.virtualTableStructure = classStructure;
|
||||||
classInfo.pointer = new WasmGlobal(pointerName, classStructure.getReference(),
|
classInfo.pointer = new WasmGlobal(pointerName, classStructure.getReference(),
|
||||||
new WasmNullConstant(classStructure.getReference()));
|
new WasmNullConstant(classStructure.getReference()));
|
||||||
|
@ -397,44 +408,118 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
if (virtualTable != null) {
|
if (virtualTable != null) {
|
||||||
fillVirtualTableMethods(target, classStructure, classInfo.pointer, virtualTable);
|
fillVirtualTableMethods(target, classStructure, classInfo.pointer, virtualTable);
|
||||||
}
|
}
|
||||||
|
if (classInfo.initializerPointer != null) {
|
||||||
|
var initFunction = functionProvider.forStaticMethod(new MethodReference(name,
|
||||||
|
CLINIT_METHOD_DESC));
|
||||||
|
initFunction.setReferenced(true);
|
||||||
|
target.add(new WasmSetGlobal(classInfo.initializerPointer, new WasmFunctionReference(initFunction)));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillVirtualTableMethods(List<WasmExpression> target, WasmStructure structure, WasmGlobal global,
|
private void fillVirtualTableMethods(List<WasmExpression> target, WasmStructure structure, WasmGlobal global,
|
||||||
WasmGCVirtualTable virtualTable) {
|
WasmGCVirtualTable virtualTable) {
|
||||||
for (var entry : virtualTable.getEntries()) {
|
for (var entry : virtualTable.getEntries()) {
|
||||||
var implementor = virtualTable.implementor(entry);
|
fillVirtualTableEntry(target, global, structure, virtualTable, entry);
|
||||||
if (implementor != null && !entry.getMethod().equals(GET_CLASS_METHOD)) {
|
}
|
||||||
var fieldIndex = virtualTableFieldOffset + entry.getIndex();
|
}
|
||||||
var expectedType = (WasmType.CompositeReference) structure.getFields().get(fieldIndex)
|
|
||||||
.getUnpackedType();
|
private void fillArrayVirtualTableMethods(List<WasmExpression> target, WasmGlobal global,
|
||||||
var expectedFunctionType = (WasmFunctionType) expectedType.composite;
|
WasmStructure objectStructure) {
|
||||||
var function = functionProvider.forInstanceMethod(implementor);
|
var virtualTable = virtualTables.lookup("java.lang.Object");
|
||||||
if (entry.getOrigin().getClassName().equals(implementor.getClassName())
|
var structure = standardClasses.objectClass().getVirtualTableStructure();
|
||||||
|| expectedFunctionType != function.getType()) {
|
|
||||||
var wrapperFunction = new WasmFunction(expectedFunctionType);
|
for (var entry : virtualTable.getEntries()) {
|
||||||
module.functions.add(wrapperFunction);
|
if (entry.getMethod().getName().equals("clone")) {
|
||||||
var call = new WasmCall(function);
|
var function = generateArrayCloneMethod(objectStructure);
|
||||||
var instanceParam = new WasmLocal(getClassInfo(virtualTable.getClassName()).getType());
|
|
||||||
wrapperFunction.add(instanceParam);
|
|
||||||
var castTarget = getClassInfo(implementor.getClassName()).getType();
|
|
||||||
call.getArguments().add(new WasmCast(new WasmGetLocal(instanceParam), castTarget));
|
|
||||||
var params = new WasmLocal[entry.getMethod().parameterCount()];
|
|
||||||
for (var i = 0; i < entry.getMethod().parameterCount(); ++i) {
|
|
||||||
params[i] = new WasmLocal(typeMapper.mapType(entry.getMethod().parameterType(i)));
|
|
||||||
call.getArguments().add(new WasmGetLocal(params[i]));
|
|
||||||
wrapperFunction.add(params[i]);
|
|
||||||
}
|
|
||||||
wrapperFunction.getBody().add(new WasmReturn(call));
|
|
||||||
function = wrapperFunction;
|
|
||||||
}
|
|
||||||
function.setReferenced(true);
|
function.setReferenced(true);
|
||||||
var ref = new WasmFunctionReference(function);
|
var ref = new WasmFunctionReference(function);
|
||||||
|
var fieldIndex = virtualTableFieldOffset + entry.getIndex();
|
||||||
target.add(new WasmStructSet(structure, new WasmGetGlobal(global), fieldIndex, ref));
|
target.add(new WasmStructSet(structure, new WasmGetGlobal(global), fieldIndex, ref));
|
||||||
|
} else {
|
||||||
|
fillVirtualTableEntry(target, global, structure, virtualTable, entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fillVirtualTableEntry(List<WasmExpression> target, WasmGlobal global,
|
||||||
|
WasmStructure structure, WasmGCVirtualTable virtualTable, WasmGCVirtualTableEntry entry) {
|
||||||
|
var implementor = virtualTable.implementor(entry);
|
||||||
|
if (implementor != null && !entry.getMethod().equals(GET_CLASS_METHOD)) {
|
||||||
|
var fieldIndex = virtualTableFieldOffset + entry.getIndex();
|
||||||
|
var expectedType = (WasmType.CompositeReference) structure.getFields().get(fieldIndex)
|
||||||
|
.getUnpackedType();
|
||||||
|
var expectedFunctionType = (WasmFunctionType) expectedType.composite;
|
||||||
|
var function = functionProvider.forInstanceMethod(implementor);
|
||||||
|
if (entry.getOrigin().getClassName().equals(implementor.getClassName())
|
||||||
|
|| expectedFunctionType != function.getType()) {
|
||||||
|
var wrapperFunction = new WasmFunction(expectedFunctionType);
|
||||||
|
module.functions.add(wrapperFunction);
|
||||||
|
var call = new WasmCall(function);
|
||||||
|
var instanceParam = new WasmLocal(getClassInfo(virtualTable.getClassName()).getType());
|
||||||
|
wrapperFunction.add(instanceParam);
|
||||||
|
var castTarget = getClassInfo(implementor.getClassName()).getType();
|
||||||
|
call.getArguments().add(new WasmCast(new WasmGetLocal(instanceParam), castTarget));
|
||||||
|
var params = new WasmLocal[entry.getMethod().parameterCount()];
|
||||||
|
for (var i = 0; i < entry.getMethod().parameterCount(); ++i) {
|
||||||
|
params[i] = new WasmLocal(typeMapper.mapType(entry.getMethod().parameterType(i)));
|
||||||
|
call.getArguments().add(new WasmGetLocal(params[i]));
|
||||||
|
wrapperFunction.add(params[i]);
|
||||||
|
}
|
||||||
|
wrapperFunction.getBody().add(new WasmReturn(call));
|
||||||
|
function = wrapperFunction;
|
||||||
|
}
|
||||||
|
function.setReferenced(true);
|
||||||
|
var ref = new WasmFunctionReference(function);
|
||||||
|
target.add(new WasmStructSet(structure, new WasmGetGlobal(global), fieldIndex, ref));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmFunction generateArrayCloneMethod(WasmStructure objectStructure) {
|
||||||
|
var arrayTypeRef = (WasmType.CompositeReference) objectStructure.getFields().get(
|
||||||
|
WasmGCClassInfoProvider.ARRAY_DATA_FIELD_OFFSET).getUnpackedType();
|
||||||
|
var arrayType = (WasmArray) arrayTypeRef.composite;
|
||||||
|
|
||||||
|
var type = typeMapper.getFunctionType(standardClasses.objectClass().getType(), CLONE_METHOD_DESC, false);
|
||||||
|
var function = new WasmFunction(type);
|
||||||
|
module.functions.add(function);
|
||||||
|
var instanceLocal = new WasmLocal(standardClasses.objectClass().getType());
|
||||||
|
var originalLocal = new WasmLocal(objectStructure.getReference());
|
||||||
|
var resultLocal = new WasmLocal(objectStructure.getReference());
|
||||||
|
var originalDataLocal = new WasmLocal(arrayType.getReference());
|
||||||
|
var dataCopyLocal = new WasmLocal(arrayType.getReference());
|
||||||
|
function.add(instanceLocal);
|
||||||
|
function.add(originalLocal);
|
||||||
|
function.add(resultLocal);
|
||||||
|
function.add(originalDataLocal);
|
||||||
|
function.add(dataCopyLocal);
|
||||||
|
|
||||||
|
function.getBody().add(new WasmSetLocal(originalLocal,
|
||||||
|
new WasmCast(new WasmGetLocal(instanceLocal), objectStructure.getReference())));
|
||||||
|
function.getBody().add(new WasmSetLocal(resultLocal, new WasmStructNewDefault(objectStructure)));
|
||||||
|
|
||||||
|
var classValue = new WasmStructGet(objectStructure, new WasmGetLocal(originalLocal),
|
||||||
|
WasmGCClassInfoProvider.CLASS_FIELD_OFFSET);
|
||||||
|
function.getBody().add(new WasmStructSet(objectStructure, new WasmGetLocal(resultLocal),
|
||||||
|
WasmGCClassInfoProvider.CLASS_FIELD_OFFSET, classValue));
|
||||||
|
|
||||||
|
var originalDataValue = new WasmStructGet(objectStructure, new WasmGetLocal(originalLocal),
|
||||||
|
WasmGCClassInfoProvider.ARRAY_DATA_FIELD_OFFSET);
|
||||||
|
function.getBody().add(new WasmSetLocal(originalDataLocal, originalDataValue));
|
||||||
|
var originalLength = new WasmArrayLength(new WasmGetLocal(originalDataLocal));
|
||||||
|
function.getBody().add(new WasmSetLocal(dataCopyLocal, new WasmArrayNewDefault(arrayType, originalLength)));
|
||||||
|
function.getBody().add(new WasmStructSet(objectStructure, new WasmGetLocal(resultLocal),
|
||||||
|
WasmGCClassInfoProvider.ARRAY_DATA_FIELD_OFFSET, new WasmGetLocal(dataCopyLocal)));
|
||||||
|
|
||||||
|
function.getBody().add(new WasmArrayCopy(arrayType, new WasmGetLocal(dataCopyLocal),
|
||||||
|
new WasmInt32Constant(0), arrayType, new WasmGetLocal(originalDataLocal),
|
||||||
|
new WasmInt32Constant(0), new WasmArrayLength(new WasmGetLocal(originalDataLocal))));
|
||||||
|
|
||||||
|
function.getBody().add(new WasmGetLocal(resultLocal));
|
||||||
|
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
private WasmStructure initRegularClassStructure(String className) {
|
private WasmStructure initRegularClassStructure(String className) {
|
||||||
var virtualTable = virtualTables.lookup(className);
|
var virtualTable = virtualTables.lookup(className);
|
||||||
var structure = new WasmStructure(names.forClassClass(className));
|
var structure = new WasmStructure(names.forClassClass(className));
|
||||||
|
@ -472,6 +557,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
new WasmGetGlobal(classInfo.pointer),
|
new WasmGetGlobal(classInfo.pointer),
|
||||||
new WasmGetGlobal(itemTypeInfo.pointer)
|
new WasmGetGlobal(itemTypeInfo.pointer)
|
||||||
));
|
));
|
||||||
|
fillArrayVirtualTableMethods(target, classInfo.pointer, classInfo.structure);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +575,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getFieldIndex(FieldReference fieldRef) {
|
public int getFieldIndex(FieldReference fieldRef) {
|
||||||
getClassInfo(fieldRef.getClassName());
|
getClassInfo(fieldRef.getClassName()).structure.init();
|
||||||
return fieldIndexes.getOrDefault(fieldRef, -1);
|
return fieldIndexes.getOrDefault(fieldRef, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,14 +600,51 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
}
|
}
|
||||||
|
|
||||||
var type = typeMapper.mapType(javaType);
|
var type = typeMapper.mapType(javaType);
|
||||||
var global = new WasmGlobal(names.forStaticField(fieldRef), type, WasmExpression.defaultValueOfType(type));
|
var wasmInitialValue = initValue != null ? initialValue(initValue) : WasmExpression.defaultValueOfType(type);
|
||||||
|
var global = new WasmGlobal(names.forStaticField(fieldRef), type, wasmInitialValue);
|
||||||
|
dynamicInitialValue(global, initValue);
|
||||||
module.globals.add(global);
|
module.globals.add(global);
|
||||||
|
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillFields(WasmGCClassInfo classInfo, ValueType type) {
|
private WasmExpression initialValue(Object value) {
|
||||||
var fields = classInfo.structure.getFields();
|
if (value instanceof Boolean) {
|
||||||
|
return new WasmInt32Constant((Boolean) value ? 1 : 0);
|
||||||
|
} else if (value instanceof Byte) {
|
||||||
|
return new WasmInt32Constant((Byte) value);
|
||||||
|
} else if (value instanceof Short) {
|
||||||
|
return new WasmInt32Constant((Short) value);
|
||||||
|
} else if (value instanceof Character) {
|
||||||
|
return new WasmInt32Constant((Character) value);
|
||||||
|
} else if (value instanceof Integer) {
|
||||||
|
return new WasmInt32Constant((Integer) value);
|
||||||
|
} else if (value instanceof Long) {
|
||||||
|
return new WasmInt64Constant((Long) value);
|
||||||
|
} else if (value instanceof Float) {
|
||||||
|
return new WasmFloat32Constant((Float) value);
|
||||||
|
} else if (value instanceof Double) {
|
||||||
|
return new WasmFloat64Constant((Double) value);
|
||||||
|
} else {
|
||||||
|
return new WasmNullConstant(standardClasses.stringClass().getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dynamicInitialValue(WasmGlobal global, Object value) {
|
||||||
|
if (value instanceof String) {
|
||||||
|
var constant = strings.getStringConstant((String) value).global;
|
||||||
|
staticFieldInitializers.add(function -> {
|
||||||
|
function.getBody().add(new WasmSetGlobal(global, new WasmGetGlobal(constant)));
|
||||||
|
});
|
||||||
|
} else if (value instanceof ValueType) {
|
||||||
|
var constant = getClassInfo((ValueType) value).pointer;
|
||||||
|
staticFieldInitializers.add(function -> {
|
||||||
|
function.getBody().add(new WasmSetGlobal(global, new WasmGetGlobal(constant)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillFields(WasmGCClassInfo classInfo, List<WasmField> fields, ValueType type) {
|
||||||
addSystemFields(fields);
|
addSystemFields(fields);
|
||||||
if (type instanceof ValueType.Object) {
|
if (type instanceof ValueType.Object) {
|
||||||
fillClassFields(fields, ((ValueType.Object) type).getClassName());
|
fillClassFields(fields, ((ValueType.Object) type).getClassName());
|
||||||
|
|
|
@ -47,6 +47,7 @@ public class WasmGCClassInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmArray getArray() {
|
public WasmArray getArray() {
|
||||||
|
structure.init();
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,11 +114,11 @@ public class WasmGCTypeMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmFunctionType getFunctionType(String className, MethodDescriptor methodDesc, boolean fresh) {
|
public WasmFunctionType getFunctionType(WasmType receiverType, MethodDescriptor methodDesc, boolean fresh) {
|
||||||
var returnType = mapType(methodDesc.getResultType());
|
var returnType = mapType(methodDesc.getResultType());
|
||||||
var javaParamTypes = methodDesc.getParameterTypes();
|
var javaParamTypes = methodDesc.getParameterTypes();
|
||||||
var paramTypes = new WasmType[javaParamTypes.length + 1];
|
var paramTypes = new WasmType[javaParamTypes.length + 1];
|
||||||
paramTypes[0] = classInfoProvider.getClassInfo(className).getType();
|
paramTypes[0] = receiverType;
|
||||||
for (var i = 0; i < javaParamTypes.length; ++i) {
|
for (var i = 0; i < javaParamTypes.length; ++i) {
|
||||||
paramTypes[i + 1] = mapType(javaParamTypes[i]);
|
paramTypes[i + 1] = mapType(javaParamTypes[i]);
|
||||||
}
|
}
|
||||||
|
@ -130,4 +130,8 @@ public class WasmGCTypeMapper {
|
||||||
return functionTypes.of(returnType, paramTypes);
|
return functionTypes.of(returnType, paramTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmFunctionType getFunctionType(String className, MethodDescriptor methodDesc, boolean fresh) {
|
||||||
|
return getFunctionType(classInfoProvider.getClassInfo(className).getType(), methodDesc, fresh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,10 @@ package org.teavm.backend.wasm.model;
|
||||||
import java.util.AbstractList;
|
import java.util.AbstractList;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class WasmStructure extends WasmCompositeType {
|
public class WasmStructure extends WasmCompositeType {
|
||||||
|
private Consumer<List<WasmField>> fieldsSupplier;
|
||||||
private List<WasmField> fieldsStorage = new ArrayList<>();
|
private List<WasmField> fieldsStorage = new ArrayList<>();
|
||||||
private WasmStructure supertype;
|
private WasmStructure supertype;
|
||||||
private boolean indexesValid = true;
|
private boolean indexesValid = true;
|
||||||
|
@ -28,6 +30,11 @@ public class WasmStructure extends WasmCompositeType {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmStructure(String name, Consumer<List<WasmField>> fieldsSupplier) {
|
||||||
|
super(name);
|
||||||
|
this.fieldsSupplier = fieldsSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
public List<WasmField> getFields() {
|
public List<WasmField> getFields() {
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
@ -59,24 +66,35 @@ public class WasmStructure extends WasmCompositeType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
if (fieldsSupplier != null) {
|
||||||
|
var supplier = fieldsSupplier;
|
||||||
|
fieldsSupplier = null;
|
||||||
|
supplier.accept(fieldsStorage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(WasmCompositeTypeVisitor visitor) {
|
public void acceptVisitor(WasmCompositeTypeVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<WasmField> fields = new AbstractList<WasmField>() {
|
private List<WasmField> fields = new AbstractList<>() {
|
||||||
@Override
|
@Override
|
||||||
public WasmField get(int index) {
|
public WasmField get(int index) {
|
||||||
|
init();
|
||||||
return fieldsStorage.get(index);
|
return fieldsStorage.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
|
init();
|
||||||
return fieldsStorage.size();
|
return fieldsStorage.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(int index, WasmField element) {
|
public void add(int index, WasmField element) {
|
||||||
|
init();
|
||||||
if (element.structure != null) {
|
if (element.structure != null) {
|
||||||
throw new IllegalArgumentException("This field already belongs to structure");
|
throw new IllegalArgumentException("This field already belongs to structure");
|
||||||
}
|
}
|
||||||
|
@ -87,6 +105,7 @@ public class WasmStructure extends WasmCompositeType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WasmField remove(int index) {
|
public WasmField remove(int index) {
|
||||||
|
init();
|
||||||
var result = fieldsStorage.remove(index);
|
var result = fieldsStorage.remove(index);
|
||||||
indexesValid = false;
|
indexesValid = false;
|
||||||
result.structure = null;
|
result.structure = null;
|
||||||
|
@ -95,6 +114,7 @@ public class WasmStructure extends WasmCompositeType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void removeRange(int fromIndex, int toIndex) {
|
protected void removeRange(int fromIndex, int toIndex) {
|
||||||
|
init();
|
||||||
var sublist = fieldsStorage.subList(fromIndex, toIndex);
|
var sublist = fieldsStorage.subList(fromIndex, toIndex);
|
||||||
for (var field : sublist) {
|
for (var field : sublist) {
|
||||||
field.structure = null;
|
field.structure = null;
|
||||||
|
@ -105,6 +125,7 @@ public class WasmStructure extends WasmCompositeType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
fieldsSupplier = null;
|
||||||
for (var field : fieldsStorage) {
|
for (var field : fieldsStorage) {
|
||||||
field.structure = null;
|
field.structure = null;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +135,7 @@ public class WasmStructure extends WasmCompositeType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WasmField set(int index, WasmField element) {
|
public WasmField set(int index, WasmField element) {
|
||||||
|
init();
|
||||||
if (element.structure != null) {
|
if (element.structure != null) {
|
||||||
throw new IllegalArgumentException("This field already belongs to structure");
|
throw new IllegalArgumentException("This field already belongs to structure");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user