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( var function = declarationsGenerator.functions().forStaticMethod(new MethodReference(
WasmGCSupport.class, "createStringArray", int.class, String[].class)); WasmGCSupport.class, "createStringArray", int.class, String[].class));
var caller = new WasmFunction(function.getType()); var caller = new WasmFunction(function.getType());
var sizeLocal = new WasmLocal(WasmType.INT32); var sizeLocal = new WasmLocal(WasmType.INT32, "length");
caller.add(sizeLocal); caller.add(sizeLocal);
caller.getBody().add(callInitializer()); caller.getBody().add(callInitializer());
caller.getBody().add(new WasmReturn(new WasmCall(function, new WasmGetLocal(sizeLocal)))); 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)); StringBuilder.class, "append", char.class, StringBuilder.class));
var stringBuilderType = declarationsGenerator.typeMapper().mapType(ValueType.parse(StringBuilder.class)); var stringBuilderType = declarationsGenerator.typeMapper().mapType(ValueType.parse(StringBuilder.class));
var caller = new WasmFunction(declarationsGenerator.functionTypes.of(null, stringBuilderType, WasmType.INT32)); var caller = new WasmFunction(declarationsGenerator.functionTypes.of(null, stringBuilderType, WasmType.INT32));
var stringBuilderLocal = new WasmLocal(stringBuilderType); var stringBuilderLocal = new WasmLocal(stringBuilderType, "stringBuilder");
var codeLocal = new WasmLocal(WasmType.INT32); var codeLocal = new WasmLocal(WasmType.INT32, "charCode");
caller.add(stringBuilderLocal); caller.add(stringBuilderLocal);
caller.add(codeLocal); caller.add(codeLocal);
caller.getBody().add(callInitializer()); caller.getBody().add(callInitializer());
@ -116,7 +116,7 @@ public class WasmGCModuleGenerator {
var stringBuilderType = declarationsGenerator.typeMapper().mapType(ValueType.parse(StringBuilder.class)); var stringBuilderType = declarationsGenerator.typeMapper().mapType(ValueType.parse(StringBuilder.class));
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class)); var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
var caller = new WasmFunction(declarationsGenerator.functionTypes.of(stringType, stringBuilderType)); var caller = new WasmFunction(declarationsGenerator.functionTypes.of(stringType, stringBuilderType));
var stringBuilderLocal = new WasmLocal(stringBuilderType); var stringBuilderLocal = new WasmLocal(stringBuilderType, "stringBuilder");
caller.add(stringBuilderLocal); caller.add(stringBuilderLocal);
caller.getBody().add(callInitializer()); caller.getBody().add(callInitializer());
caller.getBody().add(new WasmReturn(new WasmCall(function, new WasmGetLocal(stringBuilderLocal)))); 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 stringArrayType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String[].class));
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class)); var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
var caller = new WasmFunction(function.getType()); var caller = new WasmFunction(function.getType());
var arrayLocal = new WasmLocal(stringArrayType); var arrayLocal = new WasmLocal(stringArrayType, "array");
var indexLocal = new WasmLocal(WasmType.INT32); var indexLocal = new WasmLocal(WasmType.INT32, "index");
var valueLocal = new WasmLocal(stringType); var valueLocal = new WasmLocal(stringType, "string");
caller.add(arrayLocal); caller.add(arrayLocal);
caller.add(indexLocal); caller.add(indexLocal);
caller.add(valueLocal); caller.add(valueLocal);
@ -148,7 +148,7 @@ public class WasmGCModuleGenerator {
String.class, "length", int.class)); String.class, "length", int.class));
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class)); var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
var caller = new WasmFunction(function.getType()); var caller = new WasmFunction(function.getType());
var stringLocal = new WasmLocal(stringType); var stringLocal = new WasmLocal(stringType, "string");
caller.add(stringLocal); caller.add(stringLocal);
caller.getBody().add(callInitializer()); caller.getBody().add(callInitializer());
caller.getBody().add(new WasmReturn(new WasmCall(function, new WasmGetLocal(stringLocal)))); 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)); String.class, "charAt", int.class, char.class));
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class)); var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
var caller = new WasmFunction(function.getType()); var caller = new WasmFunction(function.getType());
var stringLocal = new WasmLocal(stringType); var stringLocal = new WasmLocal(stringType, "string");
var indexLocal = new WasmLocal(WasmType.INT32); var indexLocal = new WasmLocal(WasmType.INT32, "index");
caller.add(stringLocal); caller.add(stringLocal);
caller.add(indexLocal); caller.add(indexLocal);
caller.getBody().add(callInitializer()); caller.getBody().add(callInitializer());
@ -180,7 +180,7 @@ public class WasmGCModuleGenerator {
initializer = new WasmFunction(functionType); initializer = new WasmFunction(functionType);
initializer.setReferenced(true); initializer.setReferenced(true);
declarationsGenerator.module.functions.add(initializer); declarationsGenerator.module.functions.add(initializer);
initializerRef = new WasmGlobal("teavm_initializer", functionType.getReference(), initializerRef = new WasmGlobal("teavm@initializer", functionType.getReference(),
new WasmFunctionReference(initializer)); new WasmFunctionReference(initializer));
declarationsGenerator.module.globals.add(initializerRef); declarationsGenerator.module.globals.add(initializerRef);
initializer.getBody().add(new WasmSetGlobal(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.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes; import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider; 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.WasmGCClassGenerator;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider; import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCSupertypeFunctionProvider; import org.teavm.backend.wasm.generate.gc.classes.WasmGCSupertypeFunctionProvider;
@ -61,7 +60,7 @@ public class WasmGCDeclarationsGenerator {
hierarchy = new ClassHierarchy(classes); hierarchy = new ClassHierarchy(classes);
var virtualTables = createVirtualTableProvider(classes, isVirtual); var virtualTables = createVirtualTableProvider(classes, isVirtual);
functionTypes = new WasmFunctionTypes(module); functionTypes = new WasmFunctionTypes(module);
var names = new WasmNameProvider(); var names = new WasmGCNameProvider();
methodGenerator = new WasmGCMethodGenerator( methodGenerator = new WasmGCMethodGenerator(
module, module,
hierarchy, 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.Map;
import java.util.Queue; import java.util.Queue;
import java.util.function.Consumer; import java.util.function.Consumer;
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.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.WasmGCNameProvider;
import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringPool; import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringPool;
import org.teavm.backend.wasm.model.WasmArray; import org.teavm.backend.wasm.model.WasmArray;
import org.teavm.backend.wasm.model.WasmField; import org.teavm.backend.wasm.model.WasmField;
@ -106,12 +106,13 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
public final WasmGCStringPool strings; public final WasmGCStringPool strings;
public final WasmGCStandardClasses standardClasses; public final WasmGCStandardClasses standardClasses;
public final WasmGCTypeMapper typeMapper; public final WasmGCTypeMapper typeMapper;
private final NameProvider names; private final WasmGCNameProvider names;
private List<WasmExpression> initializerFunctionStatements = new ArrayList<>(); private List<WasmExpression> initializerFunctionStatements = new ArrayList<>();
private WasmFunction createPrimitiveClassFunction; private WasmFunction createPrimitiveClassFunction;
private WasmFunction createArrayClassFunction; private WasmFunction createArrayClassFunction;
private final WasmGCSupertypeFunctionGenerator supertypeGenerator; private final WasmGCSupertypeFunctionGenerator supertypeGenerator;
private final WasmGCNewArrayFunctionGenerator newArrayGenerator; private final WasmGCNewArrayFunctionGenerator newArrayGenerator;
private String arrayDataFieldName;
private int classTagOffset; private int classTagOffset;
private int classFlagsOffset; private int classFlagsOffset;
@ -134,7 +135,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource, public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource,
WasmFunctionTypes functionTypes, TagRegistry tagRegistry, WasmFunctionTypes functionTypes, TagRegistry tagRegistry,
ClassMetadataRequirements metadataRequirements, WasmGCVirtualTableProvider virtualTables, ClassMetadataRequirements metadataRequirements, WasmGCVirtualTableProvider virtualTables,
BaseWasmFunctionRepository functionProvider, NameProvider names, BaseWasmFunctionRepository functionProvider, WasmGCNameProvider names,
ClassInitializerInfo classInitializerInfo) { ClassInitializerInfo classInitializerInfo) {
this.module = module; this.module = module;
this.classSource = classSource; this.classSource = classSource;
@ -146,9 +147,9 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
this.names = names; this.names = names;
this.classInitializerInfo = classInitializerInfo; this.classInitializerInfo = classInitializerInfo;
standardClasses = new WasmGCStandardClasses(this); 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); 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); typeMapper = new WasmGCTypeMapper(classSource, this, functionTypes, module);
} }
@ -279,7 +280,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
} }
} }
if (classInfo.structure == null) { 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)); fields -> fillFields(finalClassInfo, fields, type));
module.types.add(classInfo.structure); module.types.add(classInfo.structure);
nonInitializedStructures.add(classInfo.structure); nonInitializedStructures.add(classInfo.structure);
@ -297,7 +299,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
classInfo.structure.setSupertype(standardClasses.objectClass().structure); 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(); classInfo.hasOwnVirtualTable = virtualTable != null && !virtualTable.getEntries().isEmpty();
WasmStructure classStructure; WasmStructure classStructure;
if (classInfo.hasOwnVirtualTable) { if (classInfo.hasOwnVirtualTable) {
@ -419,7 +421,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
if (classInitializerInfo.isDynamicInitializer(name)) { if (classInitializerInfo.isDynamicInitializer(name)) {
if (cls != null && cls.getMethod(CLINIT_METHOD_DESC) != null) { if (cls != null && cls.getMethod(CLINIT_METHOD_DESC) != null) {
var clinitType = functionTypes.of(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())); new WasmNullConstant(clinitType.getReference()));
module.globals.add(classInfo.initializerPointer); module.globals.add(classInfo.initializerPointer);
} }
@ -467,10 +470,11 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
WasmStructure objectStructure) { WasmStructure objectStructure) {
var virtualTable = virtualTables.lookup("java.lang.Object"); var virtualTable = virtualTables.lookup("java.lang.Object");
var structure = getArrayVirtualTableStructure(); var structure = getArrayVirtualTableStructure();
var itemType = ((ValueType.Array) type).getItemType();
for (var entry : virtualTable.getEntries()) { for (var entry : virtualTable.getEntries()) {
if (entry.getMethod().getName().equals("clone")) { if (entry.getMethod().getName().equals("clone")) {
var function = generateArrayCloneMethod(objectStructure); var function = generateArrayCloneMethod(objectStructure, itemType);
function.setReferenced(true); function.setReferenced(true);
var ref = new WasmFunctionReference(function); var ref = new WasmFunctionReference(function);
var fieldIndex = virtualTableFieldOffset + entry.getIndex(); 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); var info = metadataRequirements.getInfo(type);
if (info.arrayLength()) { if (info.arrayLength()) {
var lengthFunction = getArrayLengthFunction(objectStructure); var lengthFunction = getArrayLengthFunction(objectStructure);
@ -502,19 +505,20 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var elementType = arrayType.getElementType().asUnpackedType(); var elementType = arrayType.getElementType().asUnpackedType();
if (elementType instanceof WasmType.Reference) { if (elementType instanceof WasmType.Reference) {
if (arrayLengthObjectFunction == null) { if (arrayLengthObjectFunction == null) {
arrayLengthObjectFunction = getArrayLengthFunction(objectStructure, arrayType); arrayLengthObjectFunction = createArrayLengthFunction(objectStructure);
} }
return arrayLengthObjectFunction; 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())); var function = new WasmFunction(functionTypes.of(WasmType.INT32, standardClasses.objectClass().getType()));
function.setReferenced(true); function.setReferenced(true);
function.setName(names.topLevel("Array<*>::length"));
module.functions.add(function); module.functions.add(function);
var objectLocal = new WasmLocal(standardClasses.objectClass().getType()); var objectLocal = new WasmLocal(standardClasses.objectClass().getType(), "object");
function.add(objectLocal); function.add(objectLocal);
var castObject = new WasmCast(new WasmGetLocal(objectLocal), objectStructure.getReference()); var castObject = new WasmCast(new WasmGetLocal(objectLocal), objectStructure.getReference());
@ -534,6 +538,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
private WasmFunction getArrayGetObjectFunction() { private WasmFunction getArrayGetObjectFunction() {
if (arrayGetObjectFunction == null) { if (arrayGetObjectFunction == null) {
arrayGetObjectFunction = new WasmFunction(getArrayGetType()); arrayGetObjectFunction = new WasmFunction(getArrayGetType());
arrayGetObjectFunction.setName(names.topLevel("Array<" + names.suggestForClass("java.lang.Object")
+ "::get"));
module.functions.add(arrayGetObjectFunction); module.functions.add(arrayGetObjectFunction);
arrayGetObjectFunction.setReferenced(true); arrayGetObjectFunction.setReferenced(true);
@ -541,8 +547,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var arrayDataTypeRef = (WasmType.CompositeReference) arrayStruct.getFields() var arrayDataTypeRef = (WasmType.CompositeReference) arrayStruct.getFields()
.get(ARRAY_DATA_FIELD_OFFSET).getUnpackedType(); .get(ARRAY_DATA_FIELD_OFFSET).getUnpackedType();
var arrayDataType = (WasmArray) arrayDataTypeRef.composite; var arrayDataType = (WasmArray) arrayDataTypeRef.composite;
var objectLocal = new WasmLocal(standardClasses.objectClass().getType()); var objectLocal = new WasmLocal(standardClasses.objectClass().getType(), "object");
var indexLocal = new WasmLocal(WasmType.INT32); var indexLocal = new WasmLocal(WasmType.INT32, "index");
arrayGetObjectFunction.add(objectLocal); arrayGetObjectFunction.add(objectLocal);
arrayGetObjectFunction.add(indexLocal); arrayGetObjectFunction.add(indexLocal);
@ -556,6 +562,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
private WasmFunction generateArrayGetPrimitiveFunction(PrimitiveType type) { private WasmFunction generateArrayGetPrimitiveFunction(PrimitiveType type) {
var function = new WasmFunction(getArrayGetType()); var function = new WasmFunction(getArrayGetType());
arrayGetObjectFunction.setName(names.topLevel("Array<" + names.suggestForType(ValueType.primitive(type))
+ ">::get"));
module.functions.add(function); module.functions.add(function);
function.setReferenced(true); function.setReferenced(true);
@ -563,8 +571,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var arrayDataTypeRef = (WasmType.CompositeReference) arrayStruct.getFields() var arrayDataTypeRef = (WasmType.CompositeReference) arrayStruct.getFields()
.get(ARRAY_DATA_FIELD_OFFSET).getUnpackedType(); .get(ARRAY_DATA_FIELD_OFFSET).getUnpackedType();
var arrayDataType = (WasmArray) arrayDataTypeRef.composite; var arrayDataType = (WasmArray) arrayDataTypeRef.composite;
var objectLocal = new WasmLocal(standardClasses.objectClass().getType()); var objectLocal = new WasmLocal(standardClasses.objectClass().getType(), "object");
var indexLocal = new WasmLocal(WasmType.INT32); var indexLocal = new WasmLocal(WasmType.INT32, "index");
function.add(objectLocal); function.add(objectLocal);
function.add(indexLocal); function.add(indexLocal);
@ -644,6 +652,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
if (!entry.getOrigin().getClassName().equals(implementor.getClassName()) if (!entry.getOrigin().getClassName().equals(implementor.getClassName())
|| expectedFunctionType != function.getType()) { || expectedFunctionType != function.getType()) {
var wrapperFunction = new WasmFunction(expectedFunctionType); var wrapperFunction = new WasmFunction(expectedFunctionType);
wrapperFunction.setName(names.topLevel(names.suggestForMethod(implementor) + "@caller"));
module.functions.add(wrapperFunction); module.functions.add(wrapperFunction);
var call = new WasmCall(function); var call = new WasmCall(function);
var instanceParam = new WasmLocal(getClassInfo(virtualTable.getClassName()).getType()); 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( var arrayTypeRef = (WasmType.CompositeReference) objectStructure.getFields().get(
WasmGCClassInfoProvider.ARRAY_DATA_FIELD_OFFSET).getUnpackedType(); WasmGCClassInfoProvider.ARRAY_DATA_FIELD_OFFSET).getUnpackedType();
var arrayType = (WasmArray) arrayTypeRef.composite; var arrayType = (WasmArray) arrayTypeRef.composite;
var type = typeMapper.getFunctionType(standardClasses.objectClass().getType(), CLONE_METHOD_DESC, false); var type = typeMapper.getFunctionType(standardClasses.objectClass().getType(), CLONE_METHOD_DESC, false);
var function = new WasmFunction(type); var function = new WasmFunction(type);
function.setName(names.topLevel("Array<" + names.suggestForType(itemType) + ">::clone"));
module.functions.add(function); module.functions.add(function);
var instanceLocal = new WasmLocal(standardClasses.objectClass().getType()); var instanceLocal = new WasmLocal(standardClasses.objectClass().getType(), "instance");
var originalLocal = new WasmLocal(objectStructure.getReference()); var originalLocal = new WasmLocal(objectStructure.getReference(), "original");
var resultLocal = new WasmLocal(objectStructure.getReference()); var resultLocal = new WasmLocal(objectStructure.getReference(), "result");
var originalDataLocal = new WasmLocal(arrayType.getReference()); var originalDataLocal = new WasmLocal(arrayType.getReference(), "originalData");
var dataCopyLocal = new WasmLocal(arrayType.getReference()); var dataCopyLocal = new WasmLocal(arrayType.getReference(), "resultData");
function.add(instanceLocal); function.add(instanceLocal);
function.add(originalLocal); function.add(originalLocal);
function.add(resultLocal); function.add(resultLocal);
@ -712,7 +722,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
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), fields -> { var wasmName = names.topLevel("Class<" + names.suggestForClass(className) + ">");
var structure = new WasmStructure(wasmName, fields -> {
addSystemFields(fields); addSystemFields(fields);
fillSimpleClassFields(fields, "java.lang.Class"); fillSimpleClassFields(fields, "java.lang.Class");
addVirtualTableFields(fields, virtualTable); addVirtualTableFields(fields, virtualTable);
@ -744,19 +755,22 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
@Override @Override
public WasmStructure getArrayVirtualTableStructure() { public WasmStructure getArrayVirtualTableStructure() {
if (arrayVirtualTableStruct == null) { if (arrayVirtualTableStruct == null) {
arrayVirtualTableStruct = new WasmStructure(null, fields -> { var wasmName = names.topLevel("Class<Array<*>>");
arrayVirtualTableStruct = new WasmStructure(wasmName, fields -> {
addSystemFields(fields); addSystemFields(fields);
fillSimpleClassFields(fields, "java.lang.Class"); fillSimpleClassFields(fields, "java.lang.Class");
addVirtualTableFields(fields, virtualTables.lookup("java.lang.Object")); addVirtualTableFields(fields, virtualTables.lookup("java.lang.Object"));
if (metadataRequirements.hasArrayLength()) { if (metadataRequirements.hasArrayLength()) {
arrayLengthOffset = fields.size(); arrayLengthOffset = fields.size();
var arrayLengthType = getArrayLengthType(); var arrayLengthType = getArrayLengthType();
fields.add(new WasmField(arrayLengthType.getReference().asStorage())); fields.add(new WasmField(arrayLengthType.getReference().asStorage(),
names.structureField("@arrayLength")));
} }
if (metadataRequirements.hasArrayGet()) { if (metadataRequirements.hasArrayGet()) {
arrayGetOffset = fields.size(); arrayGetOffset = fields.size();
var arrayGetType = getArrayGetType(); 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()); arrayVirtualTableStruct.setSupertype(standardClasses.objectClass().getVirtualTableStructure());
@ -830,7 +844,8 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var type = typeMapper.mapType(javaType); var type = typeMapper.mapType(javaType);
var wasmInitialValue = initValue != null ? initialValue(initValue) : WasmExpression.defaultValueOfType(type); 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); dynamicInitialValue(global, initValue);
module.globals.add(global); module.globals.add(global);
@ -968,9 +983,18 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
} else { } else {
wasmElementType = standardClasses.objectClass().getType().asStorage(); 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); 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() { private WasmFunction getCreatePrimitiveClassFunction() {
@ -988,7 +1012,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
WasmType.INT32 WasmType.INT32
); );
var function = new WasmFunction(functionType); var function = new WasmFunction(functionType);
function.setName("teavm_fill_primitive_class"); function.setName(names.topLevel("teavm@fill_primitive_class"));
module.functions.add(function); module.functions.add(function);
var targetVar = new WasmLocal(standardClasses.classClass().getType(), "target"); var targetVar = new WasmLocal(standardClasses.classClass().getType(), "target");
@ -1047,7 +1071,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
); );
var function = new WasmFunction(functionType); var function = new WasmFunction(functionType);
module.functions.add(function); 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 targetVar = new WasmLocal(standardClasses.classClass().getType(), "target");
var itemVar = new WasmLocal(standardClasses.classClass().getType(), "item"); 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.WasmFunctionTypes;
import org.teavm.backend.wasm.generate.TemporaryVariablePool; 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.generate.gc.methods.WasmGCGenerationUtil;
import org.teavm.backend.wasm.model.WasmFunction; import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmFunctionType; import org.teavm.backend.wasm.model.WasmFunctionType;
@ -32,22 +33,26 @@ class WasmGCNewArrayFunctionGenerator {
private WasmFunctionTypes functionTypes; private WasmFunctionTypes functionTypes;
private WasmGCClassInfoProvider classInfoProvider; private WasmGCClassInfoProvider classInfoProvider;
private WasmFunctionType newArrayFunctionType; private WasmFunctionType newArrayFunctionType;
private WasmGCNameProvider names;
WasmGCNewArrayFunctionGenerator(WasmModule module, WasmFunctionTypes functionTypes, WasmGCNewArrayFunctionGenerator(WasmModule module, WasmFunctionTypes functionTypes,
WasmGCClassInfoProvider classInfoProvider) { WasmGCClassInfoProvider classInfoProvider, WasmGCNameProvider names) {
this.module = module; this.module = module;
this.functionTypes = functionTypes; this.functionTypes = functionTypes;
this.classInfoProvider = classInfoProvider; this.classInfoProvider = classInfoProvider;
this.names = names;
} }
WasmFunction generateNewArrayFunction(ValueType itemType) { WasmFunction generateNewArrayFunction(ValueType itemType) {
var function = new WasmFunction(getNewArrayFunctionType()); var function = new WasmFunction(getNewArrayFunctionType());
function.setName(names.topLevel("Array<" + names.suggestForType(itemType) + ">@new"));
module.functions.add(function); module.functions.add(function);
var sizeLocal = new WasmLocal(WasmType.INT32); var sizeLocal = new WasmLocal(WasmType.INT32, "length");
function.add(sizeLocal); function.add(sizeLocal);
var tempVars = new TemporaryVariablePool(function); var tempVars = new TemporaryVariablePool(function);
var genUtil = new WasmGCGenerationUtil(classInfoProvider, tempVars); 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); function.add(targetVar);
genUtil.allocateArray(itemType, new WasmGetLocal(sizeLocal), null, targetVar, function.getBody()); genUtil.allocateArray(itemType, new WasmGetLocal(sizeLocal), null, targetVar, function.getBody());
function.getBody().add(new WasmReturn(new WasmGetLocal(targetVar))); 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.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.teavm.backend.lowlevel.generate.NameProvider;
import org.teavm.backend.wasm.WasmFunctionTypes; 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.WasmFunction;
import org.teavm.backend.wasm.model.WasmFunctionType; import org.teavm.backend.wasm.model.WasmFunctionType;
import org.teavm.backend.wasm.model.WasmLocal; import org.teavm.backend.wasm.model.WasmLocal;
@ -47,7 +47,7 @@ public class WasmGCSupertypeFunctionGenerator implements WasmGCSupertypeFunction
private Map<ValueType, WasmFunction> functions = new HashMap<>(); private Map<ValueType, WasmFunction> functions = new HashMap<>();
private WasmModule module; private WasmModule module;
private WasmGCClassGenerator classGenerator; private WasmGCClassGenerator classGenerator;
private NameProvider nameProvider; private WasmGCNameProvider nameProvider;
private TagRegistry tagRegistry; private TagRegistry tagRegistry;
private WasmFunctionTypes functionTypes; private WasmFunctionTypes functionTypes;
private WasmFunctionType functionType; private WasmFunctionType functionType;
@ -55,7 +55,7 @@ public class WasmGCSupertypeFunctionGenerator implements WasmGCSupertypeFunction
WasmGCSupertypeFunctionGenerator( WasmGCSupertypeFunctionGenerator(
WasmModule module, WasmModule module,
WasmGCClassGenerator classGenerator, WasmGCClassGenerator classGenerator,
NameProvider nameProvider, WasmGCNameProvider nameProvider,
TagRegistry tagRegistry, TagRegistry tagRegistry,
WasmFunctionTypes functionTypes WasmFunctionTypes functionTypes
) { ) {
@ -78,7 +78,7 @@ public class WasmGCSupertypeFunctionGenerator implements WasmGCSupertypeFunction
private WasmFunction generateIsSupertypeFunction(ValueType type) { private WasmFunction generateIsSupertypeFunction(ValueType type) {
var function = new WasmFunction(getFunctionType()); 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"); var subtypeVar = new WasmLocal(classGenerator.standardClasses.classClass().getType(), "subtype");
function.add(subtypeVar); function.add(subtypeVar);
module.functions.add(function); 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.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider; import org.teavm.backend.wasm.gc.vtable.WasmGCVirtualTableProvider;
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationContext; 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.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses; import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCSupertypeFunctionProvider; import org.teavm.backend.wasm.generate.gc.classes.WasmGCSupertypeFunctionProvider;
@ -62,13 +63,15 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
private WasmGlobal exceptionGlobal; private WasmGlobal exceptionGlobal;
private WasmTag exceptionTag; private WasmTag exceptionTag;
private Map<String, Set<String>> interfaceImplementors; private Map<String, Set<String>> interfaceImplementors;
private WasmGCNameProvider names;
public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider virtualTables, public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider virtualTables,
WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ListableClassReaderSource classes, WasmGCTypeMapper typeMapper, WasmFunctionTypes functionTypes, ListableClassReaderSource classes,
ClassHierarchy hierarchy, BaseWasmFunctionRepository functions, ClassHierarchy hierarchy, BaseWasmFunctionRepository functions,
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider, WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings, WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics) { WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics,
WasmGCNameProvider names) {
this.module = module; this.module = module;
this.virtualTables = virtualTables; this.virtualTables = virtualTables;
this.typeMapper = typeMapper; this.typeMapper = typeMapper;
@ -82,6 +85,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
this.strings = strings; this.strings = strings;
this.customGenerators = customGenerators; this.customGenerators = customGenerators;
this.intrinsics = intrinsics; this.intrinsics = intrinsics;
this.names = names;
} }
public WasmGCClassInfoProvider classInfoProvider() { public WasmGCClassInfoProvider classInfoProvider() {
@ -164,7 +168,8 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
public WasmGlobal exceptionGlobal() { public WasmGlobal exceptionGlobal() {
if (exceptionGlobal == null) { if (exceptionGlobal == null) {
var type = classInfoProvider.getClassInfo("java.lang.Throwable").getType(); 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); module.globals.add(exceptionGlobal);
} }
return exceptionGlobal; return exceptionGlobal;

View File

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

View File

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

View File

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

View File

@ -36,7 +36,8 @@ public class WasmGCStringPoolGenerator implements WasmGCCustomGenerator {
@Override @Override
public void apply(MethodReference method, WasmFunction function, WasmGCCustomGeneratorContext context) { public void apply(MethodReference method, WasmFunction function, WasmGCCustomGeneratorContext context) {
var module = context.module(); 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); module.globals.add(pointer);
var resultLocal = new WasmLocal(WasmType.INT32); var resultLocal = new WasmLocal(WasmType.INT32);

View File

@ -71,6 +71,10 @@ public class WasmStructure extends WasmCompositeType {
var supplier = fieldsSupplier; var supplier = fieldsSupplier;
fieldsSupplier = null; fieldsSupplier = null;
supplier.accept(fieldsStorage); 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.writeLEB(payload.length);
section.writeBytes(payload); 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() var types = module.types.stream()
.filter(t -> t.getName() != null) .filter(t -> t.getName() != null)
.collect(Collectors.toList()); .collect(Collectors.toList());