Fix bugs in emit API

This commit is contained in:
Alexey Andreev 2015-07-30 18:11:31 +03:00
parent ce525f0a78
commit 0be4ca336d
6 changed files with 52 additions and 27 deletions

View File

@ -26,7 +26,9 @@ import org.teavm.model.ClassHolderSource;
import org.teavm.model.ClassHolderTransformer; import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource; import org.teavm.model.ClassReaderSource;
import org.teavm.model.MethodHolder;
import org.teavm.model.util.ModelUtils; 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"); throw new IllegalArgumentException("Class " + cls.getName() + " is already defined");
} }
generatedClasses.put(cls.getName(), cls); 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()); cache.remove(cls.getName());
} }

View File

@ -38,17 +38,17 @@ public class IfEmitter {
BasicBlock block = pe.prepareBlock(); BasicBlock block = pe.prepareBlock();
fork.setThen(block); fork.setThen(block);
pe.enter(block); pe.enter(block);
fragment.emit(); pe.emitAndJump(fragment, join);
pe.jump(join); pe.enter(join);
return this; return this;
} }
public IfEmitter elseDo(FragmentEmitter fragment) { public IfEmitter elseDo(FragmentEmitter fragment) {
BasicBlock block = pe.prepareBlock(); BasicBlock block = pe.prepareBlock();
fork.setThen(block); fork.setElse(block);
pe.enter(block); pe.enter(block);
fragment.emit(); pe.emitAndJump(fragment, join);
pe.jump(join); pe.enter(join);
return this; return this;
} }
} }

View File

@ -292,7 +292,6 @@ public final class ProgramEmitter {
JumpInstruction insn = new JumpInstruction(); JumpInstruction insn = new JumpInstruction();
insn.setTarget(block); insn.setTarget(block);
addInstruction(insn); addInstruction(insn);
this.block = block;
return this; return this;
} }

View File

@ -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)) { .orElse(true)) {
throw new EmitException("Can't call " + method + " on non-compatible class " + type); 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)); 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)); return new ConditionEmitter(pe, compareTo(other).fork(BranchingCondition.LESS_OR_EQUAL));
} }
@ -640,8 +640,10 @@ public class ValueEmitter {
} }
public ValueEmitter cast(ValueType type) { 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; return this;
} else if (pe.classSource.isSuperType(type, this.type).orElse(false)) {
return pe.var(variable.getIndex(), type);
} }
if (type instanceof ValueType.Primitive) { if (type instanceof ValueType.Primitive) {
@ -720,12 +722,24 @@ public class ValueEmitter {
CastIntegerInstruction insn = new CastIntegerInstruction(subtype, CastIntegerDirection.TO_INTEGER); CastIntegerInstruction insn = new CastIntegerInstruction(subtype, CastIntegerDirection.TO_INTEGER);
insn.setValue(variable); insn.setValue(variable);
ValueEmitter result = pe.newVar(ValueType.INTEGER); ValueEmitter result = pe.newVar(convertSubtype(subtype));
insn.setReceiver(result.getVariable()); insn.setReceiver(result.getVariable());
pe.addInstruction(insn); pe.addInstruction(insn);
return result; 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) { public ValueEmitter castToInteger(IntegerSubtype subtype) {
switch (subtype) { switch (subtype) {
case BYTE: case BYTE:

View File

@ -32,7 +32,11 @@ public abstract class BasicBlockMapper implements InstructionVisitor {
} }
public void transform(BasicBlock block) { 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 (Phi phi : block.getPhis()) {
for (Incoming incoming : phi.getIncomings()) { for (Incoming incoming : phi.getIncomings()) {
incoming.setSource(map(incoming.getSource())); incoming.setSource(map(incoming.getSource()));

View File

@ -18,10 +18,19 @@ package org.teavm.platform.plugin;
import org.teavm.cache.NoCache; import org.teavm.cache.NoCache;
import org.teavm.diagnostics.Diagnostics; import org.teavm.diagnostics.Diagnostics;
import org.teavm.javascript.spi.GeneratedBy; import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.model.*; import org.teavm.model.AccessLevel;
import org.teavm.model.emit.ForkEmitter; 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.emit.ProgramEmitter;
import org.teavm.model.instructions.BinaryBranchingCondition;
import org.teavm.model.util.ModelUtils; import org.teavm.model.util.ModelUtils;
import org.teavm.platform.PlatformClass; import org.teavm.platform.PlatformClass;
import org.teavm.platform.metadata.ClassScopedMetadataProvider; import org.teavm.platform.metadata.ClassScopedMetadataProvider;
@ -91,19 +100,11 @@ class MetadataProviderTransformer implements ClassHolderTransformer {
method.getModifiers().remove(ElementModifier.NATIVE); method.getModifiers().remove(ElementModifier.NATIVE);
ProgramEmitter pe = ProgramEmitter.create(method, classSource); ProgramEmitter pe = ProgramEmitter.create(method, classSource);
ForkEmitter fork = pe.getField(field.getReference(), field.getType()).fork( pe.when(pe.getField(field.getReference(), field.getType()).isNull())
BinaryBranchingCondition.REFERENCE_NOT_EQUAL, pe.constantNull(field.getType())); .thenDo(() -> pe.setField(field.getReference(), pe.invoke(createMethod.getReference().getClassName(),
createMethod.getReference().getName(), createMethod.getResultType())));
BasicBlock resourceFound = pe.prepareBlock(); pe.getField(field.getReference(), field.getType())
fork.setThen(resourceFound); .returnValue();
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);
AnnotationHolder noCacheAnnot = new AnnotationHolder(NoCache.class.getName()); AnnotationHolder noCacheAnnot = new AnnotationHolder(NoCache.class.getName());
method.getAnnotations().add(noCacheAnnot); method.getAnnotations().add(noCacheAnnot);