wasm gc: produce better names for declarations, generate locals in names section

This commit is contained in:
Alexey Andreev 2024-08-27 20:03:22 +02:00
parent 10c3731c43
commit 7324e99e6a
13 changed files with 298 additions and 65 deletions

View File

@ -85,7 +85,7 @@ public class WasmGCModuleGenerator {
var function = declarationsGenerator.functions().forStaticMethod(new MethodReference(
WasmGCSupport.class, "createStringArray", int.class, String[].class));
var caller = new WasmFunction(function.getType());
var sizeLocal = new WasmLocal(WasmType.INT32);
var sizeLocal = new WasmLocal(WasmType.INT32, "length");
caller.add(sizeLocal);
caller.getBody().add(callInitializer());
caller.getBody().add(new WasmReturn(new WasmCall(function, new WasmGetLocal(sizeLocal))));
@ -98,8 +98,8 @@ public class WasmGCModuleGenerator {
StringBuilder.class, "append", char.class, StringBuilder.class));
var stringBuilderType = declarationsGenerator.typeMapper().mapType(ValueType.parse(StringBuilder.class));
var caller = new WasmFunction(declarationsGenerator.functionTypes.of(null, stringBuilderType, WasmType.INT32));
var stringBuilderLocal = new WasmLocal(stringBuilderType);
var codeLocal = new WasmLocal(WasmType.INT32);
var stringBuilderLocal = new WasmLocal(stringBuilderType, "stringBuilder");
var codeLocal = new WasmLocal(WasmType.INT32, "charCode");
caller.add(stringBuilderLocal);
caller.add(codeLocal);
caller.getBody().add(callInitializer());
@ -116,7 +116,7 @@ public class WasmGCModuleGenerator {
var stringBuilderType = declarationsGenerator.typeMapper().mapType(ValueType.parse(StringBuilder.class));
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
var caller = new WasmFunction(declarationsGenerator.functionTypes.of(stringType, stringBuilderType));
var stringBuilderLocal = new WasmLocal(stringBuilderType);
var stringBuilderLocal = new WasmLocal(stringBuilderType, "stringBuilder");
caller.add(stringBuilderLocal);
caller.getBody().add(callInitializer());
caller.getBody().add(new WasmReturn(new WasmCall(function, new WasmGetLocal(stringBuilderLocal))));
@ -130,9 +130,9 @@ public class WasmGCModuleGenerator {
var stringArrayType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String[].class));
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
var caller = new WasmFunction(function.getType());
var arrayLocal = new WasmLocal(stringArrayType);
var indexLocal = new WasmLocal(WasmType.INT32);
var valueLocal = new WasmLocal(stringType);
var arrayLocal = new WasmLocal(stringArrayType, "array");
var indexLocal = new WasmLocal(WasmType.INT32, "index");
var valueLocal = new WasmLocal(stringType, "string");
caller.add(arrayLocal);
caller.add(indexLocal);
caller.add(valueLocal);
@ -148,7 +148,7 @@ public class WasmGCModuleGenerator {
String.class, "length", int.class));
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
var caller = new WasmFunction(function.getType());
var stringLocal = new WasmLocal(stringType);
var stringLocal = new WasmLocal(stringType, "string");
caller.add(stringLocal);
caller.getBody().add(callInitializer());
caller.getBody().add(new WasmReturn(new WasmCall(function, new WasmGetLocal(stringLocal))));
@ -161,8 +161,8 @@ public class WasmGCModuleGenerator {
String.class, "charAt", int.class, char.class));
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
var caller = new WasmFunction(function.getType());
var stringLocal = new WasmLocal(stringType);
var indexLocal = new WasmLocal(WasmType.INT32);
var stringLocal = new WasmLocal(stringType, "string");
var indexLocal = new WasmLocal(WasmType.INT32, "index");
caller.add(stringLocal);
caller.add(indexLocal);
caller.getBody().add(callInitializer());
@ -180,7 +180,7 @@ public class WasmGCModuleGenerator {
initializer = new WasmFunction(functionType);
initializer.setReferenced(true);
declarationsGenerator.module.functions.add(initializer);
initializerRef = new WasmGlobal("teavm_initializer", functionType.getReference(),
initializerRef = new WasmGlobal("teavm@initializer", functionType.getReference(),
new WasmFunctionReference(initializer));
declarationsGenerator.module.globals.add(initializerRef);
initializer.getBody().add(new WasmSetGlobal(initializerRef,

View File

@ -20,7 +20,6 @@ import java.util.function.Predicate;
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
import org.teavm.backend.wasm.generate.WasmNameProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassGenerator;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCSupertypeFunctionProvider;
@ -61,7 +60,7 @@ public class WasmGCDeclarationsGenerator {
hierarchy = new ClassHierarchy(classes);
var virtualTables = createVirtualTableProvider(classes, isVirtual);
functionTypes = new WasmFunctionTypes(module);
var names = new WasmNameProvider();
var names = new WasmGCNameProvider();
methodGenerator = new WasmGCMethodGenerator(
module,
hierarchy,

View File

@ -0,0 +1,157 @@
/*
* Copyright 2024 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.backend.wasm.generate.gc;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
public class WasmGCNameProvider {
private Set<String> occupiedTopLevelNames = new HashSet<>();
private Set<String> occupiedStructNames = new HashSet<>();
private Map<MethodDescriptor, String> virtualMethodNames = new HashMap<>();
private Map<FieldReference, String> memberFieldNames = new HashMap<>();
public String topLevel(String name) {
return pickUnoccupied(name);
}
public String structureField(String name) {
return pickUnoccupied(name, occupiedStructNames);
}
public String forVirtualMethod(MethodDescriptor method) {
return virtualMethodNames.computeIfAbsent(method,
k -> pickUnoccupied(sanitize(k.getName()), occupiedStructNames));
}
public String forMemberField(FieldReference field) {
return memberFieldNames.computeIfAbsent(field,
k -> pickUnoccupied(sanitize(field.getFieldName()), occupiedStructNames));
}
public String suggestForMethod(MethodReference method) {
StringBuilder sb = new StringBuilder();
sb.append(sanitize(method.getClassName()));
sb.append("::");
sb.append(sanitize(method.getName()));
return sb.toString();
}
public String suggestForStaticField(FieldReference field) {
StringBuilder sb = new StringBuilder();
sb.append(sanitize(field.getClassName()));
sb.append('#');
sb.append(sanitize(field.getFieldName()));
return sb.toString();
}
public String suggestForClass(String className) {
return sanitize(className);
}
public String suggestForType(ValueType type) {
StringBuilder sb = new StringBuilder();
suggestForType(type, sb);
return sb.toString();
}
private void suggestForType(ValueType type, StringBuilder sb) {
if (type instanceof ValueType.Object) {
sb.append(suggestForClass(((ValueType.Object) type).getClassName()));
} else if (type instanceof ValueType.Array) {
sb.append("Array<");
suggestForType(((ValueType.Array) type).getItemType(), sb);
sb.append(">");
} else {
sb.append("&").append(type.toString());
}
}
public static String sanitize(String name) {
char[] chars = null;
var i = 0;
for (; i < name.length(); ++i) {
var c = name.charAt(i);
if (!isIdentifierPart(c)) {
chars = new char[name.length()];
name.getChars(0, i, chars, 0);
chars[i++] = '_';
break;
}
}
if (chars == null) {
return name;
}
for (; i < name.length(); ++i) {
var c = name.charAt(i);
chars[i] = isIdentifierPart(c) ? c : '_';
}
return new String(chars);
}
public static boolean isIdentifierPart(char c) {
switch (c) {
case '!':
case '#':
case '$':
case '%':
case '&':
case '`':
case '*':
case '+':
case '-':
case '.':
case '/':
case ':':
case '<':
case '=':
case '>':
case '?':
case '@':
case '\\':
case '^':
case '_':
case '\'':
case '|':
case '~':
return true;
default:
return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9';
}
}
private String pickUnoccupied(String name) {
return pickUnoccupied(name, occupiedTopLevelNames);
}
private String pickUnoccupied(String name, Set<String> occupied) {
String result = name;
int index = 0;
while (!occupied.add(result)) {
result = name + "_" + index++;
}
return result;
}
}

View File

@ -25,13 +25,13 @@ import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.function.Consumer;
import org.teavm.backend.lowlevel.generate.NameProvider;
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
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.generate.gc.WasmGCInitializerContributor;
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringPool;
import org.teavm.backend.wasm.model.WasmArray;
import org.teavm.backend.wasm.model.WasmField;
@ -106,12 +106,13 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
public final WasmGCStringPool strings;
public final WasmGCStandardClasses standardClasses;
public final WasmGCTypeMapper typeMapper;
private final NameProvider names;
private final WasmGCNameProvider names;
private List<WasmExpression> initializerFunctionStatements = new ArrayList<>();
private WasmFunction createPrimitiveClassFunction;
private WasmFunction createArrayClassFunction;
private final WasmGCSupertypeFunctionGenerator supertypeGenerator;
private final WasmGCNewArrayFunctionGenerator newArrayGenerator;
private String arrayDataFieldName;
private int classTagOffset;
private int classFlagsOffset;
@ -134,7 +135,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource,
WasmFunctionTypes functionTypes, TagRegistry tagRegistry,
ClassMetadataRequirements metadataRequirements, WasmGCVirtualTableProvider virtualTables,
BaseWasmFunctionRepository functionProvider, NameProvider names,
BaseWasmFunctionRepository functionProvider, WasmGCNameProvider names,
ClassInitializerInfo classInitializerInfo) {
this.module = module;
this.classSource = classSource;
@ -146,9 +147,9 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
this.names = names;
this.classInitializerInfo = classInitializerInfo;
standardClasses = new WasmGCStandardClasses(this);
strings = new WasmGCStringPool(standardClasses, module, functionProvider);
strings = new WasmGCStringPool(standardClasses, module, functionProvider, names);
supertypeGenerator = new WasmGCSupertypeFunctionGenerator(module, this, names, tagRegistry, functionTypes);
newArrayGenerator = new WasmGCNewArrayFunctionGenerator(module, functionTypes, this);
newArrayGenerator = new WasmGCNewArrayFunctionGenerator(module, functionTypes, this, names);
typeMapper = new WasmGCTypeMapper(classSource, this, functionTypes, module);
}
@ -279,7 +280,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
}
}
if (classInfo.structure == null) {
classInfo.structure = new WasmStructure(name != null ? names.forClass(name) : null,
var structName = names.topLevel(names.suggestForType(type));
classInfo.structure = new WasmStructure(structName,
fields -> fillFields(finalClassInfo, fields, type));
module.types.add(classInfo.structure);
nonInitializedStructures.add(classInfo.structure);
@ -297,7 +299,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
classInfo.structure.setSupertype(standardClasses.objectClass().structure);
}
}
var pointerName = names.forClassInstance(type);
var pointerName = names.topLevel(names.suggestForType(type) + "@class");
classInfo.hasOwnVirtualTable = virtualTable != null && !virtualTable.getEntries().isEmpty();
WasmStructure classStructure;
if (classInfo.hasOwnVirtualTable) {
@ -419,7 +421,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
if (classInitializerInfo.isDynamicInitializer(name)) {
if (cls != null && cls.getMethod(CLINIT_METHOD_DESC) != null) {
var clinitType = functionTypes.of(null);
classInfo.initializerPointer = new WasmGlobal(null, clinitType.getReference(),
var wasmName = names.topLevel(names.suggestForClass(name) + "@initializer");
classInfo.initializerPointer = new WasmGlobal(wasmName, clinitType.getReference(),
new WasmNullConstant(clinitType.getReference()));
module.globals.add(classInfo.initializerPointer);
}
@ -467,10 +470,11 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
WasmStructure objectStructure) {
var virtualTable = virtualTables.lookup("java.lang.Object");
var structure = getArrayVirtualTableStructure();
var itemType = ((ValueType.Array) type).getItemType();
for (var entry : virtualTable.getEntries()) {
if (entry.getMethod().getName().equals("clone")) {
var function = generateArrayCloneMethod(objectStructure);
var function = generateArrayCloneMethod(objectStructure, itemType);
function.setReferenced(true);
var ref = new WasmFunctionReference(function);
var fieldIndex = virtualTableFieldOffset + entry.getIndex();
@ -480,7 +484,6 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
}
}
var itemType = ((ValueType.Array) type).getItemType();
var info = metadataRequirements.getInfo(type);
if (info.arrayLength()) {
var lengthFunction = getArrayLengthFunction(objectStructure);
@ -502,19 +505,20 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var elementType = arrayType.getElementType().asUnpackedType();
if (elementType instanceof WasmType.Reference) {
if (arrayLengthObjectFunction == null) {
arrayLengthObjectFunction = getArrayLengthFunction(objectStructure, arrayType);
arrayLengthObjectFunction = createArrayLengthFunction(objectStructure);
}
return arrayLengthObjectFunction;
}
return getArrayLengthFunction(objectStructure, arrayType);
return createArrayLengthFunction(objectStructure);
}
private WasmFunction getArrayLengthFunction(WasmStructure objectStructure, WasmArray arrayType) {
private WasmFunction createArrayLengthFunction(WasmStructure objectStructure) {
var function = new WasmFunction(functionTypes.of(WasmType.INT32, standardClasses.objectClass().getType()));
function.setReferenced(true);
function.setName(names.topLevel("Array<*>::length"));
module.functions.add(function);
var objectLocal = new WasmLocal(standardClasses.objectClass().getType());
var objectLocal = new WasmLocal(standardClasses.objectClass().getType(), "object");
function.add(objectLocal);
var castObject = new WasmCast(new WasmGetLocal(objectLocal), objectStructure.getReference());
@ -534,6 +538,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
private WasmFunction getArrayGetObjectFunction() {
if (arrayGetObjectFunction == null) {
arrayGetObjectFunction = new WasmFunction(getArrayGetType());
arrayGetObjectFunction.setName(names.topLevel("Array<" + names.suggestForClass("java.lang.Object")
+ "::get"));
module.functions.add(arrayGetObjectFunction);
arrayGetObjectFunction.setReferenced(true);
@ -541,8 +547,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var arrayDataTypeRef = (WasmType.CompositeReference) arrayStruct.getFields()
.get(ARRAY_DATA_FIELD_OFFSET).getUnpackedType();
var arrayDataType = (WasmArray) arrayDataTypeRef.composite;
var objectLocal = new WasmLocal(standardClasses.objectClass().getType());
var indexLocal = new WasmLocal(WasmType.INT32);
var objectLocal = new WasmLocal(standardClasses.objectClass().getType(), "object");
var indexLocal = new WasmLocal(WasmType.INT32, "index");
arrayGetObjectFunction.add(objectLocal);
arrayGetObjectFunction.add(indexLocal);
@ -556,6 +562,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
private WasmFunction generateArrayGetPrimitiveFunction(PrimitiveType type) {
var function = new WasmFunction(getArrayGetType());
arrayGetObjectFunction.setName(names.topLevel("Array<" + names.suggestForType(ValueType.primitive(type))
+ ">::get"));
module.functions.add(function);
function.setReferenced(true);
@ -563,8 +571,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var arrayDataTypeRef = (WasmType.CompositeReference) arrayStruct.getFields()
.get(ARRAY_DATA_FIELD_OFFSET).getUnpackedType();
var arrayDataType = (WasmArray) arrayDataTypeRef.composite;
var objectLocal = new WasmLocal(standardClasses.objectClass().getType());
var indexLocal = new WasmLocal(WasmType.INT32);
var objectLocal = new WasmLocal(standardClasses.objectClass().getType(), "object");
var indexLocal = new WasmLocal(WasmType.INT32, "index");
function.add(objectLocal);
function.add(indexLocal);
@ -644,6 +652,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
if (!entry.getOrigin().getClassName().equals(implementor.getClassName())
|| expectedFunctionType != function.getType()) {
var wrapperFunction = new WasmFunction(expectedFunctionType);
wrapperFunction.setName(names.topLevel(names.suggestForMethod(implementor) + "@caller"));
module.functions.add(wrapperFunction);
var call = new WasmCall(function);
var instanceParam = new WasmLocal(getClassInfo(virtualTable.getClassName()).getType());
@ -665,19 +674,20 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
}
}
private WasmFunction generateArrayCloneMethod(WasmStructure objectStructure) {
private WasmFunction generateArrayCloneMethod(WasmStructure objectStructure, ValueType itemType) {
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);
function.setName(names.topLevel("Array<" + names.suggestForType(itemType) + ">::clone"));
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());
var instanceLocal = new WasmLocal(standardClasses.objectClass().getType(), "instance");
var originalLocal = new WasmLocal(objectStructure.getReference(), "original");
var resultLocal = new WasmLocal(objectStructure.getReference(), "result");
var originalDataLocal = new WasmLocal(arrayType.getReference(), "originalData");
var dataCopyLocal = new WasmLocal(arrayType.getReference(), "resultData");
function.add(instanceLocal);
function.add(originalLocal);
function.add(resultLocal);
@ -712,7 +722,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
private WasmStructure initRegularClassStructure(String className) {
var virtualTable = virtualTables.lookup(className);
var structure = new WasmStructure(names.forClassClass(className), fields -> {
var wasmName = names.topLevel("Class<" + names.suggestForClass(className) + ">");
var structure = new WasmStructure(wasmName, fields -> {
addSystemFields(fields);
fillSimpleClassFields(fields, "java.lang.Class");
addVirtualTableFields(fields, virtualTable);
@ -744,19 +755,22 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
@Override
public WasmStructure getArrayVirtualTableStructure() {
if (arrayVirtualTableStruct == null) {
arrayVirtualTableStruct = new WasmStructure(null, fields -> {
var wasmName = names.topLevel("Class<Array<*>>");
arrayVirtualTableStruct = new WasmStructure(wasmName, fields -> {
addSystemFields(fields);
fillSimpleClassFields(fields, "java.lang.Class");
addVirtualTableFields(fields, virtualTables.lookup("java.lang.Object"));
if (metadataRequirements.hasArrayLength()) {
arrayLengthOffset = fields.size();
var arrayLengthType = getArrayLengthType();
fields.add(new WasmField(arrayLengthType.getReference().asStorage()));
fields.add(new WasmField(arrayLengthType.getReference().asStorage(),
names.structureField("@arrayLength")));
}
if (metadataRequirements.hasArrayGet()) {
arrayGetOffset = fields.size();
var arrayGetType = getArrayGetType();
fields.add(new WasmField(arrayGetType.getReference().asStorage()));
fields.add(new WasmField(arrayGetType.getReference().asStorage(),
names.structureField("@arrayGet")));
}
});
arrayVirtualTableStruct.setSupertype(standardClasses.objectClass().getVirtualTableStructure());
@ -830,7 +844,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var type = typeMapper.mapType(javaType);
var wasmInitialValue = initValue != null ? initialValue(initValue) : WasmExpression.defaultValueOfType(type);
var global = new WasmGlobal(names.forStaticField(fieldRef), type, wasmInitialValue);
var wasmName = names.topLevel(names.suggestForStaticField(fieldRef));
var global = new WasmGlobal(wasmName, type, wasmInitialValue);
dynamicInitialValue(global, initValue);
module.globals.add(global);
@ -968,9 +983,18 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
} else {
wasmElementType = standardClasses.objectClass().getType().asStorage();
}
var wasmArray = new WasmArray(null, wasmElementType);
var wasmArrayName = names.topLevel(names.suggestForType(classInfo.getValueType()) + "$Data");
var wasmArray = new WasmArray(wasmArrayName, wasmElementType);
module.types.add(wasmArray);
classInfo.structure.getFields().add(new WasmField(wasmArray.getReference().asStorage(), "data"));
classInfo.structure.getFields().add(new WasmField(wasmArray.getReference().asStorage(),
arrayDataFieldName()));
}
private String arrayDataFieldName() {
if (arrayDataFieldName == null) {
arrayDataFieldName = names.structureField("@data");
}
return arrayDataFieldName;
}
private WasmFunction getCreatePrimitiveClassFunction() {
@ -988,7 +1012,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
WasmType.INT32
);
var function = new WasmFunction(functionType);
function.setName("teavm_fill_primitive_class");
function.setName(names.topLevel("teavm@fill_primitive_class"));
module.functions.add(function);
var targetVar = new WasmLocal(standardClasses.classClass().getType(), "target");
@ -1047,7 +1071,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
);
var function = new WasmFunction(functionType);
module.functions.add(function);
function.setName("teavm_fill_array_class");
function.setName(names.topLevel("teavm@fillArrayClass"));
var targetVar = new WasmLocal(standardClasses.classClass().getType(), "target");
var itemVar = new WasmLocal(standardClasses.classClass().getType(), "item");

View File

@ -17,6 +17,7 @@ package org.teavm.backend.wasm.generate.gc.classes;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.generate.TemporaryVariablePool;
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
import org.teavm.backend.wasm.generate.gc.methods.WasmGCGenerationUtil;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmFunctionType;
@ -32,22 +33,26 @@ class WasmGCNewArrayFunctionGenerator {
private WasmFunctionTypes functionTypes;
private WasmGCClassInfoProvider classInfoProvider;
private WasmFunctionType newArrayFunctionType;
private WasmGCNameProvider names;
WasmGCNewArrayFunctionGenerator(WasmModule module, WasmFunctionTypes functionTypes,
WasmGCClassInfoProvider classInfoProvider) {
WasmGCClassInfoProvider classInfoProvider, WasmGCNameProvider names) {
this.module = module;
this.functionTypes = functionTypes;
this.classInfoProvider = classInfoProvider;
this.names = names;
}
WasmFunction generateNewArrayFunction(ValueType itemType) {
var function = new WasmFunction(getNewArrayFunctionType());
function.setName(names.topLevel("Array<" + names.suggestForType(itemType) + ">@new"));
module.functions.add(function);
var sizeLocal = new WasmLocal(WasmType.INT32);
var sizeLocal = new WasmLocal(WasmType.INT32, "length");
function.add(sizeLocal);
var tempVars = new TemporaryVariablePool(function);
var genUtil = new WasmGCGenerationUtil(classInfoProvider, tempVars);
var targetVar = new WasmLocal(classInfoProvider.getClassInfo(ValueType.arrayOf(itemType)).getType());
var targetVar = new WasmLocal(classInfoProvider.getClassInfo(ValueType.arrayOf(itemType)).getType(),
"result");
function.add(targetVar);
genUtil.allocateArray(itemType, new WasmGetLocal(sizeLocal), null, targetVar, function.getBody());
function.getBody().add(new WasmReturn(new WasmGetLocal(targetVar)));

View File

@ -19,8 +19,8 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.teavm.backend.lowlevel.generate.NameProvider;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmFunctionType;
import org.teavm.backend.wasm.model.WasmLocal;
@ -47,7 +47,7 @@ public class WasmGCSupertypeFunctionGenerator implements WasmGCSupertypeFunction
private Map<ValueType, WasmFunction> functions = new HashMap<>();
private WasmModule module;
private WasmGCClassGenerator classGenerator;
private NameProvider nameProvider;
private WasmGCNameProvider nameProvider;
private TagRegistry tagRegistry;
private WasmFunctionTypes functionTypes;
private WasmFunctionType functionType;
@ -55,7 +55,7 @@ public class WasmGCSupertypeFunctionGenerator implements WasmGCSupertypeFunction
WasmGCSupertypeFunctionGenerator(
WasmModule module,
WasmGCClassGenerator classGenerator,
NameProvider nameProvider,
WasmGCNameProvider nameProvider,
TagRegistry tagRegistry,
WasmFunctionTypes functionTypes
) {
@ -78,7 +78,7 @@ public class WasmGCSupertypeFunctionGenerator implements WasmGCSupertypeFunction
private WasmFunction generateIsSupertypeFunction(ValueType type) {
var function = new WasmFunction(getFunctionType());
function.setName(nameProvider.forSupertypeFunction(type));
function.setName(nameProvider.topLevel(nameProvider.suggestForType(type) + "@isSupertypes"));
var subtypeVar = new WasmLocal(classGenerator.standardClasses.classClass().getType(), "subtype");
function.add(subtypeVar);
module.functions.add(function);

View File

@ -25,6 +25,7 @@ import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationContext;
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCSupertypeFunctionProvider;
@ -62,13 +63,15 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
private WasmGlobal exceptionGlobal;
private WasmTag exceptionTag;
private Map<String, Set<String>> interfaceImplementors;
private WasmGCNameProvider names;
public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider virtualTables,
WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ListableClassReaderSource classes,
ClassHierarchy hierarchy, BaseWasmFunctionRepository functions,
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics) {
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics,
WasmGCNameProvider names) {
this.module = module;
this.virtualTables = virtualTables;
this.typeMapper = typeMapper;
@ -82,6 +85,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
this.strings = strings;
this.customGenerators = customGenerators;
this.intrinsics = intrinsics;
this.names = names;
}
public WasmGCClassInfoProvider classInfoProvider() {
@ -164,7 +168,8 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
public WasmGlobal exceptionGlobal() {
if (exceptionGlobal == null) {
var type = classInfoProvider.getClassInfo("java.lang.Throwable").getType();
exceptionGlobal = new WasmGlobal("teavm_thrown_exception", type, new WasmNullConstant(type));
exceptionGlobal = new WasmGlobal(names.topLevel("teavm@thrownException"), type,
new WasmNullConstant(type));
module.globals.add(exceptionGlobal);
}
return exceptionGlobal;

View File

@ -23,11 +23,11 @@ import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import org.teavm.ast.decompilation.Decompiler;
import org.teavm.backend.lowlevel.generate.NameProvider;
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCSupertypeFunctionProvider;
@ -63,7 +63,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
private ClassInitializerInfo classInitInfo;
private WasmFunctionTypes functionTypes;
private WasmGCSupertypeFunctionProvider supertypeFunctions;
private NameProvider names;
private WasmGCNameProvider names;
private Diagnostics diagnostics;
private WasmGCTypeMapper typeMapper;
private WasmGCCustomGeneratorProvider customGenerators;
@ -86,7 +86,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
WasmGCVirtualTableProvider virtualTables,
ClassInitializerInfo classInitInfo,
WasmFunctionTypes functionTypes,
NameProvider names,
WasmGCNameProvider names,
Diagnostics diagnostics,
WasmGCCustomGeneratorProvider customGenerators,
WasmGCIntrinsicProvider intrinsics
@ -149,7 +149,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
parameterTypes[i] = typeMapper.mapType(methodReference.parameterType(i));
}
var function = new WasmFunction(functionTypes.of(returnType, parameterTypes));
function.setName(names.forMethod(methodReference));
function.setName(names.topLevel(names.suggestForMethod(methodReference)));
module.functions.add(function);
function.setJavaMethod(methodReference);
@ -177,7 +177,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
parameterTypes[i + 1] = typeMapper.mapType(methodReference.parameterType(i));
}
var function = new WasmFunction(functionTypes.of(returnType, parameterTypes));
function.setName(names.forMethod(methodReference));
function.setName(names.topLevel(names.suggestForMethod(methodReference)));
module.functions.add(function);
function.setJavaMethod(methodReference);
@ -304,7 +304,8 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
standardClasses,
strings,
customGenerators,
intrinsics
intrinsics,
names
);
}
return context;
@ -314,7 +315,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
if (dummyInitializer == null) {
dummyInitializer = new WasmFunction(functionTypes.of(null));
dummyInitializer.getBody().add(new WasmReturn());
dummyInitializer.setName("teavm_dummy_initializer");
dummyInitializer.setName(names.topLevel("teavm@dummyInitializer"));
dummyInitializer.setReferenced(true);
module.functions.add(dummyInitializer);
}
@ -341,5 +342,10 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
public WasmGCClassInfoProvider classInfoProvider() {
return classInfoProvider;
}
@Override
public WasmGCNameProvider names() {
return names;
}
};
}

View File

@ -20,6 +20,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.generate.gc.WasmGCInitializerContributor;
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
import org.teavm.backend.wasm.model.WasmFunction;
@ -43,12 +44,14 @@ public class WasmGCStringPool implements WasmGCStringProvider, WasmGCInitializer
private Map<String, WasmGCStringConstant> stringMap = new LinkedHashMap<>();
private BaseWasmFunctionRepository functionProvider;
private WasmFunction nextCharArrayFunction;
private WasmGCNameProvider names;
public WasmGCStringPool(WasmGCStandardClasses standardClasses, WasmModule module,
BaseWasmFunctionRepository functionProvider) {
BaseWasmFunctionRepository functionProvider, WasmGCNameProvider names) {
this.standardClasses = standardClasses;
this.module = module;
this.functionProvider = functionProvider;
this.names = names;
}
@Override
@ -86,7 +89,9 @@ public class WasmGCStringPool implements WasmGCStringProvider, WasmGCInitializer
}
binaryWriter.writeLEB(string.length());
binaryWriter.writeBytes(string.getBytes(StandardCharsets.UTF_8));
var globalName = "teavm_java_string_" + stringMap.size();
var brief = string.length() > 16 ? string.substring(0, 16) : string;
var globalName = names.topLevel("teavm@string<" + stringMap.size() + ">"
+ WasmGCNameProvider.sanitize(brief));
var globalType = standardClasses.stringClass().getType();
var global = new WasmGlobal(globalName, globalType, WasmExpression.defaultValueOfType(globalType));
module.globals.add(global);

View File

@ -16,6 +16,7 @@
package org.teavm.backend.wasm.generators.gc;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.generate.gc.WasmGCNameProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
import org.teavm.backend.wasm.model.WasmModule;
@ -28,4 +29,6 @@ public interface WasmGCCustomGeneratorContext {
WasmGCTypeMapper typeMapper();
WasmGCClassInfoProvider classInfoProvider();
WasmGCNameProvider names();
}

View File

@ -36,7 +36,8 @@ public class WasmGCStringPoolGenerator implements WasmGCCustomGenerator {
@Override
public void apply(MethodReference method, WasmFunction function, WasmGCCustomGeneratorContext context) {
var module = context.module();
var pointer = new WasmGlobal("teavm_string_pool_pointer", WasmType.INT32, new WasmInt32Constant(0));
var pointer = new WasmGlobal(context.names().topLevel("teavm@stringPoolPointer"), WasmType.INT32,
new WasmInt32Constant(0));
module.globals.add(pointer);
var resultLocal = new WasmLocal(WasmType.INT32);

View File

@ -71,6 +71,10 @@ public class WasmStructure extends WasmCompositeType {
var supplier = fieldsSupplier;
fieldsSupplier = null;
supplier.accept(fieldsStorage);
for (var field : fieldsStorage) {
field.structure = this;
}
indexesValid = false;
}
}

View File

@ -476,6 +476,30 @@ public class WasmBinaryRenderer {
section.writeLEB(payload.length);
section.writeBytes(payload);
var functionsWithLocalNames = module.functions.stream()
.filter(fn -> fn.getLocalVariables().stream().anyMatch(v -> v.getName() != null))
.collect(Collectors.toList());
if (!functionsWithLocalNames.isEmpty()) {
var subsection = new WasmBinaryWriter();
subsection.writeLEB(functionsWithLocalNames.size());
for (var function : functionsWithLocalNames) {
subsection.writeLEB(module.functions.indexOf(function));
var locals = function.getLocalVariables().stream()
.filter(t -> t.getName() != null)
.collect(Collectors.toList());
subsection.writeLEB(locals.size());
for (var local : locals) {
subsection.writeLEB(local.getIndex());
subsection.writeAsciiString(local.getName());
}
}
payload = subsection.getData();
section.writeLEB(2);
section.writeLEB(payload.length);
section.writeBytes(payload);
}
var types = module.types.stream()
.filter(t -> t.getName() != null)
.collect(Collectors.toList());