wasm: fix programmatic initialization of a class that is statically initialized by optimizer

This commit is contained in:
Alexey Andreev 2023-11-08 19:59:24 +01:00
parent 9469e4c0b4
commit 726702dd7f
9 changed files with 90 additions and 4 deletions

View File

@ -58,6 +58,7 @@ import org.teavm.backend.c.intrinsic.AddressIntrinsic;
import org.teavm.backend.c.intrinsic.AllocatorIntrinsic; import org.teavm.backend.c.intrinsic.AllocatorIntrinsic;
import org.teavm.backend.c.intrinsic.ConsoleIntrinsic; import org.teavm.backend.c.intrinsic.ConsoleIntrinsic;
import org.teavm.backend.c.intrinsic.ExceptionHandlingIntrinsic; import org.teavm.backend.c.intrinsic.ExceptionHandlingIntrinsic;
import org.teavm.backend.c.intrinsic.FunctionClassIntrinsic;
import org.teavm.backend.c.intrinsic.FunctionIntrinsic; import org.teavm.backend.c.intrinsic.FunctionIntrinsic;
import org.teavm.backend.c.intrinsic.GCIntrinsic; import org.teavm.backend.c.intrinsic.GCIntrinsic;
import org.teavm.backend.c.intrinsic.IntegerIntrinsic; import org.teavm.backend.c.intrinsic.IntegerIntrinsic;
@ -383,6 +384,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
intrinsics.add(new MutatorIntrinsic()); intrinsics.add(new MutatorIntrinsic());
intrinsics.add(new ExceptionHandlingIntrinsic()); intrinsics.add(new ExceptionHandlingIntrinsic());
intrinsics.add(new FunctionIntrinsic(characteristics, exportDependencyListener.getResolvedMethods())); intrinsics.add(new FunctionIntrinsic(characteristics, exportDependencyListener.getResolvedMethods()));
intrinsics.add(new FunctionClassIntrinsic());
intrinsics.add(new RuntimeClassIntrinsic()); intrinsics.add(new RuntimeClassIntrinsic());
intrinsics.add(new FiberIntrinsic()); intrinsics.add(new FiberIntrinsic());
intrinsics.add(new LongIntrinsic()); intrinsics.add(new LongIntrinsic());

View File

@ -0,0 +1,36 @@
/*
* Copyright 2023 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.c.intrinsic;
import org.teavm.ast.InvocationExpr;
import org.teavm.interop.Function;
import org.teavm.model.MethodReference;
public class FunctionClassIntrinsic implements Intrinsic {
@Override
public boolean canHandle(MethodReference method) {
return method.getClassName().equals(Function.class.getName())
&& method.getName().equals("isNull");
}
@Override
public void apply(IntrinsicContext context, InvocationExpr invocation) {
context.writer().print("(");
context.emit(invocation.getArguments().get(0));
context.writer().print(" == NULL");
context.writer().print(")");
}
}

View File

@ -36,8 +36,8 @@ public class FunctionIntrinsic implements Intrinsic {
@Override @Override
public boolean canHandle(MethodReference method) { public boolean canHandle(MethodReference method) {
if (method.getClassName().equals(Function.class.getName()) && method.getName().equals("get")) { if (method.getClassName().equals(Function.class.getName())) {
return true; return method.getName().equals("get");
} }
return characteristics.isFunction(method.getClassName()); return characteristics.isFunction(method.getClassName());
} }

View File

@ -61,6 +61,7 @@ import org.teavm.backend.wasm.intrinsics.ConsoleIntrinsic;
import org.teavm.backend.wasm.intrinsics.DoubleIntrinsic; import org.teavm.backend.wasm.intrinsics.DoubleIntrinsic;
import org.teavm.backend.wasm.intrinsics.ExceptionHandlingIntrinsic; import org.teavm.backend.wasm.intrinsics.ExceptionHandlingIntrinsic;
import org.teavm.backend.wasm.intrinsics.FloatIntrinsic; import org.teavm.backend.wasm.intrinsics.FloatIntrinsic;
import org.teavm.backend.wasm.intrinsics.FunctionClassIntrinsic;
import org.teavm.backend.wasm.intrinsics.FunctionIntrinsic; import org.teavm.backend.wasm.intrinsics.FunctionIntrinsic;
import org.teavm.backend.wasm.intrinsics.GCIntrinsic; import org.teavm.backend.wasm.intrinsics.GCIntrinsic;
import org.teavm.backend.wasm.intrinsics.IntegerIntrinsic; import org.teavm.backend.wasm.intrinsics.IntegerIntrinsic;
@ -509,6 +510,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
context.addIntrinsic(new AddressIntrinsic(classGenerator)); context.addIntrinsic(new AddressIntrinsic(classGenerator));
context.addIntrinsic(new StructureIntrinsic(classes, classGenerator)); context.addIntrinsic(new StructureIntrinsic(classes, classGenerator));
context.addIntrinsic(new FunctionIntrinsic(classGenerator)); context.addIntrinsic(new FunctionIntrinsic(classGenerator));
context.addIntrinsic(new FunctionClassIntrinsic());
var wasmRuntimeIntrinsic = new WasmRuntimeIntrinsic(); var wasmRuntimeIntrinsic = new WasmRuntimeIntrinsic();
context.addIntrinsic(wasmRuntimeIntrinsic); context.addIntrinsic(wasmRuntimeIntrinsic);
context.addIntrinsic(new AllocatorIntrinsic(classGenerator)); context.addIntrinsic(new AllocatorIntrinsic(classGenerator));

View File

@ -0,0 +1,39 @@
/*
* Copyright 2016 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.intrinsics;
import org.teavm.ast.InvocationExpr;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
import org.teavm.backend.wasm.model.expression.WasmIntType;
import org.teavm.interop.Function;
import org.teavm.model.MethodReference;
public class FunctionClassIntrinsic implements WasmIntrinsic {
@Override
public boolean isApplicable(MethodReference methodReference) {
return methodReference.getClassName().equals(Function.class.getName())
&& methodReference.getName().equals("isNull");
}
@Override
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.EQ,
manager.generate(invocation.getArguments().get(0)), new WasmInt32Constant(-1));
}
}

View File

@ -20,6 +20,7 @@ import org.teavm.backend.wasm.generate.WasmClassGenerator;
import org.teavm.backend.wasm.generate.WasmGeneratorUtil; import org.teavm.backend.wasm.generate.WasmGeneratorUtil;
import org.teavm.backend.wasm.model.expression.WasmExpression; import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmIndirectCall; import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
import org.teavm.interop.Function;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
@ -32,6 +33,10 @@ public class FunctionIntrinsic implements WasmIntrinsic {
@Override @Override
public boolean isApplicable(MethodReference methodReference) { public boolean isApplicable(MethodReference methodReference) {
if (methodReference.getClassName().equals(Function.class.getName())
&& methodReference.getName().equals("isNull")) {
return false;
}
return classGenerator.isFunctionClass(methodReference.getClassName()); return classGenerator.isFunctionClass(methodReference.getClassName());
} }

View File

@ -17,4 +17,6 @@ package org.teavm.interop;
public abstract class Function { public abstract class Function {
public static native <T extends Function> T get(Class<T> functionType, Class<?> cls, String methodName); public static native <T extends Function> T get(Class<T> functionType, Class<?> cls, String methodName);
public static native boolean isNull(Function f);
} }

View File

@ -21,6 +21,7 @@ import org.teavm.backend.javascript.spi.InjectedBy;
import org.teavm.dependency.PluggableDependency; import org.teavm.dependency.PluggableDependency;
import org.teavm.interop.Address; import org.teavm.interop.Address;
import org.teavm.interop.DelegateTo; import org.teavm.interop.DelegateTo;
import org.teavm.interop.Function;
import org.teavm.interop.NoSideEffects; import org.teavm.interop.NoSideEffects;
import org.teavm.interop.PlatformMarker; import org.teavm.interop.PlatformMarker;
import org.teavm.interop.Platforms; import org.teavm.interop.Platforms;
@ -124,7 +125,7 @@ public final class Platform {
@Unmanaged @Unmanaged
private static void initClassLowLevel(RuntimeClass cls) { private static void initClassLowLevel(RuntimeClass cls) {
if (cls.init != null) { if (!Function.isNull(cls.init)) {
cls.init.run(); cls.init.run();
} }
} }

View File

@ -280,7 +280,6 @@ public class StringTest {
} }
@Test @Test
@SkipPlatform({ TestPlatform.WEBASSEMBLY, TestPlatform.WASI })
public void getUTF8ByteArrayOfLongString() throws UnsupportedEncodingException { public void getUTF8ByteArrayOfLongString() throws UnsupportedEncodingException {
char[] chars = new char[8192]; char[] chars = new char[8192];
for (int i = 0; i < chars.length;) { for (int i = 0; i < chars.length;) {