Skip to content

Commit

Permalink
wasm gc: support exporting declarations as JS entities from module
Browse files Browse the repository at this point in the history
  • Loading branch information
konsoletyper committed Oct 6, 2024
1 parent 73dda91 commit 2129f5d
Show file tree
Hide file tree
Showing 17 changed files with 479 additions and 231 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
import org.teavm.interop.Platforms;
import org.teavm.interop.Unmanaged;
import org.teavm.interop.UnsupportedOn;
import org.teavm.jso.JSObject;
import org.teavm.jso.core.JSDate;
import org.teavm.jso.impl.JS;

public class TDate implements TComparable<TDate> {
private long value;
Expand Down Expand Up @@ -420,7 +422,7 @@ public String toString() {
} else if (PlatformDetector.isWebAssembly()) {
return toStringWebAssembly(value);
} else if (PlatformDetector.isWebAssemblyGC()) {
return toStringWebAssemblyGC(value);
return JS.unwrapString(toStringWebAssemblyGC(value));
} else {
return JSDate.create(value).stringValue();
}
Expand All @@ -435,7 +437,7 @@ public String toString() {
private static native String toStringWebAssembly(double date);

@Import(module = "teavmDate", name = "dateToString")
private static native String toStringWebAssemblyGC(double date);
private static native JSObject toStringWebAssemblyGC(double date);

@Deprecated
public String toLocaleString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.teavm.backend.wasm.generate.gc.WasmGCDeclarationsGenerator;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.runtime.StringInternPool;
import org.teavm.backend.wasm.runtime.gc.WasmGCSupport;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;

Expand All @@ -40,41 +39,6 @@ public WasmFunction generateMainFunction(String entryPoint) {
"main", ValueType.parse(String[].class), ValueType.VOID));
}

public WasmFunction generateCreateStringBuilderFunction() {
return declarationsGenerator.functions().forStaticMethod(new MethodReference(
WasmGCSupport.class, "createStringBuilder", StringBuilder.class));
}

public WasmFunction generateCreateStringArrayFunction() {
return declarationsGenerator.functions().forStaticMethod(new MethodReference(
WasmGCSupport.class, "createStringArray", int.class, String[].class));
}

public WasmFunction generateAppendCharFunction() {
return declarationsGenerator.functions().forInstanceMethod(new MethodReference(
StringBuilder.class, "append", char.class, StringBuilder.class));
}

public WasmFunction generateBuildStringFunction() {
return declarationsGenerator.functions().forInstanceMethod(new MethodReference(
StringBuilder.class, "toString", String.class));
}

public WasmFunction generateSetToStringArrayFunction() {
return declarationsGenerator.functions().forStaticMethod(new MethodReference(
WasmGCSupport.class, "setToStringArray", String[].class, int.class, String.class, void.class));
}

public WasmFunction generateStringLengthFunction() {
return declarationsGenerator.functions().forInstanceMethod(new MethodReference(
String.class, "length", int.class));
}

public WasmFunction generateCharAtFunction() {
return declarationsGenerator.functions().forInstanceMethod(new MethodReference(
String.class, "charAt", int.class, char.class));
}

public WasmFunction generateReportGarbageCollectedStringFunction() {
var entryType = ValueType.object(StringInternPool.class.getName() + "$Entry");
return declarationsGenerator.functions().forStaticMethod(new MethodReference(
Expand Down
35 changes: 10 additions & 25 deletions core/src/main/java/org/teavm/backend/wasm/WasmGCTarget.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.teavm.backend.wasm.runtime.StringInternPool;
import org.teavm.backend.wasm.transformation.gc.BaseClassesTransformation;
import org.teavm.backend.wasm.transformation.gc.ClassLoaderResourceTransformation;
import org.teavm.backend.wasm.transformation.gc.EntryPointTransformation;
import org.teavm.dependency.DependencyAnalyzer;
import org.teavm.dependency.DependencyListener;
import org.teavm.interop.Platforms;
Expand Down Expand Up @@ -73,6 +74,7 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
private List<WasmGCCustomTypeMapperFactory> customTypeMapperFactories = new ArrayList<>();
private Map<MethodReference, WasmGCCustomGenerator> customCustomGenerators = new HashMap<>();
private List<WasmGCCustomGeneratorFactory> customGeneratorFactories = new ArrayList<>();
private EntryPointTransformation entryPointTransformation = new EntryPointTransformation();

public void setObfuscated(boolean obfuscated) {
this.obfuscated = obfuscated;
Expand Down Expand Up @@ -118,6 +120,8 @@ public void addCustomTypeMapperFactory(WasmGCCustomTypeMapperFactory customTypeM
@Override
public void setController(TeaVMTargetController controller) {
this.controller = controller;
entryPointTransformation.setEntryPoint(controller.getEntryPoint());
entryPointTransformation.setEntryPointName(controller.getEntryPointName());
}

@Override
Expand All @@ -134,7 +138,8 @@ public List<DependencyListener> getDependencyListeners() {
public List<ClassHolderTransformer> getTransformers() {
return List.of(
new BaseClassesTransformation(),
new ClassLoaderResourceTransformation()
new ClassLoaderResourceTransformation(),
entryPointTransformation
);
}

Expand Down Expand Up @@ -198,7 +203,8 @@ public void emit(ListableClassHolderSource classes, BuildTarget buildTarget, Str
intrinsics,
customTypeMapperFactories,
controller::isVirtual,
strict
strict,
controller.getEntryPoint()
);
declarationsGenerator.setFriendlyToDebugger(controller.isFriendlyToDebugger());
var moduleGenerator = new WasmGCModuleGenerator(declarationsGenerator);
Expand All @@ -207,38 +213,17 @@ public void emit(ListableClassHolderSource classes, BuildTarget buildTarget, Str
mainFunction.setExportName(controller.getEntryPointName());
mainFunction.setName(controller.getEntryPointName());

var stringBuilderFunction = moduleGenerator.generateCreateStringBuilderFunction();
stringBuilderFunction.setExportName("createStringBuilder");

var createStringArrayFunction = moduleGenerator.generateCreateStringArrayFunction();
createStringArrayFunction.setExportName("createStringArray");

var appendCharFunction = moduleGenerator.generateAppendCharFunction();
appendCharFunction.setExportName("appendChar");

var buildStringFunction = moduleGenerator.generateBuildStringFunction();
buildStringFunction.setExportName("buildString");

var setArrayFunction = moduleGenerator.generateSetToStringArrayFunction();
setArrayFunction.setExportName("setToStringArray");

var stringLengthFunction = moduleGenerator.generateStringLengthFunction();
stringLengthFunction.setExportName("stringLength");

var charAtFunction = moduleGenerator.generateCharAtFunction();
charAtFunction.setExportName("charAt");

var internMethod = controller.getDependencyInfo().getMethod(new MethodReference(String.class,
"intern", String.class));
if (internMethod != null && internMethod.isUsed()) {
var removeStringEntryFunction = moduleGenerator.generateReportGarbageCollectedStringFunction();
removeStringEntryFunction.setExportName("reportGarbageCollectedString");
removeStringEntryFunction.setExportName("teavm.reportGarbageCollectedString");
}

var exceptionMessageRef = new MethodReference(Throwable.class, "getMessage", Throwable.class);
if (controller.getDependencyInfo().getMethod(exceptionMessageRef) != null) {
var exceptionMessageFunction = declarationsGenerator.functions().forInstanceMethod(exceptionMessageRef);
exceptionMessageFunction.setExportName("exceptionMessage");
exceptionMessageFunction.setExportName("teavm.exceptionMessage");
}

moduleGenerator.generate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ public WasmGCDeclarationsGenerator(
WasmGCIntrinsicProvider intrinsics,
List<WasmGCCustomTypeMapperFactory> customTypeMapperFactories,
Predicate<MethodReference> isVirtual,
boolean strict
boolean strict,
String entryPoint
) {
this.module = module;
hierarchy = new ClassHierarchy(classes);
Expand All @@ -82,6 +83,7 @@ public WasmGCDeclarationsGenerator(
customGenerators,
intrinsics,
strict,
entryPoint,
initializerContributors::add
);
var tags = new TagRegistry(classes, hierarchy);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
private Map<String, Set<String>> interfaceImplementors;
private WasmGCNameProvider names;
private boolean strict;
private String entryPoint;
private Consumer<WasmGCInitializerContributor> initializerContributors;

public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider virtualTables,
Expand All @@ -73,7 +74,8 @@ public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider vir
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics,
WasmGCNameProvider names, boolean strict, Consumer<WasmGCInitializerContributor> initializerContributors) {
WasmGCNameProvider names, boolean strict, String entryPoint,
Consumer<WasmGCInitializerContributor> initializerContributors) {
this.module = module;
this.virtualTables = virtualTables;
this.typeMapper = typeMapper;
Expand All @@ -90,6 +92,7 @@ public WasmGCGenerationContext(WasmModule module, WasmGCVirtualTableProvider vir
this.intrinsics = intrinsics;
this.names = names;
this.strict = strict;
this.entryPoint = entryPoint;
this.initializerContributors = initializerContributors;
}

Expand All @@ -109,6 +112,10 @@ public WasmGCStringProvider strings() {
return strings;
}

public String entryPoint() {
return entryPoint;
}

public WasmGCVirtualTableProvider virtualTables() {
return virtualTables;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,11 @@ public WasmTag exceptionTag() {
return context.getExceptionTag();
}

@Override
public String entryPoint() {
return context.entryPoint();
}

@Override
public void addToInitializer(Consumer<WasmFunction> initializerContributor) {
context.addToInitializer(initializerContributor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
private WasmGCStandardClasses standardClasses;
private WasmGCStringProvider strings;
private boolean strict;
private String entryPoint;
private Consumer<WasmGCInitializerContributor> initializerContributors;

public WasmGCMethodGenerator(
Expand All @@ -103,6 +104,7 @@ public WasmGCMethodGenerator(
WasmGCCustomGeneratorProvider customGenerators,
WasmGCIntrinsicProvider intrinsics,
boolean strict,
String entryPoint,
Consumer<WasmGCInitializerContributor> initializerContributors
) {
this.module = module;
Expand All @@ -117,6 +119,7 @@ public WasmGCMethodGenerator(
this.customGenerators = customGenerators;
this.intrinsics = intrinsics;
this.strict = strict;
this.entryPoint = entryPoint;
this.initializerContributors = initializerContributors;
}

Expand Down Expand Up @@ -362,6 +365,7 @@ private WasmGCGenerationContext getGenerationContext() {
intrinsics,
names,
strict,
entryPoint,
initializerContributors
);
}
Expand Down Expand Up @@ -434,6 +438,11 @@ public WasmGCStringProvider strings() {
return context.strings();
}

@Override
public String entryPoint() {
return context.entryPoint();
}

@Override
public void addToInitializer(Consumer<WasmFunction> initializerContributor) {
context.addToInitializer(initializerContributor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,7 @@ public interface WasmGCCustomGeneratorContext {

WasmGCStringProvider strings();

String entryPoint();

void addToInitializer(Consumer<WasmFunction> initializerContributor);
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,7 @@ public interface WasmGCIntrinsicContext {

WasmTag exceptionTag();

String entryPoint();

void addToInitializer(Consumer<WasmFunction> initializerContributor);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.transformation.gc;

import org.teavm.model.AnnotationHolder;
import org.teavm.model.AnnotationValue;
import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.ClassHolderTransformerContext;
import org.teavm.model.MethodDescriptor;

public class EntryPointTransformation implements ClassHolderTransformer {
private static final MethodDescriptor MAIN_METHOD = new MethodDescriptor("main", String[].class, void.class);
private String entryPoint;
private String entryPointName;

public void setEntryPoint(String entryPoint) {
this.entryPoint = entryPoint;
}

public void setEntryPointName(String entryPointName) {
this.entryPointName = entryPointName;
}

@Override
public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) {
if (cls.getName().equals(entryPoint)) {
var mainMethod = cls.getMethod(MAIN_METHOD);
if (mainMethod != null) {
mainMethod.getAnnotations().add(new AnnotationHolder("org.teavm.jso.JSExport"));

var methodAnnot = new AnnotationHolder("org.teavm.jso.JSMethod");
methodAnnot.getValues().put("value", new AnnotationValue(entryPointName));
}
}
}
}
Loading

0 comments on commit 2129f5d

Please sign in to comment.