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());