wasm gc: group structurally equal different substructures into recursive group in order to benefit from using native ref.test/rest.cast instructions for classes

This commit is contained in:
Alexey Andreev 2024-09-18 13:24:29 +02:00
parent 55ac5d0321
commit 944fd22513
4 changed files with 70 additions and 3 deletions

View File

@ -300,6 +300,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
var structName = names.topLevel(names.suggestForType(type));
classInfo.structure = new WasmStructure(structName,
fields -> fillFields(finalClassInfo, fields, type));
classInfo.structure.setNominal(true);
module.types.add(classInfo.structure);
nonInitializedStructures.add(classInfo.structure);
}

View File

@ -81,6 +81,7 @@ import org.teavm.backend.wasm.model.expression.WasmTest;
import org.teavm.backend.wasm.model.expression.WasmThrow;
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
import org.teavm.model.ClassHierarchy;
import org.teavm.model.ElementModifier;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference;
import org.teavm.model.TextLocation;
@ -517,7 +518,7 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
}
private boolean canCastNatively(ValueType type) {
/*if (type instanceof ValueType.Array) {
if (type instanceof ValueType.Array) {
return true;
}
var className = ((ValueType.Object) type).getClassName();
@ -525,8 +526,7 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
if (cls == null) {
return false;
}
return !cls.hasModifier(ElementModifier.INTERFACE);*/
return false;
return !cls.hasModifier(ElementModifier.INTERFACE);
}
@Override

View File

@ -25,6 +25,7 @@ public class WasmStructure extends WasmCompositeType {
private List<WasmField> fieldsStorage = new ArrayList<>();
private WasmStructure supertype;
private boolean indexesValid = true;
private boolean nominal;
public WasmStructure(String name) {
super(name);
@ -57,6 +58,14 @@ public class WasmStructure extends WasmCompositeType {
return false;
}
public boolean isNominal() {
return nominal;
}
public void setNominal(boolean nominal) {
this.nominal = nominal;
}
void ensureIndexes() {
if (!indexesValid) {
indexesValid = true;

View File

@ -15,6 +15,9 @@
*/
package org.teavm.backend.wasm.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.teavm.common.Graph;
import org.teavm.common.GraphBuilder;
@ -29,9 +32,63 @@ final class WasmTypeGraphBuilder {
visitor.currentIndex = module.types.indexOf(type);
type.acceptVisitor(visitor);
}
addNominalStructures(module, types, graphBuilder);
return graphBuilder.build();
}
private static void addNominalStructures(WasmModule module, Iterable<WasmCompositeType> types,
GraphBuilder graphBuilder) {
var subStructures = new HashMap<WasmStructure, List<WasmStructure>>();
var topLevelStructures = new ArrayList<WasmStructure>();
for (var type : types) {
if (type instanceof WasmStructure) {
var structure = (WasmStructure) type;
if (structure.isNominal()) {
if (structure.getSupertype() != null) {
subStructures.computeIfAbsent(structure.getSupertype(), k -> new ArrayList<>()).add(structure);
} else {
topLevelStructures.add(structure);
}
}
}
}
mergeNominalStructures(module, topLevelStructures, 0, graphBuilder);
for (var entry : subStructures.entrySet()) {
mergeNominalStructures(module, entry.getValue(), entry.getKey().getFields().size(), graphBuilder);
}
}
private static void mergeNominalStructures(WasmModule module, List<WasmStructure> structures, int parentFieldCount,
GraphBuilder graphBuilder) {
outer: for (var i = 0; i < structures.size(); i++) {
for (var j = i + 1; j < structures.size(); j++) {
var a = structures.get(i);
var b = structures.get(j);
if (areSameStructures(parentFieldCount, a, b)) {
var p = module.types.indexOf(a);
var q = module.types.indexOf(b);
graphBuilder.addEdge(p, q);
graphBuilder.addEdge(q, p);
continue outer;
}
}
}
}
private static boolean areSameStructures(int start, WasmStructure a, WasmStructure b) {
if (a.getFields().size() != b.getFields().size()) {
return false;
}
for (var i = start; i < a.getFields().size(); i++) {
if (a.getFields().get(i).getType() != b.getFields().get(i).getType()) {
return false;
}
}
return true;
}
private static class GraphBuilderVisitor implements WasmCompositeTypeVisitor {
final WasmModule module;
final GraphBuilder graphBuilder;