wasm gc: reduce number of generated virtual table entries, reduce size of a simple program

This commit is contained in:
Alexey Andreev 2024-08-23 21:09:55 +02:00
parent 3e19ca341e
commit 4a345610cf
6 changed files with 22 additions and 9 deletions

View File

@ -15,10 +15,10 @@
*/ */
package org.teavm.classlib.impl.console; package org.teavm.classlib.impl.console;
import java.io.OutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult; import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction; import java.nio.charset.CodingErrorAction;
@ -30,7 +30,7 @@ public abstract class JsConsolePrintStream extends PrintStream {
private Runnable flushAction; private Runnable flushAction;
public JsConsolePrintStream() { public JsConsolePrintStream() {
super((OutputStream) null); super(null, false, (Charset) null);
} }
@Override @Override

View File

@ -122,7 +122,8 @@ public class WasmGCTarget implements TeaVMTarget {
controller.getDependencyInfo(), controller.getDependencyInfo(),
controller.getDiagnostics(), controller.getDiagnostics(),
customGenerators, customGenerators,
intrinsics intrinsics,
controller::isVirtual
); );
declarationsGenerator.setFriendlyToDebugger(controller.isFriendlyToDebugger()); declarationsGenerator.setFriendlyToDebugger(controller.isFriendlyToDebugger());
var moduleGenerator = new WasmGCModuleGenerator(declarationsGenerator); var moduleGenerator = new WasmGCModuleGenerator(declarationsGenerator);

View File

@ -24,6 +24,7 @@ import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.teavm.common.LCATree; import org.teavm.common.LCATree;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
@ -35,6 +36,7 @@ import org.teavm.model.MethodReference;
class WasmGCVirtualTableBuilder { class WasmGCVirtualTableBuilder {
ListableClassReaderSource classes; ListableClassReaderSource classes;
Collection<MethodReference> methodsAtCallSites; Collection<MethodReference> methodsAtCallSites;
Predicate<MethodReference> isVirtual;
private Map<String, Set<MethodDescriptor>> groupedMethodsAtCallSites = new HashMap<>(); private Map<String, Set<MethodDescriptor>> groupedMethodsAtCallSites = new HashMap<>();
private List<Table> tables = new ArrayList<>(); private List<Table> tables = new ArrayList<>();
private Map<String, Table> tableMap = new HashMap<>(); private Map<String, Table> tableMap = new HashMap<>();
@ -178,6 +180,9 @@ class WasmGCVirtualTableBuilder {
if (method.getProgram() == null && !method.hasModifier(ElementModifier.NATIVE)) { if (method.getProgram() == null && !method.hasModifier(ElementModifier.NATIVE)) {
continue; continue;
} }
if (!isVirtual.test(method.getReference())) {
continue;
}
var index = indexes.getOrDefault(method.getDescriptor(), -1); var index = indexes.getOrDefault(method.getDescriptor(), -1);
if (index >= 0) { if (index >= 0) {
table.implementors.set(index, method.getReference()); table.implementors.set(index, method.getReference());

View File

@ -17,6 +17,7 @@ package org.teavm.backend.wasm.gc.vtable;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate;
import org.teavm.model.ListableClassReaderSource; import org.teavm.model.ListableClassReaderSource;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
@ -24,10 +25,11 @@ public class WasmGCVirtualTableProvider {
private Map<String, WasmGCVirtualTable> virtualTables; private Map<String, WasmGCVirtualTable> virtualTables;
public WasmGCVirtualTableProvider(ListableClassReaderSource classes, public WasmGCVirtualTableProvider(ListableClassReaderSource classes,
Collection<MethodReference> methodsAtCallSites) { Collection<MethodReference> methodsAtCallSites, Predicate<MethodReference> isVirtual) {
var builder = new WasmGCVirtualTableBuilder(); var builder = new WasmGCVirtualTableBuilder();
builder.classes = classes; builder.classes = classes;
builder.methodsAtCallSites = methodsAtCallSites; builder.methodsAtCallSites = methodsAtCallSites;
builder.isVirtual = isVirtual;
builder.build(); builder.build();
virtualTables = builder.result; virtualTables = builder.result;
} }

View File

@ -16,6 +16,7 @@
package org.teavm.backend.wasm.generate.gc; package org.teavm.backend.wasm.generate.gc;
import java.util.List; import java.util.List;
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;
@ -33,6 +34,7 @@ import org.teavm.dependency.DependencyInfo;
import org.teavm.diagnostics.Diagnostics; import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.ClassHierarchy; import org.teavm.model.ClassHierarchy;
import org.teavm.model.ListableClassHolderSource; import org.teavm.model.ListableClassHolderSource;
import org.teavm.model.MethodReference;
import org.teavm.model.analysis.ClassInitializerInfo; import org.teavm.model.analysis.ClassInitializerInfo;
import org.teavm.model.analysis.ClassMetadataRequirements; import org.teavm.model.analysis.ClassMetadataRequirements;
import org.teavm.model.classes.TagRegistry; import org.teavm.model.classes.TagRegistry;
@ -52,11 +54,12 @@ public class WasmGCDeclarationsGenerator {
DependencyInfo dependencyInfo, DependencyInfo dependencyInfo,
Diagnostics diagnostics, Diagnostics diagnostics,
WasmGCCustomGeneratorProvider customGenerators, WasmGCCustomGeneratorProvider customGenerators,
WasmGCIntrinsicProvider intrinsics WasmGCIntrinsicProvider intrinsics,
Predicate<MethodReference> isVirtual
) { ) {
this.module = module; this.module = module;
hierarchy = new ClassHierarchy(classes); hierarchy = new ClassHierarchy(classes);
var virtualTables = createVirtualTableProvider(classes); var virtualTables = createVirtualTableProvider(classes, isVirtual);
functionTypes = new WasmFunctionTypes(module); functionTypes = new WasmFunctionTypes(module);
var names = new WasmNameProvider(); var names = new WasmNameProvider();
methodGenerator = new WasmGCMethodGenerator( methodGenerator = new WasmGCMethodGenerator(
@ -130,8 +133,10 @@ public class WasmGCDeclarationsGenerator {
} }
} }
private static WasmGCVirtualTableProvider createVirtualTableProvider(ListableClassHolderSource classes) { private static WasmGCVirtualTableProvider createVirtualTableProvider(ListableClassHolderSource classes,
return new WasmGCVirtualTableProvider(classes, VirtualTableBuilder.getMethodsUsedOnCallSites(classes, true)); Predicate<MethodReference> isVirtual) {
return new WasmGCVirtualTableProvider(classes, VirtualTableBuilder.getMethodsUsedOnCallSites(classes, true),
isVirtual);
} }
public WasmFunction dummyInitializer() { public WasmFunction dummyInitializer() {

View File

@ -451,7 +451,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
.getUnpackedType(); .getUnpackedType();
var expectedFunctionType = (WasmFunctionType) expectedType.composite; var expectedFunctionType = (WasmFunctionType) expectedType.composite;
var function = functionProvider.forInstanceMethod(implementor); var function = functionProvider.forInstanceMethod(implementor);
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);
module.functions.add(wrapperFunction); module.functions.add(wrapperFunction);