Skip to content

Commit

Permalink
wasm gc: support running tests
Browse files Browse the repository at this point in the history
  • Loading branch information
konsoletyper committed Aug 16, 2024
1 parent 40fbce0 commit ded24a1
Show file tree
Hide file tree
Showing 17 changed files with 324 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.teavm.classlib.java.lang.reflect;

import org.teavm.backend.javascript.spi.GeneratedBy;
import org.teavm.classlib.PlatformDetector;
import org.teavm.classlib.java.lang.TArrayIndexOutOfBoundsException;
import org.teavm.classlib.java.lang.TClass;
import org.teavm.classlib.java.lang.TIllegalArgumentException;
Expand Down Expand Up @@ -59,9 +60,15 @@ public static TObject newInstance(Class<?> componentType, int length) throws TNe
if (length < 0) {
throw new TNegativeArraySizeException();
}
return newInstanceImpl(((TClass<?>) (Object) componentType).getPlatformClass(), length);
if (PlatformDetector.isWebAssemblyGC()) {
return newInstanceImpl(componentType, length);
} else {
return newInstanceImpl(((TClass<?>) (Object) componentType).getPlatformClass(), length);
}
}

private static native TObject newInstanceImpl(Class<?> componentType, int length);

@GeneratedBy(ArrayNativeGenerator.class)
@DelegateTo("newInstanceLowLevel")
@NoSideEffects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
private int classParentOffset;
private int classArrayOffset;
private int classArrayItemOffset;
private int classNewArrayOffset;
private int classSupertypeFunctionOffset;
private int virtualTableFieldOffset;

Expand Down Expand Up @@ -275,6 +276,11 @@ public int getClassSupertypeFunctionOffset() {
return classSupertypeFunctionOffset;
}

@Override
public int getClassNameOffset() {
return classNameOffset;
}

@Override
public int getVirtualMethodsOffset() {
return virtualTableFieldOffset;
Expand Down Expand Up @@ -546,6 +552,8 @@ private void fillSimpleClassFields(List<WasmStorageType> fields, String classNam
fields.add(standardClasses.classClass().getType().asStorage());
classSupertypeFunctionOffset = fields.size();
fields.add(supertypeGenerator.getFunctionType().getReference().asStorage());
classNewArrayOffset = fields.size();
fields.add(WasmType.Reference.FUNC.asStorage());
virtualTableFieldOffset = fields.size();
classNameOffset = fieldIndexes.getOrDefault(new FieldReference(className, "name"), -1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public interface WasmGCClassInfoProvider {

int getClassSupertypeFunctionOffset();

int getClassNameOffset();

default WasmGCClassInfo getClassInfo(String name) {
return getClassInfo(ValueType.object(name));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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.classes;

import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.model.ValueType;

class WasmGCNewArrayFunctionGenerator {
WasmFunction generateNewArrayFunction(ValueType itemType) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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.generators.gc;

import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.model.MethodReference;

public class ArrayGenerator implements WasmGCCustomGenerator {
@Override
public void apply(MethodReference method, WasmFunction function, WasmGCCustomGeneratorContext context) {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public void apply(MethodReference method, WasmFunction function, WasmGCCustomGen
case "isInstance":
generateIsInstance(function, context);
break;
case "getName":
generateGetName(function, context);
break;
default:
throw new IllegalArgumentException("Unsupported method: " + method);
}
Expand Down Expand Up @@ -65,4 +68,14 @@ private void generateIsInstance(WasmFunction function, WasmGCCustomGeneratorCont

function.getBody().add(new WasmReturn(conditional));
}

private void generateGetName(WasmFunction function, WasmGCCustomGeneratorContext context) {
var classCls = context.classInfoProvider().getClassInfo("java.lang.Class");
var thisVar = new WasmLocal(classCls.getType());
function.add(thisVar);

var nameRef = new WasmStructGet(classCls.getStructure(), new WasmGetLocal(thisVar),
context.classInfoProvider().getClassNameOffset());
function.getBody().add(new WasmReturn(nameRef));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.teavm.backend.wasm.generators.gc;

import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.Map;
import org.teavm.backend.wasm.generate.gc.methods.WasmGCCustomGeneratorProvider;
Expand All @@ -28,11 +29,13 @@ public WasmGCCustomGenerators() {
fillClass();
fillStringPool();
fillSystem();
fillArray();
}

private void fillClass() {
var classGenerators = new ClassGenerators();
generators.put(new MethodReference(Class.class, "isInstance", Object.class, boolean.class), classGenerators);
generators.put(new MethodReference(Class.class, "getName", String.class), classGenerators);
}

private void fillStringPool() {
Expand All @@ -50,6 +53,12 @@ private void fillSystem() {
);
}

private void fillArray() {
var arrayGenerator = new ArrayGenerator();
generators.put(new MethodReference(Array.class, "newInstanceImpl", Class.class, int.class, Object.class),
arrayGenerator);
}

@Override
public WasmGCCustomGenerator get(MethodReference method) {
return generators.get(method);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.teavm.model.analysis;

import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.Map;
import org.teavm.dependency.DependencyInfo;
Expand All @@ -34,6 +35,8 @@ public class ClassMetadataRequirements {
"getDeclaringClass", Class.class);
private static final MethodReference GET_ENCLOSING_CLASS_METHOD = new MethodReference(Class.class,
"getEnclosingClass", Class.class);
private static final MethodReference NEW_ARRAY = new MethodReference(Array.class,
"newInstance", int.class, Class.class, Object.class);
private static final ClassInfo EMPTY_INFO = new ClassInfo();
private Map<ValueType, ClassInfo> requirements = new HashMap<>();

Expand Down Expand Up @@ -85,6 +88,14 @@ public ClassMetadataRequirements(DependencyInfo dependencyInfo) {
requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo()).enclosingClass = true;
}
}

var newArrayMethod = dependencyInfo.getMethod(NEW_ARRAY);
if (newArrayMethod != null) {
var classNames = newArrayMethod.getVariable(1).getClassValueNode().getTypes();
for (var className : classNames) {
requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo()).newArray = true;
}
}
}

public Info getInfo(String className) {
Expand Down Expand Up @@ -122,6 +133,7 @@ static class ClassInfo implements Info {
boolean enclosingClass;
boolean superclass;
boolean isAssignable;
boolean newArray;

@Override
public boolean name() {
Expand Down Expand Up @@ -152,6 +164,11 @@ public boolean superclass() {
public boolean isAssignable() {
return isAssignable;
}

@Override
public boolean newArray() {
return newArray;
}
}

public interface Info {
Expand All @@ -166,5 +183,7 @@ public interface Info {
boolean superclass();

boolean isAssignable();

boolean newArray();
}
}
3 changes: 3 additions & 0 deletions tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ tasks.test {
systemProperty("teavm.junit.wasm", providers.gradleProperty("teavm.tests.wasm").orElse("true").get())
systemProperty("teavm.junit.wasm.runner", browser)

systemProperty("teavm.junit.wasm-gc", providers.gradleProperty("teavm.tests.wasm-gc").orElse("false").get())
systemProperty("teavm.junit.wasm-gc.runner", browser)

systemProperty("teavm.junit.wasi", providers.gradleProperty("teavm.tests.wasi").orElse("true").get())
systemProperty("teavm.junit.wasi.runner", providers.gradleProperty("teavm.tests.wasi.runner")
.orElse("./run-wasi.sh").get())
Expand Down
19 changes: 16 additions & 3 deletions tools/browser-runner/src/main/resources/test-server/frame.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
window.addEventListener("message", event => {
let request = event.data;
switch (request.type) {
case "JAVASCRIPT":
case "JAVASCRIPT": {
const files = request.additionalFiles ? [...request.additionalFiles, request.file] : [request.file];
appendFiles(files, 0, () => {
launchTest(request.argument, response => {
Expand All @@ -29,8 +29,8 @@ window.addEventListener("message", event => {
event.source.postMessage(wrapResponse({ status: "failed", errorMessage: error }), "*");
});
break;

case "WASM":
}
case "WASM": {
const runtimeFile = request.file.path + "-runtime.js";
appendFiles([{ path: runtimeFile, type: "regular" }], 0, () => {
launchWasmTest(request.file, request.argument, response => {
Expand All @@ -40,6 +40,19 @@ window.addEventListener("message", event => {
event.source.postMessage(wrapResponse({ status: "failed", errorMessage: error }), "*");
});
break;
}

case "WASM_GC": {
const runtimeFile = request.file.path + "-runtime.js";
appendFiles([{ path: runtimeFile, type: "regular" }], 0, () => {
launchWasmTest(request.file, request.argument, response => {
event.source.postMessage(response, "*");
});
}, error => {
event.source.postMessage(wrapResponse({ status: "failed", errorMessage: error} ), "*");
});
break;
}
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ final class PropertyNames {
static final String WASM_ENABLED = "teavm.junit.wasm";
static final String WASI_ENABLED = "teavm.junit.wasi";
static final String WASI_RUNNER = "teavm.junit.wasi.runner";
static final String WASM_GC_ENABLED = "teavm.junit.wasm-gc";
static final String C_COMPILER = "teavm.junit.c.compiler";
static final String C_LINE_NUMBERS = "teavm.junit.c.lineNumbers";
static final String MINIFIED = "teavm.junit.minified";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import org.teavm.backend.c.CTarget;
import org.teavm.backend.javascript.JavaScriptTarget;
import org.teavm.backend.wasm.WasmGCTarget;
import org.teavm.backend.wasm.WasmTarget;
import org.teavm.vm.TeaVM;
import org.teavm.vm.TeaVMOptimizationLevel;
Expand Down Expand Up @@ -115,6 +116,38 @@ public void apply(WasmTarget target) {
}
};

TeaVMTestConfiguration<WasmGCTarget> WASM_GC_DEFAULT = new TeaVMTestConfiguration<>() {
@Override
public String getSuffix() {
return "";
}

@Override
public void apply(TeaVM vm) {
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
}

@Override
public void apply(WasmGCTarget target) {
}
};

TeaVMTestConfiguration<WasmGCTarget> WASM_GC_OPTIMIZED = new TeaVMTestConfiguration<>() {
@Override
public String getSuffix() {
return "optimized";
}

@Override
public void apply(TeaVM vm) {
vm.setOptimizationLevel(TeaVMOptimizationLevel.FULL);
}

@Override
public void apply(WasmGCTarget target) {
}
};

TeaVMTestConfiguration<CTarget> C_DEFAULT = new TeaVMTestConfiguration<>() {
@Override
public String getSuffix() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public class TeaVMTestRunner extends Runner implements Filterable {

platforms.add(new JSPlatformSupport(classSource, referenceCache));
platforms.add(new WebAssemblyPlatformSupport(classSource, referenceCache));
platforms.add(new WebAssemblyGCPlatformSupport(classSource, referenceCache));
platforms.add(new WasiPlatformSupport(classSource, referenceCache));
platforms.add(new CPlatformSupport(classSource, referenceCache));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ public enum TestPlatform {
JAVASCRIPT,
WEBASSEMBLY,
WASI,
WEBASSEMBLY_GC,
C
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ CompileResult compile(TeaVMTestConfiguration<T> configuration,
}
}

private File getOutputFile(File path, String baseName, String suffix, String extension) {
protected final File getOutputFile(File path, String baseName, String suffix, String extension) {
StringBuilder simpleName = new StringBuilder();
simpleName.append(baseName);
if (!suffix.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2021 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.junit;

final class TestWasmGCEntryPoint {
private TestWasmGCEntryPoint() {
}

public static void main(String[] args) throws Throwable {
TestEntryPoint.run(args.length > 0 ? args[0] : null);
}
}
Loading

0 comments on commit ded24a1

Please sign in to comment.