mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Introduce concept of 'weak' cast.
Use weak casts to maintain proper typing within methods during various operations on IR. At generation level, ignore weak casts, except for Wasm GC BE, which turns weak casts into platform casts.
This commit is contained in:
parent
8b52741e04
commit
a97e6574ac
|
@ -21,6 +21,7 @@ import org.teavm.model.ValueType;
|
||||||
public class CastExpr extends Expr {
|
public class CastExpr extends Expr {
|
||||||
private Expr value;
|
private Expr value;
|
||||||
private ValueType target;
|
private ValueType target;
|
||||||
|
private boolean weak;
|
||||||
|
|
||||||
public Expr getValue() {
|
public Expr getValue() {
|
||||||
return value;
|
return value;
|
||||||
|
@ -38,6 +39,14 @@ public class CastExpr extends Expr {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWeak() {
|
||||||
|
return weak;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeak(boolean weak) {
|
||||||
|
this.weak = weak;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(ExprVisitor visitor) {
|
public void acceptVisitor(ExprVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
@ -48,6 +57,7 @@ public class CastExpr extends Expr {
|
||||||
CastExpr copy = new CastExpr();
|
CastExpr copy = new CastExpr();
|
||||||
copy.value = value.clone(cache);
|
copy.value = value.clone(cache);
|
||||||
copy.target = target;
|
copy.target = target;
|
||||||
|
copy.weak = weak;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,7 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
expr.setVariableIndex(insn.getReceiver().getIndex());
|
expr.setVariableIndex(insn.getReceiver().getIndex());
|
||||||
expr.setValue(Expr.var(insn.getValue().getIndex()));
|
expr.setValue(Expr.var(insn.getValue().getIndex()));
|
||||||
expr.setTarget(insn.getTargetType());
|
expr.setTarget(insn.getTargetType());
|
||||||
|
expr.setWeak(insn.isWeak());
|
||||||
assign(expr, insn.getReceiver());
|
assign(expr, insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1056,6 +1056,11 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastExpr expr) {
|
public void visit(CastExpr expr) {
|
||||||
|
if (expr.isWeak()) {
|
||||||
|
expr.getValue().acceptVisitor(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (expr.getTarget() instanceof ValueType.Object) {
|
if (expr.getTarget() instanceof ValueType.Object) {
|
||||||
String className = ((ValueType.Object) expr.getTarget()).getClassName();
|
String className = ((ValueType.Object) expr.getTarget()).getClassName();
|
||||||
if (!context.getCharacteristics().isManaged(className)) {
|
if (!context.getCharacteristics().isManaged(className)) {
|
||||||
|
|
|
@ -878,7 +878,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastExpr expr) {
|
public void visit(CastExpr expr) {
|
||||||
if (context.isStrict()) {
|
if (context.isStrict() && !expr.isWeak()) {
|
||||||
if (expr.getLocation() != null) {
|
if (expr.getLocation() != null) {
|
||||||
pushLocation(expr.getLocation());
|
pushLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,19 +20,15 @@ import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.analysis.BaseTypeInference;
|
import org.teavm.model.analysis.BaseTypeInference;
|
||||||
import org.teavm.model.instructions.InvocationType;
|
|
||||||
|
|
||||||
public class PreciseTypeInference extends BaseTypeInference<PreciseValueType> {
|
public class PreciseTypeInference extends BaseTypeInference<PreciseValueType> {
|
||||||
public static final PreciseValueType OBJECT_TYPE = new PreciseValueType(ValueType.object("java.lang.Object"),
|
public static final PreciseValueType OBJECT_TYPE = new PreciseValueType(ValueType.object("java.lang.Object"),
|
||||||
false);
|
false);
|
||||||
private ClassHierarchy hierarchy;
|
private ClassHierarchy hierarchy;
|
||||||
private WasmGCMethodReturnTypes returnTypes;
|
|
||||||
|
|
||||||
public PreciseTypeInference(Program program, MethodReference reference, ClassHierarchy hierarchy,
|
public PreciseTypeInference(Program program, MethodReference reference, ClassHierarchy hierarchy) {
|
||||||
WasmGCMethodReturnTypes returnTypes) {
|
|
||||||
super(program, reference);
|
super(program, reference);
|
||||||
this.hierarchy = hierarchy;
|
this.hierarchy = hierarchy;
|
||||||
this.returnTypes = returnTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -108,14 +104,6 @@ public class PreciseTypeInference extends BaseTypeInference<PreciseValueType> {
|
||||||
return new PreciseValueType(ValueType.arrayOf(preciseValueType.valueType), false);
|
return new PreciseValueType(ValueType.arrayOf(preciseValueType.valueType), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected PreciseValueType methodReturnType(InvocationType invocationType, MethodReference methodRef) {
|
|
||||||
if (invocationType == InvocationType.SPECIAL) {
|
|
||||||
return new PreciseValueType(returnTypes.returnTypeOf(methodRef), false);
|
|
||||||
}
|
|
||||||
return super.methodReturnType(invocationType, methodRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PreciseValueType arrayUnwrapType(PreciseValueType type) {
|
protected PreciseValueType arrayUnwrapType(PreciseValueType type) {
|
||||||
return new PreciseValueType(type.valueType, true);
|
return new PreciseValueType(type.valueType, true);
|
||||||
|
|
|
@ -1,64 +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.gc;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.teavm.dependency.DependencyInfo;
|
|
||||||
import org.teavm.model.ClassHierarchy;
|
|
||||||
import org.teavm.model.MethodReference;
|
|
||||||
import org.teavm.model.ValueType;
|
|
||||||
|
|
||||||
public class WasmGCMethodReturnTypes {
|
|
||||||
private DependencyInfo dependencyInfo;
|
|
||||||
private ClassHierarchy hierarchy;
|
|
||||||
private Map<MethodReference, ValueType> cache = new HashMap<>();
|
|
||||||
|
|
||||||
public WasmGCMethodReturnTypes(DependencyInfo dependencyInfo, ClassHierarchy hierarchy) {
|
|
||||||
this.dependencyInfo = dependencyInfo;
|
|
||||||
this.hierarchy = hierarchy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueType returnTypeOf(MethodReference reference) {
|
|
||||||
return cache.computeIfAbsent(reference, this::calculateReturnType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ValueType calculateReturnType(MethodReference reference) {
|
|
||||||
if (!(reference.getReturnType() instanceof ValueType.Object)) {
|
|
||||||
return reference.getReturnType();
|
|
||||||
}
|
|
||||||
var method = dependencyInfo.getMethod(reference);
|
|
||||||
if (method == null) {
|
|
||||||
return reference.getReturnType();
|
|
||||||
}
|
|
||||||
var types = method.getResult().getTypes();
|
|
||||||
if (types.length == 0) {
|
|
||||||
return reference.getReturnType();
|
|
||||||
}
|
|
||||||
var type = hierarchy.getClassSource().get(types[0]);
|
|
||||||
if (type == null) {
|
|
||||||
return reference.getReturnType();
|
|
||||||
}
|
|
||||||
for (var i = 1; i < types.length; ++i) {
|
|
||||||
var otherType = hierarchy.getClassSource().get(types[i]);
|
|
||||||
if (otherType == null) {
|
|
||||||
return reference.getReturnType();
|
|
||||||
}
|
|
||||||
type = hierarchy.getClassSource().get(WasmGCUtil.findCommonSuperclass(hierarchy, type, otherType));
|
|
||||||
}
|
|
||||||
return ValueType.object(type.getName());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,11 +23,9 @@ import org.teavm.model.util.VariableCategoryProvider;
|
||||||
public class WasmGCVariableCategoryProvider implements VariableCategoryProvider {
|
public class WasmGCVariableCategoryProvider implements VariableCategoryProvider {
|
||||||
private ClassHierarchy hierarchy;
|
private ClassHierarchy hierarchy;
|
||||||
private PreciseTypeInference inference;
|
private PreciseTypeInference inference;
|
||||||
private WasmGCMethodReturnTypes returnTypes;
|
|
||||||
|
|
||||||
public WasmGCVariableCategoryProvider(ClassHierarchy hierarchy, WasmGCMethodReturnTypes returnTypes) {
|
public WasmGCVariableCategoryProvider(ClassHierarchy hierarchy) {
|
||||||
this.hierarchy = hierarchy;
|
this.hierarchy = hierarchy;
|
||||||
this.returnTypes = returnTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreciseTypeInference getTypeInference() {
|
public PreciseTypeInference getTypeInference() {
|
||||||
|
@ -36,7 +34,7 @@ public class WasmGCVariableCategoryProvider implements VariableCategoryProvider
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] getCategories(Program program, MethodReference method) {
|
public Object[] getCategories(Program program, MethodReference method) {
|
||||||
inference = new PreciseTypeInference(program, method, hierarchy, returnTypes);
|
inference = new PreciseTypeInference(program, method, hierarchy);
|
||||||
inference.setPhisSkipped(true);
|
inference.setPhisSkipped(true);
|
||||||
inference.setBackPropagation(true);
|
inference.setBackPropagation(true);
|
||||||
var result = new Object[program.variableCount()];
|
var result = new Object[program.variableCount()];
|
||||||
|
|
|
@ -1170,6 +1170,11 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastExpr expr) {
|
public void visit(CastExpr expr) {
|
||||||
|
if (expr.isWeak()) {
|
||||||
|
acceptWithType(expr.getValue(), expr.getTarget());
|
||||||
|
result = generateCast(result, mapType(expr.getTarget()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
var block = new WasmBlock(false);
|
var block = new WasmBlock(false);
|
||||||
var wasmTargetType = mapType(expr.getTarget());
|
var wasmTargetType = mapType(expr.getTarget());
|
||||||
block.setType(wasmTargetType);
|
block.setType(wasmTargetType);
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||||
import org.teavm.backend.wasm.gc.WasmGCMethodReturnTypes;
|
|
||||||
import org.teavm.backend.wasm.generate.WasmNameProvider;
|
import org.teavm.backend.wasm.generate.WasmNameProvider;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassGenerator;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassGenerator;
|
||||||
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
|
||||||
|
@ -47,7 +46,6 @@ public class WasmGCDeclarationsGenerator {
|
||||||
public final WasmFunctionTypes functionTypes;
|
public final WasmFunctionTypes functionTypes;
|
||||||
private final WasmGCClassGenerator classGenerator;
|
private final WasmGCClassGenerator classGenerator;
|
||||||
private final WasmGCMethodGenerator methodGenerator;
|
private final WasmGCMethodGenerator methodGenerator;
|
||||||
private final WasmGCMethodReturnTypes returnTypes;
|
|
||||||
|
|
||||||
public WasmGCDeclarationsGenerator(
|
public WasmGCDeclarationsGenerator(
|
||||||
WasmModule module,
|
WasmModule module,
|
||||||
|
@ -64,7 +62,6 @@ public class WasmGCDeclarationsGenerator {
|
||||||
var virtualTables = createVirtualTableProvider(classes, virtualMethods);
|
var virtualTables = createVirtualTableProvider(classes, virtualMethods);
|
||||||
functionTypes = new WasmFunctionTypes(module);
|
functionTypes = new WasmFunctionTypes(module);
|
||||||
var names = new WasmNameProvider();
|
var names = new WasmNameProvider();
|
||||||
returnTypes = new WasmGCMethodReturnTypes(dependencyInfo, hierarchy);
|
|
||||||
methodGenerator = new WasmGCMethodGenerator(
|
methodGenerator = new WasmGCMethodGenerator(
|
||||||
module,
|
module,
|
||||||
hierarchy,
|
hierarchy,
|
||||||
|
@ -74,7 +71,6 @@ public class WasmGCDeclarationsGenerator {
|
||||||
functionTypes,
|
functionTypes,
|
||||||
names,
|
names,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
returnTypes,
|
|
||||||
customGenerators,
|
customGenerators,
|
||||||
intrinsics
|
intrinsics
|
||||||
);
|
);
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
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.WasmGCMethodReturnTypes;
|
|
||||||
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationContext;
|
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationContext;
|
||||||
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.WasmGCStandardClasses;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
||||||
|
@ -57,7 +56,6 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
private WasmGCSupertypeFunctionProvider supertypeFunctions;
|
private WasmGCSupertypeFunctionProvider supertypeFunctions;
|
||||||
private WasmGCCustomGeneratorProvider customGenerators;
|
private WasmGCCustomGeneratorProvider customGenerators;
|
||||||
private WasmGCIntrinsicProvider intrinsics;
|
private WasmGCIntrinsicProvider intrinsics;
|
||||||
private WasmGCMethodReturnTypes returnTypes;
|
|
||||||
private WasmFunction npeMethod;
|
private WasmFunction npeMethod;
|
||||||
private WasmFunction aaiobeMethod;
|
private WasmFunction aaiobeMethod;
|
||||||
private WasmFunction cceMethod;
|
private WasmFunction cceMethod;
|
||||||
|
@ -70,8 +68,7 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
ClassHierarchy hierarchy, BaseWasmFunctionRepository functions,
|
ClassHierarchy hierarchy, BaseWasmFunctionRepository functions,
|
||||||
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
|
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
|
||||||
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
|
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
|
||||||
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics,
|
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics) {
|
||||||
WasmGCMethodReturnTypes returnTypes) {
|
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.virtualTables = virtualTables;
|
this.virtualTables = virtualTables;
|
||||||
this.typeMapper = typeMapper;
|
this.typeMapper = typeMapper;
|
||||||
|
@ -85,7 +82,6 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
this.strings = strings;
|
this.strings = strings;
|
||||||
this.customGenerators = customGenerators;
|
this.customGenerators = customGenerators;
|
||||||
this.intrinsics = intrinsics;
|
this.intrinsics = intrinsics;
|
||||||
this.returnTypes = returnTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmGCClassInfoProvider classInfoProvider() {
|
public WasmGCClassInfoProvider classInfoProvider() {
|
||||||
|
@ -186,10 +182,6 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
|
||||||
return intrinsics;
|
return intrinsics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WasmGCMethodReturnTypes returnTypes() {
|
|
||||||
return returnTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<String> getInterfaceImplementors(String className) {
|
public Collection<String> getInterfaceImplementors(String className) {
|
||||||
if (interfaceImplementors == null) {
|
if (interfaceImplementors == null) {
|
||||||
fillInterfaceImplementors();
|
fillInterfaceImplementors();
|
||||||
|
|
|
@ -481,7 +481,7 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WasmExpression forceType(WasmExpression expression, ValueType type) {
|
protected WasmExpression forceType(WasmExpression expression, ValueType type) {
|
||||||
return forceType(expression, mapType(context.returnTypes().returnTypeOf(currentMethod)));
|
return forceType(expression, mapType(currentMethod.getReturnType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private WasmExpression forceType(WasmExpression expression, WasmType expectedType) {
|
private WasmExpression forceType(WasmExpression expression, WasmType expectedType) {
|
||||||
|
|
|
@ -25,7 +25,6 @@ import org.teavm.ast.decompilation.Decompiler;
|
||||||
import org.teavm.backend.lowlevel.generate.NameProvider;
|
import org.teavm.backend.lowlevel.generate.NameProvider;
|
||||||
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.WasmGCMethodReturnTypes;
|
|
||||||
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
|
||||||
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.WasmGCStandardClasses;
|
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
|
||||||
|
@ -78,7 +77,6 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
private WasmGCClassInfoProvider classInfoProvider;
|
private WasmGCClassInfoProvider classInfoProvider;
|
||||||
private WasmGCStandardClasses standardClasses;
|
private WasmGCStandardClasses standardClasses;
|
||||||
private WasmGCStringProvider strings;
|
private WasmGCStringProvider strings;
|
||||||
private WasmGCMethodReturnTypes returnTypes;
|
|
||||||
|
|
||||||
public WasmGCMethodGenerator(
|
public WasmGCMethodGenerator(
|
||||||
WasmModule module,
|
WasmModule module,
|
||||||
|
@ -89,7 +87,6 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
WasmFunctionTypes functionTypes,
|
WasmFunctionTypes functionTypes,
|
||||||
NameProvider names,
|
NameProvider names,
|
||||||
Diagnostics diagnostics,
|
Diagnostics diagnostics,
|
||||||
WasmGCMethodReturnTypes returnTypes,
|
|
||||||
WasmGCCustomGeneratorProvider customGenerators,
|
WasmGCCustomGeneratorProvider customGenerators,
|
||||||
WasmGCIntrinsicProvider intrinsics
|
WasmGCIntrinsicProvider intrinsics
|
||||||
) {
|
) {
|
||||||
|
@ -101,7 +98,6 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
this.functionTypes = functionTypes;
|
this.functionTypes = functionTypes;
|
||||||
this.names = names;
|
this.names = names;
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
this.returnTypes = returnTypes;
|
|
||||||
this.customGenerators = customGenerators;
|
this.customGenerators = customGenerators;
|
||||||
this.intrinsics = intrinsics;
|
this.intrinsics = intrinsics;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +142,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
private WasmFunction createStaticFunction(MethodReference methodReference) {
|
private WasmFunction createStaticFunction(MethodReference methodReference) {
|
||||||
var returnType = typeMapper.mapType(returnTypes.returnTypeOf(methodReference));
|
var returnType = typeMapper.mapType(methodReference.getReturnType());
|
||||||
var parameterTypes = new WasmType[methodReference.parameterCount()];
|
var parameterTypes = new WasmType[methodReference.parameterCount()];
|
||||||
for (var i = 0; i < parameterTypes.length; ++i) {
|
for (var i = 0; i < parameterTypes.length; ++i) {
|
||||||
parameterTypes[i] = typeMapper.mapType(methodReference.parameterType(i));
|
parameterTypes[i] = typeMapper.mapType(methodReference.parameterType(i));
|
||||||
|
@ -173,7 +169,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
private WasmFunction createInstanceFunction(MethodReference methodReference) {
|
private WasmFunction createInstanceFunction(MethodReference methodReference) {
|
||||||
var returnType = typeMapper.mapType(returnTypes.returnTypeOf(methodReference));
|
var returnType = typeMapper.mapType(methodReference.getReturnType());
|
||||||
var parameterTypes = new WasmType[methodReference.parameterCount() + 1];
|
var parameterTypes = new WasmType[methodReference.parameterCount() + 1];
|
||||||
parameterTypes[0] = typeMapper.mapType(ValueType.object(methodReference.getClassName()));
|
parameterTypes[0] = typeMapper.mapType(ValueType.object(methodReference.getClassName()));
|
||||||
for (var i = 0; i < methodReference.parameterCount(); ++i) {
|
for (var i = 0; i < methodReference.parameterCount(); ++i) {
|
||||||
|
@ -213,7 +209,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
|
|
||||||
private void generateRegularMethodBody(MethodHolder method, WasmFunction function) {
|
private void generateRegularMethodBody(MethodHolder method, WasmFunction function) {
|
||||||
var decompiler = getDecompiler();
|
var decompiler = getDecompiler();
|
||||||
var categoryProvider = new WasmGCVariableCategoryProvider(hierarchy, returnTypes);
|
var categoryProvider = new WasmGCVariableCategoryProvider(hierarchy);
|
||||||
var allocator = new RegisterAllocator(categoryProvider);
|
var allocator = new RegisterAllocator(categoryProvider);
|
||||||
allocator.allocateRegisters(method.getReference(), method.getProgram(), friendlyToDebugger);
|
allocator.allocateRegisters(method.getReference(), method.getProgram(), friendlyToDebugger);
|
||||||
var ast = decompiler.decompileRegular(method);
|
var ast = decompiler.decompileRegular(method);
|
||||||
|
@ -302,8 +298,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
|
||||||
standardClasses,
|
standardClasses,
|
||||||
strings,
|
strings,
|
||||||
customGenerators,
|
customGenerators,
|
||||||
intrinsics,
|
intrinsics
|
||||||
returnTypes
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
|
|
|
@ -714,6 +714,7 @@ public class AstIO {
|
||||||
output.writeUnsigned(23);
|
output.writeUnsigned(23);
|
||||||
output.writeUnsigned(symbolTable.lookup(expr.getTarget().toString()));
|
output.writeUnsigned(symbolTable.lookup(expr.getTarget().toString()));
|
||||||
writeExpr(expr.getValue());
|
writeExpr(expr.getValue());
|
||||||
|
output.writeUnsigned(expr.isWeak() ? 1 : 0);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
|
@ -1106,6 +1107,7 @@ public class AstIO {
|
||||||
expr.setLocation(lastReadLocation);
|
expr.setLocation(lastReadLocation);
|
||||||
expr.setTarget(ValueType.parse(symbolTable.at(input.readUnsigned())));
|
expr.setTarget(ValueType.parse(symbolTable.at(input.readUnsigned())));
|
||||||
expr.setValue(readExpr(input));
|
expr.setValue(readExpr(input));
|
||||||
|
expr.setWeak(input.readUnsigned() != 0);
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
case 24: {
|
case 24: {
|
||||||
|
|
|
@ -451,12 +451,13 @@ public class ProgramIO {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(25);
|
output.writeUnsigned(25);
|
||||||
output.writeUnsigned(receiver.getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(symbolTable.lookup(targetType.toString()));
|
output.writeUnsigned(symbolTable.lookup(targetType.toString()));
|
||||||
output.writeUnsigned(value.getIndex());
|
output.writeUnsigned(value.getIndex());
|
||||||
|
output.writeUnsigned(weak ? 1 : 0);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
|
@ -988,6 +989,7 @@ public class ProgramIO {
|
||||||
insn.setReceiver(program.variableAt(input.readUnsigned()));
|
insn.setReceiver(program.variableAt(input.readUnsigned()));
|
||||||
insn.setTargetType(parseValueType(symbolTable.at(input.readUnsigned())));
|
insn.setTargetType(parseValueType(symbolTable.at(input.readUnsigned())));
|
||||||
insn.setValue(program.variableAt(input.readUnsigned()));
|
insn.setValue(program.variableAt(input.readUnsigned()));
|
||||||
|
insn.setWeak(input.readUnsigned() != 0);
|
||||||
return insn;
|
return insn;
|
||||||
}
|
}
|
||||||
case 26: {
|
case 26: {
|
||||||
|
|
|
@ -228,13 +228,15 @@ abstract class AbstractInstructionAnalyzer extends AbstractInstructionReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
|
if (!weak) {
|
||||||
String className = extractClassName(targetType);
|
String className = extractClassName(targetType);
|
||||||
if (className != null) {
|
if (className != null) {
|
||||||
getAnalyzer().linkClass(className);
|
getAnalyzer().linkClass(className);
|
||||||
}
|
}
|
||||||
getAnalyzer().linkClass("java.lang.ClassCastException");
|
getAnalyzer().linkClass("java.lang.ClassCastException");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initClass(String className) {
|
public void initClass(String className) {
|
||||||
|
|
|
@ -95,7 +95,7 @@ class ClassClosureAnalyzer extends AbstractInstructionReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
build(targetType);
|
build(targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ public class DataFlowGraphBuilder extends AbstractInstructionReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
builder.addEdge(value.getIndex(), receiver.getIndex());
|
builder.addEdge(value.getIndex(), receiver.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,9 +221,11 @@ class DependencyGraphBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
super.cast(receiver, value, targetType);
|
super.cast(receiver, value, targetType, weak);
|
||||||
|
if (!weak) {
|
||||||
currentExceptionConsumer.consume(dependencyAnalyzer.getType("java.lang.ClassCastException"));
|
currentExceptionConsumer.consume(dependencyAnalyzer.getType("java.lang.ClassCastException"));
|
||||||
|
}
|
||||||
DependencyNode valueNode = nodes[value.getIndex()];
|
DependencyNode valueNode = nodes[value.getIndex()];
|
||||||
DependencyNode receiverNode = nodes[receiver.getIndex()];
|
DependencyNode receiverNode = nodes[receiver.getIndex()];
|
||||||
ClassReaderSource classSource = dependencyAnalyzer.getClassSource();
|
ClassReaderSource classSource = dependencyAnalyzer.getClassSource();
|
||||||
|
|
|
@ -83,7 +83,7 @@ public class InstructionReadVisitor implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastInstruction insn) {
|
public void visit(CastInstruction insn) {
|
||||||
reader.cast(insn.getReceiver(), insn.getValue(), insn.getTargetType());
|
reader.cast(insn.getReceiver(), insn.getValue(), insn.getTargetType(), insn.isWeak());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -340,7 +340,7 @@ public class Interpreter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean cast) {
|
||||||
variables[receiver.getIndex()] = asJvmClass(targetType).cast(variables[value.getIndex()]);
|
variables[receiver.getIndex()] = asJvmClass(targetType).cast(variables[value.getIndex()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class AbstractInstructionReader implements InstructionReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -23,6 +23,7 @@ public class CastInstruction extends Instruction {
|
||||||
private Variable value;
|
private Variable value;
|
||||||
private Variable receiver;
|
private Variable receiver;
|
||||||
private ValueType targetType;
|
private ValueType targetType;
|
||||||
|
private boolean weak;
|
||||||
|
|
||||||
public Variable getValue() {
|
public Variable getValue() {
|
||||||
return value;
|
return value;
|
||||||
|
@ -48,6 +49,14 @@ public class CastInstruction extends Instruction {
|
||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWeak() {
|
||||||
|
return weak;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeak(boolean weak) {
|
||||||
|
this.weak = weak;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(InstructionVisitor visitor) {
|
public void acceptVisitor(InstructionVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|
|
@ -44,7 +44,7 @@ public interface InstructionReader {
|
||||||
|
|
||||||
void assign(VariableReader receiver, VariableReader assignee);
|
void assign(VariableReader receiver, VariableReader assignee);
|
||||||
|
|
||||||
void cast(VariableReader receiver, VariableReader value, ValueType targetType);
|
void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak);
|
||||||
|
|
||||||
void cast(VariableReader receiver, VariableReader value, NumericOperandType sourceType,
|
void cast(VariableReader receiver, VariableReader value, NumericOperandType sourceType,
|
||||||
NumericOperandType targetType);
|
NumericOperandType targetType);
|
||||||
|
|
|
@ -43,9 +43,10 @@ public final class ExceptionHandlingUtil {
|
||||||
|| insn instanceof ConstructArrayInstruction || insn instanceof ConstructMultiArrayInstruction
|
|| insn instanceof ConstructArrayInstruction || insn instanceof ConstructMultiArrayInstruction
|
||||||
|| insn instanceof CloneArrayInstruction || insn instanceof RaiseInstruction
|
|| insn instanceof CloneArrayInstruction || insn instanceof RaiseInstruction
|
||||||
|| insn instanceof MonitorEnterInstruction || insn instanceof MonitorExitInstruction
|
|| insn instanceof MonitorEnterInstruction || insn instanceof MonitorExitInstruction
|
||||||
|| insn instanceof NullCheckInstruction || insn instanceof BoundCheckInstruction
|
|| insn instanceof NullCheckInstruction || insn instanceof BoundCheckInstruction) {
|
||||||
|| insn instanceof CastInstruction) {
|
|
||||||
return true;
|
return true;
|
||||||
|
} else if (insn instanceof CastInstruction) {
|
||||||
|
return !((CastInstruction) insn).isWeak();
|
||||||
} else if (insn instanceof InvokeInstruction) {
|
} else if (insn instanceof InvokeInstruction) {
|
||||||
return isManagedMethodCall(characteristics, ((InvokeInstruction) insn).getMethod());
|
return isManagedMethodCall(characteristics, ((InvokeInstruction) insn).getMethod());
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ public class NativePointerFinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
assignmentGraph.addEdge(value.getIndex(), receiver.getIndex());
|
assignmentGraph.addEdge(value.getIndex(), receiver.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.instructions.AssignInstruction;
|
|
||||||
import org.teavm.model.instructions.CastInstruction;
|
import org.teavm.model.instructions.CastInstruction;
|
||||||
import org.teavm.model.instructions.InvocationType;
|
import org.teavm.model.instructions.InvocationType;
|
||||||
import org.teavm.model.instructions.InvokeInstruction;
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
|
@ -172,11 +171,7 @@ public class Devirtualization {
|
||||||
}
|
}
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
AssignInstruction assign = new AssignInstruction();
|
cast.setWeak(true);
|
||||||
assign.setAssignee(cast.getValue());
|
|
||||||
assign.setReceiver(cast.getReceiver());
|
|
||||||
assign.setLocation(cast.getLocation());
|
|
||||||
cast.replace(assign);
|
|
||||||
eliminatedCasts++;
|
eliminatedCasts++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -570,7 +570,8 @@ public class GlobalValueNumbering implements MethodOptimization {
|
||||||
int a = map[insn.getValue().getIndex()];
|
int a = map[insn.getValue().getIndex()];
|
||||||
int p = replaceMap[insn.getValue().getIndex()];
|
int p = replaceMap[insn.getValue().getIndex()];
|
||||||
insn.setValue(program.variableAt(p));
|
insn.setValue(program.variableAt(p));
|
||||||
bind(insn.getReceiver().getIndex(), "@" + a + "::" + insn.getTargetType());
|
var operator = insn.isWeak() ? ":::" : "::";
|
||||||
|
bind(insn.getReceiver().getIndex(), "@" + a + operator + insn.getTargetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -240,8 +240,12 @@ class InstructionStringifier implements InstructionReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
appendLocalVar(receiver).append(" := cast ").appendLocalVar(value).append(" to ")
|
appendLocalVar(receiver).append(" := ");
|
||||||
|
if (weak) {
|
||||||
|
append("weak ");
|
||||||
|
}
|
||||||
|
append("cast ").appendLocalVar(value).append(" to ")
|
||||||
.escapeIdentifierIfNeeded(targetType.toString());
|
.escapeIdentifierIfNeeded(targetType.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,11 +208,12 @@ public class InstructionCopyReader implements InstructionReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
CastInstruction insnCopy = new CastInstruction();
|
CastInstruction insnCopy = new CastInstruction();
|
||||||
insnCopy.setValue(copyVar(value));
|
insnCopy.setValue(copyVar(value));
|
||||||
insnCopy.setReceiver(copyVar(receiver));
|
insnCopy.setReceiver(copyVar(receiver));
|
||||||
insnCopy.setTargetType(targetType);
|
insnCopy.setTargetType(targetType);
|
||||||
|
insnCopy.setWeak(weak);
|
||||||
copy = insnCopy;
|
copy = insnCopy;
|
||||||
copy.setLocation(location);
|
copy.setLocation(location);
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,7 +296,7 @@ public class TypeInferer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
types[receiver.getIndex()] = convert(targetType);
|
types[receiver.getIndex()] = convert(targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -465,6 +465,9 @@ class JSClassProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean processCast(CastInstruction cast, CallLocation location) {
|
private boolean processCast(CastInstruction cast, CallLocation location) {
|
||||||
|
if (cast.isWeak()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!(cast.getTargetType() instanceof ValueType.Object)) {
|
if (!(cast.getTargetType() instanceof ValueType.Object)) {
|
||||||
cast.setTargetType(processType(cast.getTargetType()));
|
cast.setTargetType(processType(cast.getTargetType()));
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -607,7 +607,7 @@ public class CompositeMethodGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
|
||||||
CastInstruction insn = new CastInstruction();
|
CastInstruction insn = new CastInstruction();
|
||||||
insn.setTargetType(targetType);
|
insn.setTargetType(targetType);
|
||||||
insn.setValue(var(value));
|
insn.setValue(var(value));
|
||||||
|
|
|
@ -77,7 +77,7 @@ class ResourceProgramTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeCastToResource(CastInstruction cast) {
|
private void removeCastToResource(CastInstruction cast) {
|
||||||
if (hierarchy.isSuperType(RESOURCE, cast.getTargetType(), false)) {
|
if (!cast.isWeak() && hierarchy.isSuperType(RESOURCE, cast.getTargetType(), false)) {
|
||||||
AssignInstruction assign = new AssignInstruction();
|
AssignInstruction assign = new AssignInstruction();
|
||||||
assign.setReceiver(cast.getReceiver());
|
assign.setReceiver(cast.getReceiver());
|
||||||
assign.setAssignee(cast.getValue());
|
assign.setAssignee(cast.getValue());
|
||||||
|
|
Loading…
Reference in New Issue
Block a user