wasm gc: trying to fix type validation

This commit is contained in:
Alexey Andreev 2024-07-30 17:33:31 +02:00
parent 87aaa0b452
commit a1a776ea9b
3 changed files with 30 additions and 15 deletions

View File

@ -181,8 +181,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var name = type instanceof ValueType.Object var name = type instanceof ValueType.Object
? ((ValueType.Object) type).getClassName() ? ((ValueType.Object) type).getClassName()
: null; : null;
classInfo.structure = new WasmStructure(name); classInfo.structure = new WasmStructure(name != null ? names.forClass(name) : null);
classInfo.structure.getFields().add(standardClasses.classClass().getType().asStorage());
module.types.add(classInfo.structure); module.types.add(classInfo.structure);
fillFields(classInfo.structure.getFields(), type); fillFields(classInfo.structure.getFields(), type);
} }
@ -335,7 +334,9 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var virtualTable = virtualTables.lookup(className); var virtualTable = virtualTables.lookup(className);
var structure = new WasmStructure(names.forClassClass(className)); var structure = new WasmStructure(names.forClassClass(className));
module.types.add(structure); module.types.add(structure);
fillClassFields(structure.getFields(), "java.lang.Class"); structure.getFields().add(standardClasses.classClass().getType().asStorage());
structure.getFields().add(WasmType.Reference.ANY.asStorage());
fillSimpleClassFields(structure.getFields(), "java.lang.Class");
addVirtualTableFields(structure, virtualTable); addVirtualTableFields(structure, virtualTable);
return structure; return structure;
} }
@ -385,6 +386,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
@Override @Override
public int getFieldIndex(FieldReference fieldRef) { public int getFieldIndex(FieldReference fieldRef) {
getClassInfo(fieldRef.getClassName());
var result = fieldIndexes.getOrDefault(fieldRef, -1); var result = fieldIndexes.getOrDefault(fieldRef, -1);
if (result < 0) { if (result < 0) {
throw new IllegalStateException("Can't get offset of field " + fieldRef); throw new IllegalStateException("Can't get offset of field " + fieldRef);
@ -430,6 +432,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
private void fillFields(List<WasmStorageType> fields, ValueType type) { private void fillFields(List<WasmStorageType> fields, ValueType type) {
fields.add(standardClasses.classClass().getType().asStorage()); fields.add(standardClasses.classClass().getType().asStorage());
fields.add(WasmType.Reference.ANY.asStorage());
if (type instanceof ValueType.Object) { if (type instanceof ValueType.Object) {
fillClassFields(fields, ((ValueType.Object) type).getClassName()); fillClassFields(fields, ((ValueType.Object) type).getClassName());
} else if (type instanceof ValueType.Array) { } else if (type instanceof ValueType.Array) {
@ -450,10 +453,11 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var classReader = classSource.get(className); var classReader = classSource.get(className);
if (classReader.getParent() != null) { if (classReader.getParent() != null) {
fillClassFields(fields, classReader.getParent()); fillClassFields(fields, classReader.getParent());
} else {
fields.add(standardClasses.classClass().getType().asStorage());
} }
for (var field : classReader.getFields()) { for (var field : classReader.getFields()) {
if (className.equals("java.lang.Object") && field.getName().equals("monitor")) {
continue;
}
if (field.hasModifier(ElementModifier.STATIC)) { if (field.hasModifier(ElementModifier.STATIC)) {
continue; continue;
} }

View File

@ -230,18 +230,12 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
WasmExpression classRef = new WasmStructGet(instanceStruct, new WasmGetLocal(instance), WasmExpression classRef = new WasmStructGet(instanceStruct, new WasmGetLocal(instance),
WasmGCClassInfoProvider.CLASS_FIELD_OFFSET); WasmGCClassInfoProvider.CLASS_FIELD_OFFSET);
var index = context.classInfoProvider().getVirtualMethodIndex(method); var index = context.classInfoProvider().getVirtualMethodIndex(method);
var vtableType = (WasmType.CompositeReference) instanceStruct.getFields() var vtableStruct = context.classInfoProvider().getClassInfo(vtable.getClassName())
.get(WasmGCClassInfoProvider.CLASS_FIELD_OFFSET).asUnpackedType();
var vtableStruct = (WasmStructure) vtableType.composite;
var expectedVtableStruct = context.classInfoProvider().getClassInfo(vtable.getClassName())
.getVirtualTableStructure(); .getVirtualTableStructure();
if (expectedVtableStruct != vtableStruct) { classRef = new WasmCast(classRef, vtableStruct.getReference());
classRef = new WasmCast(classRef, expectedVtableStruct.getReference());
}
var functionRef = new WasmStructGet(expectedVtableStruct, classRef, index); var functionRef = new WasmStructGet(vtableStruct, classRef, index);
var functionTypeRef = (WasmType.CompositeReference) expectedVtableStruct.getFields() var functionTypeRef = (WasmType.CompositeReference) vtableStruct.getFields().get(index).asUnpackedType();
.get(index).asUnpackedType();
var invoke = new WasmCallReference(functionRef, (WasmFunctionType) functionTypeRef.composite); var invoke = new WasmCallReference(functionRef, (WasmFunctionType) functionTypeRef.composite);
invoke.getArguments().addAll(arguments); invoke.getArguments().addAll(arguments);
return invoke; return invoke;

View File

@ -440,6 +440,23 @@ public class WasmBinaryRenderer {
section.writeLEB(payload.length); section.writeLEB(payload.length);
section.writeBytes(payload); section.writeBytes(payload);
var types = module.types.stream()
.filter(t -> t.getName() != null)
.collect(Collectors.toList());
if (!types.isEmpty()) {
var typesSubsection = new WasmBinaryWriter();
typesSubsection.writeLEB(types.size());
for (var type : types) {
typesSubsection.writeLEB(module.types.indexOf(type));
typesSubsection.writeAsciiString(type.getName());
}
payload = typesSubsection.getData();
section.writeLEB(4);
section.writeLEB(payload.length);
section.writeBytes(payload);
}
writeSection(SECTION_UNKNOWN, "name", section.getData()); writeSection(SECTION_UNKNOWN, "name", section.getData());
} }