mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: implement System.identityHashCode() and some Integer intrinsics
This commit is contained in:
parent
5d109236d9
commit
335e2da4cf
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
||||||
import org.teavm.classlib.PlatformDetector;
|
import org.teavm.classlib.PlatformDetector;
|
||||||
import org.teavm.dependency.PluggableDependency;
|
import org.teavm.dependency.PluggableDependency;
|
||||||
import org.teavm.interop.Address;
|
import org.teavm.interop.Address;
|
||||||
|
@ -246,7 +247,22 @@ public class TObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
final int identity() {
|
final int identity() {
|
||||||
if (PlatformDetector.isLowLevel()) {
|
if (PlatformDetector.isWebAssemblyGC()) {
|
||||||
|
var identity = wasmGCIdentity();
|
||||||
|
if (identity < 0) {
|
||||||
|
var monitor = this.monitor;
|
||||||
|
if (monitor != null) {
|
||||||
|
if (monitor.id < 0) {
|
||||||
|
monitor.id = WasmGCSupport.nextObjectId() & 0x7ffffff;
|
||||||
|
}
|
||||||
|
return monitor.id;
|
||||||
|
} else {
|
||||||
|
identity = WasmGCSupport.nextObjectId();
|
||||||
|
setWasmGCIdentity(identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return identity;
|
||||||
|
} else if (PlatformDetector.isLowLevel()) {
|
||||||
Monitor monitor = this.monitor;
|
Monitor monitor = this.monitor;
|
||||||
if (monitor == null) {
|
if (monitor == null) {
|
||||||
int hashCode = hashCodeLowLevel(this);
|
int hashCode = hashCodeLowLevel(this);
|
||||||
|
@ -271,6 +287,10 @@ public class TObject {
|
||||||
return Platform.getPlatformObject(this).getId();
|
return Platform.getPlatformObject(this).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private native int wasmGCIdentity();
|
||||||
|
|
||||||
|
private native void setWasmGCIdentity(int identity);
|
||||||
|
|
||||||
@DelegateTo("hashCodeLowLevelImpl")
|
@DelegateTo("hashCodeLowLevelImpl")
|
||||||
@NoSideEffects
|
@NoSideEffects
|
||||||
@Unmanaged
|
@Unmanaged
|
||||||
|
|
|
@ -135,6 +135,8 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
||||||
return "extern";
|
return "extern";
|
||||||
case STRUCT:
|
case STRUCT:
|
||||||
return "struct";
|
return "struct";
|
||||||
|
case I31:
|
||||||
|
return "i31";
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
@ -829,8 +831,21 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(WasmHollowType.Reference type) {
|
public void cast(WasmHollowType.Reference type, boolean nullable) {
|
||||||
writer.address(address).write("ref.cast ").write(typeToString(type)).eol();
|
writer.address(address).write("ref.cast (ref ");
|
||||||
|
if (!nullable) {
|
||||||
|
writer.write("null ");
|
||||||
|
}
|
||||||
|
writer.write(typeToString(type)).write(")").eol();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void test(WasmHollowType.Reference type, boolean nullable) {
|
||||||
|
writer.address(address).write("ref.test (ref ");
|
||||||
|
if (!nullable) {
|
||||||
|
writer.write("null ");
|
||||||
|
}
|
||||||
|
writer.write(typeToString(type)).write(")").eol();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -890,6 +905,16 @@ public class DisassemblyCodeSectionListener implements AddressListener, CodeSect
|
||||||
writer.address(address).write("ref.func ").write(Integer.toString(functionIndex)).eol();
|
writer.address(address).write("ref.func ").write(Integer.toString(functionIndex)).eol();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void int31Reference() {
|
||||||
|
writer.address(address).write("ref.i31").eol();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void int31Get(WasmSignedType signedType) {
|
||||||
|
writer.address(address).write("ref.i31_").write(signedType == WasmSignedType.SIGNED ? "s" : "u").eol();
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
var file = new File(args[0]);
|
var file = new File(args[0]);
|
||||||
var bytes = Files.readAllBytes(file.toPath());
|
var bytes = Files.readAllBytes(file.toPath());
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.teavm.ast.SubscriptExpr;
|
||||||
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.PreciseTypeInference;
|
import org.teavm.backend.wasm.gc.PreciseTypeInference;
|
||||||
|
import org.teavm.backend.wasm.generate.TemporaryVariablePool;
|
||||||
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor;
|
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
|
||||||
|
@ -587,5 +588,10 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
public WasmGCClassInfoProvider classInfoProvider() {
|
public WasmGCClassInfoProvider classInfoProvider() {
|
||||||
return context.classInfoProvider();
|
return context.classInfoProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemporaryVariablePool tempVars() {
|
||||||
|
return tempVars;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,23 +24,28 @@ import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
public class LongIntrinsic implements WasmGCIntrinsic {
|
public class IntNumIntrinsic implements WasmGCIntrinsic {
|
||||||
private static final MethodReference COMPARE_UNSIGNED = new MethodReference(WasmRuntime.class,
|
private final MethodReference compareUnsigned;
|
||||||
"compareUnsigned", long.class, long.class, int.class);
|
private final WasmIntType wasmType;
|
||||||
|
|
||||||
|
public IntNumIntrinsic(Class<?> javaType, WasmIntType wasmType) {
|
||||||
|
compareUnsigned = new MethodReference(WasmRuntime.class, "compareUnsigned", javaType, javaType, int.class);
|
||||||
|
this.wasmType = wasmType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||||
switch (invocation.getMethod().getName()) {
|
switch (invocation.getMethod().getName()) {
|
||||||
case "divideUnsigned":
|
case "divideUnsigned":
|
||||||
return new WasmIntBinary(WasmIntType.INT64, WasmIntBinaryOperation.DIV_UNSIGNED,
|
return new WasmIntBinary(wasmType, WasmIntBinaryOperation.DIV_UNSIGNED,
|
||||||
context.generate(invocation.getArguments().get(0)),
|
context.generate(invocation.getArguments().get(0)),
|
||||||
context.generate(invocation.getArguments().get(1)));
|
context.generate(invocation.getArguments().get(1)));
|
||||||
case "remainderUnsigned":
|
case "remainderUnsigned":
|
||||||
return new WasmIntBinary(WasmIntType.INT64, WasmIntBinaryOperation.REM_UNSIGNED,
|
return new WasmIntBinary(wasmType, WasmIntBinaryOperation.REM_UNSIGNED,
|
||||||
context.generate(invocation.getArguments().get(0)),
|
context.generate(invocation.getArguments().get(0)),
|
||||||
context.generate(invocation.getArguments().get(1)));
|
context.generate(invocation.getArguments().get(1)));
|
||||||
case "compareUnsigned":
|
case "compareUnsigned":
|
||||||
return new WasmCall(context.functions().forStaticMethod(COMPARE_UNSIGNED),
|
return new WasmCall(context.functions().forStaticMethod(compareUnsigned),
|
||||||
context.generate(invocation.getArguments().get(0)),
|
context.generate(invocation.getArguments().get(0)),
|
||||||
context.generate(invocation.getArguments().get(1)));
|
context.generate(invocation.getArguments().get(1)));
|
||||||
default:
|
default:
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* 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.intrinsics.gc;
|
||||||
|
|
||||||
|
import org.teavm.ast.InvocationExpr;
|
||||||
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmBranch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmDrop;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Get;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Reference;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntUnary;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntUnaryOperation;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmNullConstant;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmTest;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
|
public class ObjectIntrinsic implements WasmGCIntrinsic {
|
||||||
|
@Override
|
||||||
|
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||||
|
switch (invocation.getMethod().getName()) {
|
||||||
|
case "getClass":
|
||||||
|
return generateGetClass(invocation, context);
|
||||||
|
case "getMonitor":
|
||||||
|
return generateGetMonitor(invocation, context);
|
||||||
|
case "setMonitor":
|
||||||
|
return generateSetMonitor(invocation, context);
|
||||||
|
case "wasmGCIdentity":
|
||||||
|
return generateGetIdentity(invocation, context);
|
||||||
|
case "setWasmGCIdentity":
|
||||||
|
return generateSetIdentity(invocation, context);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmExpression generateGetClass(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||||
|
var obj = context.generate(invocation.getArguments().get(0));
|
||||||
|
var objectStruct = context.classInfoProvider().getClassInfo("java.lang.Object").getStructure();
|
||||||
|
var result = new WasmStructGet(objectStruct, obj, WasmGCClassInfoProvider.CLASS_FIELD_OFFSET);
|
||||||
|
result.setLocation(invocation.getLocation());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmExpression generateGetMonitor(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||||
|
var monitorType = context.classInfoProvider().getClassInfo(ValueType.object("java.lang.Object$Monitor"))
|
||||||
|
.getStructure().getReference();
|
||||||
|
var objectStruct = context.classInfoProvider().getClassInfo(ValueType.object("java.lang.Object"))
|
||||||
|
.getStructure();
|
||||||
|
var block = new WasmBlock(false);
|
||||||
|
block.setType(monitorType);
|
||||||
|
var tmpVar = context.tempVars().acquire(WasmType.Reference.ANY);
|
||||||
|
var instance = context.generate(invocation.getArguments().get(0));
|
||||||
|
block.getBody().add(new WasmSetLocal(tmpVar, new WasmStructGet(objectStruct, instance,
|
||||||
|
WasmGCClassInfoProvider.MONITOR_FIELD_OFFSET)));
|
||||||
|
|
||||||
|
WasmExpression test = new WasmTest(new WasmGetLocal(tmpVar), monitorType, false);
|
||||||
|
test = new WasmIntUnary(WasmIntType.INT32, WasmIntUnaryOperation.EQZ, test);
|
||||||
|
var branch = new WasmBranch(test, block);
|
||||||
|
branch.setResult(new WasmNullConstant(monitorType));
|
||||||
|
block.getBody().add(new WasmDrop(branch));
|
||||||
|
|
||||||
|
block.getBody().add(new WasmCast(new WasmGetLocal(tmpVar), monitorType));
|
||||||
|
context.tempVars().release(tmpVar);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmExpression generateSetMonitor(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||||
|
var objectStruct = context.classInfoProvider().getClassInfo(ValueType.object("java.lang.Object"))
|
||||||
|
.getStructure();
|
||||||
|
var instance = context.generate(invocation.getArguments().get(0));
|
||||||
|
var monitor = context.generate(invocation.getArguments().get(1));
|
||||||
|
return new WasmStructSet(objectStruct, instance, WasmGCClassInfoProvider.MONITOR_FIELD_OFFSET, monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmExpression generateGetIdentity(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||||
|
var objectStruct = context.classInfoProvider().getClassInfo(ValueType.object("java.lang.Object"))
|
||||||
|
.getStructure();
|
||||||
|
var block = new WasmBlock(false);
|
||||||
|
block.setType(WasmType.INT32);
|
||||||
|
var tmpVar = context.tempVars().acquire(WasmType.Reference.ANY);
|
||||||
|
var instance = context.generate(invocation.getArguments().get(0));
|
||||||
|
block.getBody().add(new WasmSetLocal(tmpVar, new WasmStructGet(objectStruct, instance,
|
||||||
|
WasmGCClassInfoProvider.MONITOR_FIELD_OFFSET)));
|
||||||
|
|
||||||
|
WasmExpression test = new WasmTest(new WasmGetLocal(tmpVar), WasmType.Reference.I31, false);
|
||||||
|
test = new WasmIntUnary(WasmIntType.INT32, WasmIntUnaryOperation.EQZ, test);
|
||||||
|
var branch = new WasmBranch(test, block);
|
||||||
|
branch.setResult(new WasmInt32Constant(-1));
|
||||||
|
block.getBody().add(new WasmDrop(branch));
|
||||||
|
|
||||||
|
var i31ref = new WasmCast(new WasmGetLocal(tmpVar), WasmType.Reference.I31);
|
||||||
|
block.getBody().add(new WasmInt31Get(i31ref, WasmSignedType.UNSIGNED));
|
||||||
|
context.tempVars().release(tmpVar);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WasmExpression generateSetIdentity(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||||
|
var objectStruct = context.classInfoProvider().getClassInfo(ValueType.object("java.lang.Object"))
|
||||||
|
.getStructure();
|
||||||
|
var instance = context.generate(invocation.getArguments().get(0));
|
||||||
|
var identity = context.generate(invocation.getArguments().get(1));
|
||||||
|
var identityWrapper = new WasmInt31Reference(identity);
|
||||||
|
return new WasmStructSet(objectStruct, instance, WasmGCClassInfoProvider.MONITOR_FIELD_OFFSET,
|
||||||
|
identityWrapper);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.intrinsics.gc;
|
|
||||||
|
|
||||||
import org.teavm.ast.InvocationExpr;
|
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
|
||||||
|
|
||||||
public class ObjectIntrinsics implements WasmGCIntrinsic {
|
|
||||||
@Override
|
|
||||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
|
||||||
var obj = context.generate(invocation.getArguments().get(0));
|
|
||||||
var objectStruct = context.classInfoProvider().getClassInfo("java.lang.Object").getStructure();
|
|
||||||
var result = new WasmStructGet(objectStruct, obj, WasmGCClassInfoProvider.CLASS_FIELD_OFFSET);
|
|
||||||
result.setLocation(invocation.getLocation());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,6 +19,7 @@ import org.teavm.ast.Expr;
|
||||||
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.PreciseTypeInference;
|
import org.teavm.backend.wasm.gc.PreciseTypeInference;
|
||||||
|
import org.teavm.backend.wasm.generate.TemporaryVariablePool;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCTypeMapper;
|
||||||
import org.teavm.backend.wasm.model.WasmModule;
|
import org.teavm.backend.wasm.model.WasmModule;
|
||||||
|
@ -41,4 +42,6 @@ public interface WasmGCIntrinsicContext {
|
||||||
WasmGCTypeMapper typeMapper();
|
WasmGCTypeMapper typeMapper();
|
||||||
|
|
||||||
WasmGCClassInfoProvider classInfoProvider();
|
WasmGCClassInfoProvider classInfoProvider();
|
||||||
|
|
||||||
|
TemporaryVariablePool tempVars();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,9 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.teavm.backend.wasm.WasmRuntime;
|
import org.teavm.backend.wasm.WasmRuntime;
|
||||||
import org.teavm.backend.wasm.generate.gc.methods.WasmGCIntrinsicProvider;
|
import org.teavm.backend.wasm.generate.gc.methods.WasmGCIntrinsicProvider;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||||
private Map<MethodReference, WasmGCIntrinsic> intrinsics = new HashMap<>();
|
private Map<MethodReference, WasmGCIntrinsic> intrinsics = new HashMap<>();
|
||||||
|
@ -30,7 +32,7 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||||
fillObject();
|
fillObject();
|
||||||
fillClass();
|
fillClass();
|
||||||
fillSystem();
|
fillSystem();
|
||||||
fillLong();
|
fillLongAndInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillWasmRuntime() {
|
private void fillWasmRuntime() {
|
||||||
|
@ -50,8 +52,16 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillObject() {
|
private void fillObject() {
|
||||||
var objectIntrinsics = new ObjectIntrinsics();
|
var objectIntrinsics = new ObjectIntrinsic();
|
||||||
intrinsics.put(new MethodReference(Object.class, "getClass", Class.class), objectIntrinsics);
|
intrinsics.put(new MethodReference(Object.class, "getClass", Class.class), objectIntrinsics);
|
||||||
|
intrinsics.put(new MethodReference(Object.class.getName(), "getMonitor",
|
||||||
|
ValueType.object("java.lang.Object$Monitor")), objectIntrinsics);
|
||||||
|
intrinsics.put(new MethodReference(Object.class.getName(), "setMonitor",
|
||||||
|
ValueType.object("java.lang.Object$Monitor"), ValueType.VOID), objectIntrinsics);
|
||||||
|
intrinsics.put(new MethodReference(Object.class.getName(), "wasmGCIdentity", ValueType.INTEGER),
|
||||||
|
objectIntrinsics);
|
||||||
|
intrinsics.put(new MethodReference(Object.class.getName(), "setWasmGCIdentity", ValueType.INTEGER,
|
||||||
|
ValueType.VOID), objectIntrinsics);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillClass() {
|
private void fillClass() {
|
||||||
|
@ -66,13 +76,18 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||||
int.class, int.class, void.class), new SystemArrayCopyIntrinsic());
|
int.class, int.class, void.class), new SystemArrayCopyIntrinsic());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillLong() {
|
private void fillLongAndInteger() {
|
||||||
var intrinsic = new LongIntrinsic();
|
fillIntNum(int.class, Integer.class, WasmIntType.INT32);
|
||||||
intrinsics.put(new MethodReference(Long.class, "divideUnsigned", long.class, long.class, long.class),
|
fillIntNum(long.class, Long.class, WasmIntType.INT64);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillIntNum(Class<?> javaClass, Class<?> wrapperClass, WasmIntType wasmType) {
|
||||||
|
var intrinsic = new IntNumIntrinsic(javaClass, wasmType);
|
||||||
|
intrinsics.put(new MethodReference(wrapperClass, "divideUnsigned", javaClass, javaClass, javaClass),
|
||||||
intrinsic);
|
intrinsic);
|
||||||
intrinsics.put(new MethodReference(Long.class, "remainderUnsigned", long.class, long.class, long.class),
|
intrinsics.put(new MethodReference(wrapperClass, "remainderUnsigned", javaClass, javaClass, javaClass),
|
||||||
intrinsic);
|
intrinsic);
|
||||||
intrinsics.put(new MethodReference(Long.class, "compareUnsigned", long.class, long.class, int.class),
|
intrinsics.put(new MethodReference(wrapperClass, "compareUnsigned", javaClass, javaClass, int.class),
|
||||||
intrinsic);
|
intrinsic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ public abstract class WasmType {
|
||||||
public static final SpecialReference EXTERN = SpecialReferenceKind.EXTERN.asType();
|
public static final SpecialReference EXTERN = SpecialReferenceKind.EXTERN.asType();
|
||||||
public static final SpecialReference STRUCT = SpecialReferenceKind.STRUCT.asType();
|
public static final SpecialReference STRUCT = SpecialReferenceKind.STRUCT.asType();
|
||||||
public static final SpecialReference ARRAY = SpecialReferenceKind.ARRAY.asType();
|
public static final SpecialReference ARRAY = SpecialReferenceKind.ARRAY.asType();
|
||||||
|
public static final SpecialReference I31 = SpecialReferenceKind.I31.asType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class CompositeReference extends Reference {
|
public static final class CompositeReference extends Reference {
|
||||||
|
@ -85,7 +86,8 @@ public abstract class WasmType {
|
||||||
ANY,
|
ANY,
|
||||||
EXTERN,
|
EXTERN,
|
||||||
STRUCT,
|
STRUCT,
|
||||||
ARRAY;
|
ARRAY,
|
||||||
|
I31;
|
||||||
|
|
||||||
private SpecialReference type;
|
private SpecialReference type;
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,16 @@ import org.teavm.backend.wasm.model.WasmType;
|
||||||
public class WasmCast extends WasmExpression {
|
public class WasmCast extends WasmExpression {
|
||||||
private WasmExpression value;
|
private WasmExpression value;
|
||||||
private WasmType.Reference targetType;
|
private WasmType.Reference targetType;
|
||||||
|
private boolean nullable;
|
||||||
|
|
||||||
public WasmCast(WasmExpression value, WasmType.Reference targetType) {
|
public WasmCast(WasmExpression value, WasmType.Reference targetType) {
|
||||||
|
this(value, targetType, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmCast(WasmExpression value, WasmType.Reference targetType, boolean nullable) {
|
||||||
this.value = Objects.requireNonNull(value);
|
this.value = Objects.requireNonNull(value);
|
||||||
this.targetType = Objects.requireNonNull(targetType);
|
this.targetType = Objects.requireNonNull(targetType);
|
||||||
|
this.nullable = nullable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmExpression getValue() {
|
public WasmExpression getValue() {
|
||||||
|
@ -43,6 +49,14 @@ public class WasmCast extends WasmExpression {
|
||||||
this.targetType = Objects.requireNonNull(targetType);
|
this.targetType = Objects.requireNonNull(targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isNullable() {
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNullable(boolean nullable) {
|
||||||
|
this.nullable = nullable;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|
|
@ -251,6 +251,11 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor {
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmTest expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructNew expression) {
|
public void visit(WasmStructNew expression) {
|
||||||
for (var initializer : expression.getInitializers()) {
|
for (var initializer : expression.getInitializers()) {
|
||||||
|
@ -308,4 +313,14 @@ public class WasmDefaultExpressionVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmFunctionReference expression) {
|
public void visit(WasmFunctionReference expression) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Reference expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Get expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,8 @@ public interface WasmExpressionVisitor {
|
||||||
|
|
||||||
void visit(WasmCast expression);
|
void visit(WasmCast expression);
|
||||||
|
|
||||||
|
void visit(WasmTest expression);
|
||||||
|
|
||||||
void visit(WasmStructNew expression);
|
void visit(WasmStructNew expression);
|
||||||
|
|
||||||
void visit(WasmStructNewDefault expression);
|
void visit(WasmStructNewDefault expression);
|
||||||
|
@ -115,4 +117,8 @@ public interface WasmExpressionVisitor {
|
||||||
void visit(WasmArrayCopy expression);
|
void visit(WasmArrayCopy expression);
|
||||||
|
|
||||||
void visit(WasmFunctionReference expression);
|
void visit(WasmFunctionReference expression);
|
||||||
|
|
||||||
|
void visit(WasmInt31Reference expression);
|
||||||
|
|
||||||
|
void visit(WasmInt31Get expression);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* 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.model.expression;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class WasmInt31Get extends WasmExpression {
|
||||||
|
private WasmSignedType signedType;
|
||||||
|
private WasmExpression value;
|
||||||
|
|
||||||
|
public WasmInt31Get(WasmExpression value, WasmSignedType signedType) {
|
||||||
|
this.signedType = Objects.requireNonNull(signedType);
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmSignedType getSignedType() {
|
||||||
|
return signedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignedType(WasmSignedType signedType) {
|
||||||
|
this.signedType = Objects.requireNonNull(signedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmExpression getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(WasmExpression value) {
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* 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.model.expression;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class WasmInt31Reference extends WasmExpression {
|
||||||
|
private WasmExpression value;
|
||||||
|
|
||||||
|
public WasmInt31Reference(WasmExpression value) {
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmExpression getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(WasmExpression value) {
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -300,6 +300,12 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor {
|
||||||
expression.setValue(mapper.apply(expression.getValue()));
|
expression.setValue(mapper.apply(expression.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmTest expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
expression.setValue(mapper.apply(expression.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructNew expression) {
|
public void visit(WasmStructNew expression) {
|
||||||
replaceExpressions(expression.getInitializers());
|
replaceExpressions(expression.getInitializers());
|
||||||
|
@ -378,4 +384,16 @@ public class WasmReplacingExpressionVisitor implements WasmExpressionVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmFunctionReference expression) {
|
public void visit(WasmFunctionReference expression) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Reference expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
expression.setValue(mapper.apply(expression.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Get expression) {
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
expression.setValue(mapper.apply(expression.getValue()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.model.expression;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.teavm.backend.wasm.model.WasmType;
|
||||||
|
|
||||||
|
public class WasmTest extends WasmExpression {
|
||||||
|
private WasmExpression value;
|
||||||
|
private WasmType.Reference testType;
|
||||||
|
private boolean nullable;
|
||||||
|
|
||||||
|
public WasmTest(WasmExpression value, WasmType.Reference testType) {
|
||||||
|
this(value, testType, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmTest(WasmExpression value, WasmType.Reference testType, boolean nullable) {
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
this.testType = Objects.requireNonNull(testType);
|
||||||
|
this.nullable = nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmExpression getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(WasmExpression value) {
|
||||||
|
this.value = Objects.requireNonNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WasmType.Reference getTestType() {
|
||||||
|
return testType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTestType(WasmType.Reference testType) {
|
||||||
|
this.testType = Objects.requireNonNull(testType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNullable() {
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNullable(boolean nullable) {
|
||||||
|
this.nullable = nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void acceptVisitor(WasmExpressionVisitor visitor) {
|
||||||
|
visitor.visit(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,7 @@ import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmTest;
|
||||||
|
|
||||||
public class UnusedTypeElimination {
|
public class UnusedTypeElimination {
|
||||||
private WasmModule module;
|
private WasmModule module;
|
||||||
|
@ -103,6 +104,11 @@ public class UnusedTypeElimination {
|
||||||
use(expression.getTargetType());
|
use(expression.getTargetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmTest expression) {
|
||||||
|
super.visit(expression);
|
||||||
|
use(expression.getTestType());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmArrayGet expression) {
|
public void visit(WasmArrayGet expression) {
|
||||||
|
|
|
@ -135,7 +135,10 @@ public interface CodeListener {
|
||||||
default void nullConstant(WasmHollowType.Reference type) {
|
default void nullConstant(WasmHollowType.Reference type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default void cast(WasmHollowType.Reference type) {
|
default void cast(WasmHollowType.Reference type, boolean nullable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
default void test(WasmHollowType.Reference type, boolean nullable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default void structNew(int typeIndex) {
|
default void structNew(int typeIndex) {
|
||||||
|
@ -173,4 +176,10 @@ public interface CodeListener {
|
||||||
|
|
||||||
default void functionReference(int functionIndex) {
|
default void functionReference(int functionIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void int31Reference() {
|
||||||
|
}
|
||||||
|
|
||||||
|
default void int31Get(WasmSignedType signedType) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -727,8 +727,31 @@ public class CodeSectionParser {
|
||||||
codeListener.arrayCopy(readLEB(), readLEB());
|
codeListener.arrayCopy(readLEB(), readLEB());
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case 20:
|
||||||
|
codeListener.test(readHeapType(), false);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 21:
|
||||||
|
codeListener.test(readHeapType(), true);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 22:
|
||||||
|
codeListener.cast(readHeapType(), false);
|
||||||
|
return true;
|
||||||
|
|
||||||
case 23:
|
case 23:
|
||||||
codeListener.cast(readHeapType());
|
codeListener.cast(readHeapType(), true);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 28:
|
||||||
|
codeListener.int31Reference();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 29:
|
||||||
|
codeListener.int31Get(WasmSignedType.SIGNED);
|
||||||
|
return true;
|
||||||
|
case 30:
|
||||||
|
codeListener.int31Get(WasmSignedType.UNSIGNED);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -868,6 +891,8 @@ public class CodeSectionParser {
|
||||||
return WasmHollowType.Reference.EXTERN;
|
return WasmHollowType.Reference.EXTERN;
|
||||||
case 0x6E:
|
case 0x6E:
|
||||||
return WasmHollowType.Reference.ANY;
|
return WasmHollowType.Reference.ANY;
|
||||||
|
case 0x6C:
|
||||||
|
return WasmHollowType.Reference.I31;
|
||||||
case 0x6B:
|
case 0x6B:
|
||||||
return WasmHollowType.Reference.STRUCT;
|
return WasmHollowType.Reference.STRUCT;
|
||||||
case 0x6A:
|
case 0x6A:
|
||||||
|
|
|
@ -61,6 +61,7 @@ public class WasmHollowType {
|
||||||
public static final SpecialReference EXTERN = new SpecialReference(WasmType.SpecialReferenceKind.EXTERN);
|
public static final SpecialReference EXTERN = new SpecialReference(WasmType.SpecialReferenceKind.EXTERN);
|
||||||
public static final SpecialReference STRUCT = new SpecialReference(WasmType.SpecialReferenceKind.STRUCT);
|
public static final SpecialReference STRUCT = new SpecialReference(WasmType.SpecialReferenceKind.STRUCT);
|
||||||
public static final SpecialReference ARRAY = new SpecialReference(WasmType.SpecialReferenceKind.ARRAY);
|
public static final SpecialReference ARRAY = new SpecialReference(WasmType.SpecialReferenceKind.ARRAY);
|
||||||
|
public static final SpecialReference I31 = new SpecialReference(WasmType.SpecialReferenceKind.I31);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class CompositeReference extends WasmHollowType.Reference {
|
public static final class CompositeReference extends WasmHollowType.Reference {
|
||||||
|
|
|
@ -54,6 +54,8 @@ import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Get;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Reference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
|
@ -68,6 +70,7 @@ import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
|
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
|
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
|
@ -77,6 +80,7 @@ import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmTest;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmTry;
|
import org.teavm.backend.wasm.model.expression.WasmTry;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
|
@ -1071,11 +1075,21 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
pushLocation(expression);
|
pushLocation(expression);
|
||||||
expression.getValue().acceptVisitor(this);
|
expression.getValue().acceptVisitor(this);
|
||||||
writer.writeByte(0xfb);
|
writer.writeByte(0xfb);
|
||||||
writer.writeByte(23);
|
writer.writeByte(expression.isNullable() ? 23 : 22);
|
||||||
writer.writeHeapType(expression.getTargetType(), module);
|
writer.writeHeapType(expression.getTargetType(), module);
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmTest expression) {
|
||||||
|
pushLocation(expression);
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
writer.writeByte(0xfb);
|
||||||
|
writer.writeByte(expression.isNullable() ? 21 : 20);
|
||||||
|
writer.writeHeapType(expression.getTestType(), module);
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructNew expression) {
|
public void visit(WasmStructNew expression) {
|
||||||
pushLocation(expression);
|
pushLocation(expression);
|
||||||
|
@ -1207,6 +1221,24 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Reference expression) {
|
||||||
|
pushLocation(expression);
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
writer.writeByte(0xfb);
|
||||||
|
writer.writeByte(28);
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Get expression) {
|
||||||
|
pushLocation(expression);
|
||||||
|
expression.getValue().acceptVisitor(this);
|
||||||
|
writer.writeByte(0xfb);
|
||||||
|
writer.writeByte(expression.getSignedType() == WasmSignedType.SIGNED ? 29 : 30);
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
|
|
||||||
private int alignment(int value) {
|
private int alignment(int value) {
|
||||||
return 31 - Integer.numberOfLeadingZeros(Math.max(1, value));
|
return 31 - Integer.numberOfLeadingZeros(Math.max(1, value));
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,9 @@ public class WasmBinaryWriter {
|
||||||
case ARRAY:
|
case ARRAY:
|
||||||
writeByte(0x6a);
|
writeByte(0x6a);
|
||||||
break;
|
break;
|
||||||
|
case I31:
|
||||||
|
writeByte(0x6c);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,8 @@ import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Get;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Reference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
|
@ -78,6 +80,7 @@ import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmTest;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmTry;
|
import org.teavm.backend.wasm.model.expression.WasmTry;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
|
@ -1170,6 +1173,11 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
||||||
unsupported();
|
unsupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmTest expression) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructNew expression) {
|
public void visit(WasmStructNew expression) {
|
||||||
unsupported();
|
unsupported();
|
||||||
|
@ -1220,6 +1228,16 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor {
|
||||||
unsupported();
|
unsupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Reference expression) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Get expression) {
|
||||||
|
unsupported();
|
||||||
|
}
|
||||||
|
|
||||||
private void unsupported() {
|
private void unsupported() {
|
||||||
value = new CExpression("/* unsupported */");
|
value = new CExpression("/* unsupported */");
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Get;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Reference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
|
@ -70,6 +72,7 @@ import org.teavm.backend.wasm.model.expression.WasmReferencesEqual;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
import org.teavm.backend.wasm.model.expression.WasmReturn;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmSetLocal;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
|
import org.teavm.backend.wasm.model.expression.WasmStoreFloat32;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
|
import org.teavm.backend.wasm.model.expression.WasmStoreFloat64;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
import org.teavm.backend.wasm.model.expression.WasmStoreInt32;
|
||||||
|
@ -79,6 +82,7 @@ import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmTest;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmTry;
|
import org.teavm.backend.wasm.model.expression.WasmTry;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
|
@ -700,6 +704,13 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmTest expression) {
|
||||||
|
open().append("ref.test ").append(type(expression.getTestType()));
|
||||||
|
line(expression.getValue());
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructNew expression) {
|
public void visit(WasmStructNew expression) {
|
||||||
open().append("struct.new ");
|
open().append("struct.new ");
|
||||||
|
@ -811,6 +822,20 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Reference expression) {
|
||||||
|
open().append("ref.i31 ");
|
||||||
|
line(expression.getValue());
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Get expression) {
|
||||||
|
open().append("i31.get_" + (expression.getSignedType() == WasmSignedType.SIGNED ? "s" : "u"));
|
||||||
|
line(expression.getValue());
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
private String type(WasmType type) {
|
private String type(WasmType type) {
|
||||||
if (type instanceof WasmType.Number) {
|
if (type instanceof WasmType.Number) {
|
||||||
return type(((WasmType.Number) type).number);
|
return type(((WasmType.Number) type).number);
|
||||||
|
@ -826,6 +851,8 @@ class WasmRenderingVisitor implements WasmExpressionVisitor {
|
||||||
return "funcref";
|
return "funcref";
|
||||||
case ARRAY:
|
case ARRAY:
|
||||||
return "arrayref";
|
return "arrayref";
|
||||||
|
case I31:
|
||||||
|
return "i31ref";
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Get;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmInt31Reference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
import org.teavm.backend.wasm.model.expression.WasmInt64Constant;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||||
|
@ -66,6 +68,7 @@ import org.teavm.backend.wasm.model.expression.WasmStructNew;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
import org.teavm.backend.wasm.model.expression.WasmSwitch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmTest;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmTry;
|
import org.teavm.backend.wasm.model.expression.WasmTry;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
|
@ -278,6 +281,11 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
||||||
result = expression.getTargetType();
|
result = expression.getTargetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmTest expression) {
|
||||||
|
result = WasmType.INT32;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WasmStructNew expression) {
|
public void visit(WasmStructNew expression) {
|
||||||
result = expression.getType().getReference();
|
result = expression.getType().getReference();
|
||||||
|
@ -328,6 +336,16 @@ public class WasmTypeInference implements WasmExpressionVisitor {
|
||||||
result = expression.getFunction().getType().getReference();
|
result = expression.getFunction().getType().getReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Get expression) {
|
||||||
|
result = WasmType.INT32;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(WasmInt31Reference expression) {
|
||||||
|
result = WasmType.Reference.I31;
|
||||||
|
}
|
||||||
|
|
||||||
private static WasmType map(WasmIntType type) {
|
private static WasmType map(WasmIntType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT32:
|
case INT32:
|
||||||
|
|
|
@ -18,6 +18,8 @@ package org.teavm.backend.wasm.runtime;
|
||||||
import org.teavm.interop.Import;
|
import org.teavm.interop.Import;
|
||||||
|
|
||||||
public class WasmGCSupport {
|
public class WasmGCSupport {
|
||||||
|
private static int lastObjectId = 1831433054;
|
||||||
|
|
||||||
private WasmGCSupport() {
|
private WasmGCSupport() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +39,15 @@ public class WasmGCSupport {
|
||||||
return new CloneNotSupportedException();
|
return new CloneNotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int nextObjectId() {
|
||||||
|
var x = lastObjectId;
|
||||||
|
x ^= x << 13;
|
||||||
|
x ^= x >>> 17;
|
||||||
|
x ^= x << 5;
|
||||||
|
lastObjectId = x;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
@Import(name = "putcharStdout")
|
@Import(name = "putcharStdout")
|
||||||
public static native void putCharStdout(char c);
|
public static native void putCharStdout(char c);
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,29 @@
|
||||||
package org.teavm.backend.wasm.transformation.gc;
|
package org.teavm.backend.wasm.transformation.gc;
|
||||||
|
|
||||||
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
||||||
|
import org.teavm.model.AccessLevel;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassHolderTransformer;
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.ClassHolderTransformerContext;
|
import org.teavm.model.ClassHolderTransformerContext;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.Program;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.emit.ProgramEmitter;
|
import org.teavm.model.emit.ProgramEmitter;
|
||||||
|
import org.teavm.model.instructions.GetFieldInstruction;
|
||||||
|
import org.teavm.model.instructions.InvocationType;
|
||||||
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
|
import org.teavm.model.instructions.PutFieldInstruction;
|
||||||
|
|
||||||
public class BaseClassesTransformation implements ClassHolderTransformer {
|
public class BaseClassesTransformation implements ClassHolderTransformer {
|
||||||
|
private static final MethodReference GET_MONITOR = new MethodReference(Object.class.getName(),
|
||||||
|
"getMonitor", ValueType.object("java.lang.Object$Monitor"));
|
||||||
|
private static final MethodReference SET_MONITOR = new MethodReference(Object.class.getName(),
|
||||||
|
"setMonitor", ValueType.object("java.lang.Object$Monitor"), ValueType.VOID);
|
||||||
|
private static final FieldReference MONITOR = new FieldReference(Object.class.getName(), "monitor");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) {
|
public void transformClass(ClassHolder cls, ClassHolderTransformerContext context) {
|
||||||
if (cls.getName().equals("java.lang.Object")) {
|
if (cls.getName().equals("java.lang.Object")) {
|
||||||
|
@ -37,8 +53,22 @@ public class BaseClassesTransformation implements ClassHolderTransformer {
|
||||||
em.invoke(WasmGCSupport.class, "cnse", CloneNotSupportedException.class).raise();
|
em.invoke(WasmGCSupport.class, "cnse", CloneNotSupportedException.class).raise();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
if (method.getProgram() != null) {
|
||||||
|
transformMonitorFieldAccess(method.getProgram());
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var getMonitorMethod = new MethodHolder(GET_MONITOR.getDescriptor());
|
||||||
|
getMonitorMethod.setLevel(AccessLevel.PRIVATE);
|
||||||
|
getMonitorMethod.getModifiers().add(ElementModifier.NATIVE);
|
||||||
|
cls.addMethod(getMonitorMethod);
|
||||||
|
|
||||||
|
var setMonitorMethod = new MethodHolder(SET_MONITOR.getDescriptor());
|
||||||
|
setMonitorMethod.setLevel(AccessLevel.PRIVATE);
|
||||||
|
setMonitorMethod.getModifiers().add(ElementModifier.NATIVE);
|
||||||
|
cls.addMethod(setMonitorMethod);
|
||||||
} else if (cls.getName().equals("java.lang.Class")) {
|
} else if (cls.getName().equals("java.lang.Class")) {
|
||||||
for (var method : cls.getMethods()) {
|
for (var method : cls.getMethods()) {
|
||||||
switch (method.getName()) {
|
switch (method.getName()) {
|
||||||
|
@ -49,6 +79,45 @@ public class BaseClassesTransformation implements ClassHolderTransformer {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (cls.getName().equals("java.lang.System")) {
|
||||||
|
for (var method : cls.getMethods()) {
|
||||||
|
switch (method.getName()) {
|
||||||
|
case "arraycopy":
|
||||||
|
method.setProgram(null);
|
||||||
|
method.getModifiers().add(ElementModifier.NATIVE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transformMonitorFieldAccess(Program program) {
|
||||||
|
for (var block : program.getBasicBlocks()) {
|
||||||
|
for (var instruction : block) {
|
||||||
|
if (instruction instanceof GetFieldInstruction) {
|
||||||
|
var getField = (GetFieldInstruction) instruction;
|
||||||
|
if (getField.getField().equals(MONITOR)) {
|
||||||
|
var invocation = new InvokeInstruction();
|
||||||
|
invocation.setType(InvocationType.SPECIAL);
|
||||||
|
invocation.setInstance(getField.getInstance());
|
||||||
|
invocation.setMethod(GET_MONITOR);
|
||||||
|
invocation.setReceiver(getField.getReceiver());
|
||||||
|
invocation.setLocation(getField.getLocation());
|
||||||
|
getField.replace(invocation);
|
||||||
|
}
|
||||||
|
} else if (instruction instanceof PutFieldInstruction) {
|
||||||
|
var putField = (PutFieldInstruction) instruction;
|
||||||
|
if (putField.getField().equals(MONITOR)) {
|
||||||
|
var invocation = new InvokeInstruction();
|
||||||
|
invocation.setType(InvocationType.SPECIAL);
|
||||||
|
invocation.setInstance(putField.getInstance());
|
||||||
|
invocation.setMethod(SET_MONITOR);
|
||||||
|
invocation.setArguments(putField.getValue());
|
||||||
|
invocation.setLocation(putField.getLocation());
|
||||||
|
putField.replace(invocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,7 @@ public abstract class BaseTypeInference<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullConstantInstruction insn) {
|
public void visit(NullConstantInstruction insn) {
|
||||||
types[insn.getReceiver().getIndex()] = nullType();
|
type(insn.getReceiver(), nullType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -454,6 +454,10 @@ public abstract class BaseTypeInference<T> {
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
var t = mapType(type);
|
var t = mapType(type);
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
|
if (types[target.getIndex()] != null) {
|
||||||
|
//noinspection unchecked
|
||||||
|
t = merge((T) types[target.getIndex()], t);
|
||||||
|
}
|
||||||
types[target.getIndex()] = t;
|
types[target.getIndex()] = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,6 +465,10 @@ public abstract class BaseTypeInference<T> {
|
||||||
|
|
||||||
void type(Variable target, T type) {
|
void type(Variable target, T type) {
|
||||||
if (target != null && type != null) {
|
if (target != null && type != null) {
|
||||||
|
if (types[target.getIndex()] != null) {
|
||||||
|
//noinspection unchecked
|
||||||
|
type = merge((T) types[target.getIndex()], type);
|
||||||
|
}
|
||||||
types[target.getIndex()] = type;
|
types[target.getIndex()] = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -388,7 +388,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
return !cancelled;
|
return !cancelled;
|
||||||
});
|
});
|
||||||
target.contributeDependencies(dependencyAnalyzer);
|
target.contributeDependencies(dependencyAnalyzer);
|
||||||
dependencyAnalyzer.addDependencyListener(new StdlibDependencyListener());
|
if (target.needsSystemArrayCopyOptimization()) {
|
||||||
|
dependencyAnalyzer.addDependencyListener(new StdlibDependencyListener());
|
||||||
|
}
|
||||||
dependencyAnalyzer.processDependencies();
|
dependencyAnalyzer.processDependencies();
|
||||||
if (wasCancelled() || !diagnostics.getSevereProblems().isEmpty()) {
|
if (wasCancelled() || !diagnostics.getSevereProblems().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user