From a97e6574ac265009301b06ef2e20c5290a7754e3 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sun, 18 Aug 2024 18:47:04 +0200 Subject: [PATCH] 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. --- .../src/main/java/org/teavm/ast/CastExpr.java | 10 +++ .../ast/decompilation/StatementGenerator.java | 1 + .../c/generate/CodeGenerationVisitor.java | 5 ++ .../rendering/StatementRenderer.java | 2 +- .../backend/wasm/gc/PreciseTypeInference.java | 14 +--- .../wasm/gc/WasmGCMethodReturnTypes.java | 64 ------------------- .../gc/WasmGCVariableCategoryProvider.java | 6 +- .../methods/BaseWasmGenerationVisitor.java | 5 ++ .../gc/WasmGCDeclarationsGenerator.java | 4 -- .../gc/methods/WasmGCGenerationContext.java | 10 +-- .../gc/methods/WasmGCGenerationVisitor.java | 2 +- .../gc/methods/WasmGCMethodGenerator.java | 13 ++-- core/src/main/java/org/teavm/cache/AstIO.java | 2 + .../main/java/org/teavm/cache/ProgramIO.java | 4 +- .../AbstractInstructionAnalyzer.java | 12 ++-- .../dependency/ClassClosureAnalyzer.java | 2 +- .../dependency/DataFlowGraphBuilder.java | 2 +- .../dependency/DependencyGraphBuilder.java | 8 ++- .../teavm/model/InstructionReadVisitor.java | 2 +- .../java/org/teavm/model/Interpreter.java | 2 +- .../AbstractInstructionReader.java | 2 +- .../model/instructions/CastInstruction.java | 9 +++ .../model/instructions/InstructionReader.java | 2 +- .../model/lowlevel/ExceptionHandlingUtil.java | 5 +- .../model/lowlevel/NativePointerFinder.java | 2 +- .../model/optimization/Devirtualization.java | 7 +- .../optimization/GlobalValueNumbering.java | 3 +- .../model/text/InstructionStringifier.java | 8 ++- .../model/util/InstructionCopyReader.java | 3 +- .../org/teavm/model/util/TypeInferer.java | 2 +- .../org/teavm/jso/impl/JSClassProcessor.java | 3 + .../impl/CompositeMethodGenerator.java | 2 +- .../plugin/ResourceProgramTransformer.java | 2 +- 33 files changed, 84 insertions(+), 136 deletions(-) delete mode 100644 core/src/main/java/org/teavm/backend/wasm/gc/WasmGCMethodReturnTypes.java diff --git a/core/src/main/java/org/teavm/ast/CastExpr.java b/core/src/main/java/org/teavm/ast/CastExpr.java index 8a52bc0ce..b20ad0d08 100644 --- a/core/src/main/java/org/teavm/ast/CastExpr.java +++ b/core/src/main/java/org/teavm/ast/CastExpr.java @@ -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; } } diff --git a/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java b/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java index be885aec4..da209c4b2 100644 --- a/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java +++ b/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java @@ -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()); } diff --git a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java index d8d34e7e8..b53728ba9 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java @@ -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)) { diff --git a/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java b/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java index 2862f3ddf..feeee4ddf 100644 --- a/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java +++ b/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java @@ -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()); } diff --git a/core/src/main/java/org/teavm/backend/wasm/gc/PreciseTypeInference.java b/core/src/main/java/org/teavm/backend/wasm/gc/PreciseTypeInference.java index bc1f64780..2474e38da 100644 --- a/core/src/main/java/org/teavm/backend/wasm/gc/PreciseTypeInference.java +++ b/core/src/main/java/org/teavm/backend/wasm/gc/PreciseTypeInference.java @@ -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 { 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 { 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); diff --git a/core/src/main/java/org/teavm/backend/wasm/gc/WasmGCMethodReturnTypes.java b/core/src/main/java/org/teavm/backend/wasm/gc/WasmGCMethodReturnTypes.java deleted file mode 100644 index 4b9ce6fc3..000000000 --- a/core/src/main/java/org/teavm/backend/wasm/gc/WasmGCMethodReturnTypes.java +++ /dev/null @@ -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 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()); - } -} diff --git a/core/src/main/java/org/teavm/backend/wasm/gc/WasmGCVariableCategoryProvider.java b/core/src/main/java/org/teavm/backend/wasm/gc/WasmGCVariableCategoryProvider.java index 08060e4e6..b77560eae 100644 --- a/core/src/main/java/org/teavm/backend/wasm/gc/WasmGCVariableCategoryProvider.java +++ b/core/src/main/java/org/teavm/backend/wasm/gc/WasmGCVariableCategoryProvider.java @@ -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()]; diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java b/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java index 4d1cbe762..14cac5530 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java @@ -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); diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/WasmGCDeclarationsGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/WasmGCDeclarationsGenerator.java index 4d8d6463c..b93f05dbf 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/WasmGCDeclarationsGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/WasmGCDeclarationsGenerator.java @@ -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 ); diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationContext.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationContext.java index 871374562..fcb901f0a 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationContext.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationContext.java @@ -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 getInterfaceImplementors(String className) { if (interfaceImplementors == null) { fillInterfaceImplementors(); diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java index 5fad8f228..9237d5a92 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java @@ -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) { diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java index 78e53a167..7c7051912 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java @@ -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; diff --git a/core/src/main/java/org/teavm/cache/AstIO.java b/core/src/main/java/org/teavm/cache/AstIO.java index 8139a047e..fb01c74e1 100644 --- a/core/src/main/java/org/teavm/cache/AstIO.java +++ b/core/src/main/java/org/teavm/cache/AstIO.java @@ -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: { diff --git a/core/src/main/java/org/teavm/cache/ProgramIO.java b/core/src/main/java/org/teavm/cache/ProgramIO.java index 42d5d1655..efdf974e2 100644 --- a/core/src/main/java/org/teavm/cache/ProgramIO.java +++ b/core/src/main/java/org/teavm/cache/ProgramIO.java @@ -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: { diff --git a/core/src/main/java/org/teavm/dependency/AbstractInstructionAnalyzer.java b/core/src/main/java/org/teavm/dependency/AbstractInstructionAnalyzer.java index 88e2f55d8..0d1656247 100644 --- a/core/src/main/java/org/teavm/dependency/AbstractInstructionAnalyzer.java +++ b/core/src/main/java/org/teavm/dependency/AbstractInstructionAnalyzer.java @@ -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 diff --git a/core/src/main/java/org/teavm/dependency/ClassClosureAnalyzer.java b/core/src/main/java/org/teavm/dependency/ClassClosureAnalyzer.java index e5cdb1967..d7e68b11b 100644 --- a/core/src/main/java/org/teavm/dependency/ClassClosureAnalyzer.java +++ b/core/src/main/java/org/teavm/dependency/ClassClosureAnalyzer.java @@ -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); } diff --git a/core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java b/core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java index 66acf24db..421c714f3 100644 --- a/core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java +++ b/core/src/main/java/org/teavm/dependency/DataFlowGraphBuilder.java @@ -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()); } diff --git a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java index 15c8c0579..0be2cdc14 100644 --- a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java +++ b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java @@ -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(); diff --git a/core/src/main/java/org/teavm/model/InstructionReadVisitor.java b/core/src/main/java/org/teavm/model/InstructionReadVisitor.java index b7a1da1a7..c6e0649d2 100644 --- a/core/src/main/java/org/teavm/model/InstructionReadVisitor.java +++ b/core/src/main/java/org/teavm/model/InstructionReadVisitor.java @@ -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 diff --git a/core/src/main/java/org/teavm/model/Interpreter.java b/core/src/main/java/org/teavm/model/Interpreter.java index dbe087d8e..b72aa0162 100644 --- a/core/src/main/java/org/teavm/model/Interpreter.java +++ b/core/src/main/java/org/teavm/model/Interpreter.java @@ -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()]); } diff --git a/core/src/main/java/org/teavm/model/instructions/AbstractInstructionReader.java b/core/src/main/java/org/teavm/model/instructions/AbstractInstructionReader.java index 942c739ee..2919d4056 100644 --- a/core/src/main/java/org/teavm/model/instructions/AbstractInstructionReader.java +++ b/core/src/main/java/org/teavm/model/instructions/AbstractInstructionReader.java @@ -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 diff --git a/core/src/main/java/org/teavm/model/instructions/CastInstruction.java b/core/src/main/java/org/teavm/model/instructions/CastInstruction.java index 9e91d93af..a06b2f7e0 100644 --- a/core/src/main/java/org/teavm/model/instructions/CastInstruction.java +++ b/core/src/main/java/org/teavm/model/instructions/CastInstruction.java @@ -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); diff --git a/core/src/main/java/org/teavm/model/instructions/InstructionReader.java b/core/src/main/java/org/teavm/model/instructions/InstructionReader.java index 8991ef290..405126ab3 100644 --- a/core/src/main/java/org/teavm/model/instructions/InstructionReader.java +++ b/core/src/main/java/org/teavm/model/instructions/InstructionReader.java @@ -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); diff --git a/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingUtil.java b/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingUtil.java index ec75dc9b9..73708bd99 100644 --- a/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingUtil.java +++ b/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingUtil.java @@ -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()); } diff --git a/core/src/main/java/org/teavm/model/lowlevel/NativePointerFinder.java b/core/src/main/java/org/teavm/model/lowlevel/NativePointerFinder.java index 176e57968..c0ad41251 100644 --- a/core/src/main/java/org/teavm/model/lowlevel/NativePointerFinder.java +++ b/core/src/main/java/org/teavm/model/lowlevel/NativePointerFinder.java @@ -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()); } diff --git a/core/src/main/java/org/teavm/model/optimization/Devirtualization.java b/core/src/main/java/org/teavm/model/optimization/Devirtualization.java index 62f6e2616..f6672a1c2 100644 --- a/core/src/main/java/org/teavm/model/optimization/Devirtualization.java +++ b/core/src/main/java/org/teavm/model/optimization/Devirtualization.java @@ -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++; } } diff --git a/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java b/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java index f9899f9b1..86cf03e2a 100644 --- a/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java +++ b/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java @@ -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 diff --git a/core/src/main/java/org/teavm/model/text/InstructionStringifier.java b/core/src/main/java/org/teavm/model/text/InstructionStringifier.java index 0dc8b3fd5..f908689dc 100644 --- a/core/src/main/java/org/teavm/model/text/InstructionStringifier.java +++ b/core/src/main/java/org/teavm/model/text/InstructionStringifier.java @@ -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()); } diff --git a/core/src/main/java/org/teavm/model/util/InstructionCopyReader.java b/core/src/main/java/org/teavm/model/util/InstructionCopyReader.java index 0474c3023..881f6c1df 100644 --- a/core/src/main/java/org/teavm/model/util/InstructionCopyReader.java +++ b/core/src/main/java/org/teavm/model/util/InstructionCopyReader.java @@ -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); } diff --git a/core/src/main/java/org/teavm/model/util/TypeInferer.java b/core/src/main/java/org/teavm/model/util/TypeInferer.java index a9c59d8b7..434a30e01 100644 --- a/core/src/main/java/org/teavm/model/util/TypeInferer.java +++ b/core/src/main/java/org/teavm/model/util/TypeInferer.java @@ -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); } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java index 472e104f9..f072060dc 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java @@ -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; diff --git a/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/CompositeMethodGenerator.java b/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/CompositeMethodGenerator.java index ae9c10c4d..973774afc 100644 --- a/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/CompositeMethodGenerator.java +++ b/metaprogramming/impl/src/main/java/org/teavm/metaprogramming/impl/CompositeMethodGenerator.java @@ -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)); diff --git a/platform/src/main/java/org/teavm/platform/plugin/ResourceProgramTransformer.java b/platform/src/main/java/org/teavm/platform/plugin/ResourceProgramTransformer.java index 9b3f23f0f..be7101645 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/ResourceProgramTransformer.java +++ b/platform/src/main/java/org/teavm/platform/plugin/ResourceProgramTransformer.java @@ -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());