diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java index 0f85399c5..57940d83c 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java @@ -26,7 +26,9 @@ import org.teavm.model.ClassHolderSource; import org.teavm.model.ClassHolderTransformer; import org.teavm.model.ClassReader; import org.teavm.model.ClassReaderSource; +import org.teavm.model.MethodHolder; import org.teavm.model.util.ModelUtils; +import org.teavm.optimization.UnreachableBasicBlockEliminator; /** * @@ -54,6 +56,11 @@ class DependencyClassSource implements ClassHolderSource { throw new IllegalArgumentException("Class " + cls.getName() + " is already defined"); } generatedClasses.put(cls.getName(), cls); + for (MethodHolder method : cls.getMethods()) { + if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) { + new UnreachableBasicBlockEliminator().optimize(method.getProgram()); + } + } cache.remove(cls.getName()); } diff --git a/teavm-core/src/main/java/org/teavm/model/emit/IfEmitter.java b/teavm-core/src/main/java/org/teavm/model/emit/IfEmitter.java index ef49956ce..24ae0dd4b 100644 --- a/teavm-core/src/main/java/org/teavm/model/emit/IfEmitter.java +++ b/teavm-core/src/main/java/org/teavm/model/emit/IfEmitter.java @@ -38,17 +38,17 @@ public class IfEmitter { BasicBlock block = pe.prepareBlock(); fork.setThen(block); pe.enter(block); - fragment.emit(); - pe.jump(join); + pe.emitAndJump(fragment, join); + pe.enter(join); return this; } public IfEmitter elseDo(FragmentEmitter fragment) { BasicBlock block = pe.prepareBlock(); - fork.setThen(block); + fork.setElse(block); pe.enter(block); - fragment.emit(); - pe.jump(join); + pe.emitAndJump(fragment, join); + pe.enter(join); return this; } } diff --git a/teavm-core/src/main/java/org/teavm/model/emit/ProgramEmitter.java b/teavm-core/src/main/java/org/teavm/model/emit/ProgramEmitter.java index 45fd12b66..25c204116 100644 --- a/teavm-core/src/main/java/org/teavm/model/emit/ProgramEmitter.java +++ b/teavm-core/src/main/java/org/teavm/model/emit/ProgramEmitter.java @@ -292,7 +292,6 @@ public final class ProgramEmitter { JumpInstruction insn = new JumpInstruction(); insn.setTarget(block); addInstruction(insn); - this.block = block; return this; } diff --git a/teavm-core/src/main/java/org/teavm/model/emit/ValueEmitter.java b/teavm-core/src/main/java/org/teavm/model/emit/ValueEmitter.java index 4f0ed7283..65b9b1457 100644 --- a/teavm-core/src/main/java/org/teavm/model/emit/ValueEmitter.java +++ b/teavm-core/src/main/java/org/teavm/model/emit/ValueEmitter.java @@ -415,7 +415,7 @@ public class ValueEmitter { } } - if (!pe.classSource.isSuperType(((ValueType.Object) type).getClassName(), method.getClassName()) + if (!pe.classSource.isSuperType(method.getClassName(), ((ValueType.Object) type).getClassName()) .orElse(true)) { throw new EmitException("Can't call " + method + " on non-compatible class " + type); } @@ -615,7 +615,7 @@ public class ValueEmitter { return new ConditionEmitter(pe, compareTo(other).fork(BranchingCondition.LESS)); } - public ConditionEmitter isLessOrEuqalTo(ValueEmitter other) { + public ConditionEmitter isLessOrEqualTo(ValueEmitter other) { return new ConditionEmitter(pe, compareTo(other).fork(BranchingCondition.LESS_OR_EQUAL)); } @@ -640,8 +640,10 @@ public class ValueEmitter { } public ValueEmitter cast(ValueType type) { - if (type.equals(this.type) || pe.classSource.isSuperType(type, this.type).orElse(false)) { + if (type.equals(this.type)) { return this; + } else if (pe.classSource.isSuperType(type, this.type).orElse(false)) { + return pe.var(variable.getIndex(), type); } if (type instanceof ValueType.Primitive) { @@ -720,12 +722,24 @@ public class ValueEmitter { CastIntegerInstruction insn = new CastIntegerInstruction(subtype, CastIntegerDirection.TO_INTEGER); insn.setValue(variable); - ValueEmitter result = pe.newVar(ValueType.INTEGER); + ValueEmitter result = pe.newVar(convertSubtype(subtype)); insn.setReceiver(result.getVariable()); pe.addInstruction(insn); return result; } + private ValueType convertSubtype(IntegerSubtype subtype) { + switch (subtype) { + case BYTE: + return ValueType.BYTE; + case SHORT: + return ValueType.SHORT; + case CHARACTER: + return ValueType.CHARACTER; + } + throw new IllegalArgumentException("Unknown subtype: " + subtype); + } + public ValueEmitter castToInteger(IntegerSubtype subtype) { switch (subtype) { case BYTE: diff --git a/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java b/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java index 60842f50c..7f21c4a83 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java +++ b/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java @@ -32,7 +32,11 @@ public abstract class BasicBlockMapper implements InstructionVisitor { } public void transform(BasicBlock block) { - block.getLastInstruction().acceptVisitor(this); + Instruction lastInsn = block.getLastInstruction(); + if (lastInsn == null) { + return; + } + lastInsn.acceptVisitor(this); for (Phi phi : block.getPhis()) { for (Incoming incoming : phi.getIncomings()) { incoming.setSource(map(incoming.getSource())); diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java index e6fe9dab5..59887e95f 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java @@ -18,10 +18,19 @@ package org.teavm.platform.plugin; import org.teavm.cache.NoCache; import org.teavm.diagnostics.Diagnostics; import org.teavm.javascript.spi.GeneratedBy; -import org.teavm.model.*; -import org.teavm.model.emit.ForkEmitter; +import org.teavm.model.AccessLevel; +import org.teavm.model.AnnotationHolder; +import org.teavm.model.AnnotationReader; +import org.teavm.model.AnnotationValue; +import org.teavm.model.CallLocation; +import org.teavm.model.ClassHolder; +import org.teavm.model.ClassHolderTransformer; +import org.teavm.model.ClassReaderSource; +import org.teavm.model.ElementModifier; +import org.teavm.model.FieldHolder; +import org.teavm.model.MethodHolder; +import org.teavm.model.ValueType; import org.teavm.model.emit.ProgramEmitter; -import org.teavm.model.instructions.BinaryBranchingCondition; import org.teavm.model.util.ModelUtils; import org.teavm.platform.PlatformClass; import org.teavm.platform.metadata.ClassScopedMetadataProvider; @@ -91,19 +100,11 @@ class MetadataProviderTransformer implements ClassHolderTransformer { method.getModifiers().remove(ElementModifier.NATIVE); ProgramEmitter pe = ProgramEmitter.create(method, classSource); - ForkEmitter fork = pe.getField(field.getReference(), field.getType()).fork( - BinaryBranchingCondition.REFERENCE_NOT_EQUAL, pe.constantNull(field.getType())); - - BasicBlock resourceFound = pe.prepareBlock(); - fork.setThen(resourceFound); - pe.getField(field.getReference(), field.getType()).returnValue(); - - BasicBlock block = pe.prepareBlock(); - fork.setElse(block); - pe.enter(block); - pe.setField(field.getReference(), pe.invoke(createMethod.getReference().getClassName(), - createMethod.getReference().getName(), createMethod.getResultType())); - pe.jump(resourceFound); + pe.when(pe.getField(field.getReference(), field.getType()).isNull()) + .thenDo(() -> pe.setField(field.getReference(), pe.invoke(createMethod.getReference().getClassName(), + createMethod.getReference().getName(), createMethod.getResultType()))); + pe.getField(field.getReference(), field.getType()) + .returnValue(); AnnotationHolder noCacheAnnot = new AnnotationHolder(NoCache.class.getName()); method.getAnnotations().add(noCacheAnnot);