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