Merge "Fix register allocation of arguments and triage remaining example tests."
diff --git a/src/main/java/com/android/tools/r8/cf/CfPrinter.java b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
index af51fdc..3fd7d75 100644
--- a/src/main/java/com/android/tools/r8/cf/CfPrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.cf.code.CfFrame;
import com.android.tools.r8.cf.code.CfGoto;
import com.android.tools.r8.cf.code.CfIf;
+import com.android.tools.r8.cf.code.CfIfCmp;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfLabel;
@@ -17,6 +18,7 @@
import com.android.tools.r8.cf.code.CfNew;
import com.android.tools.r8.cf.code.CfPop;
import com.android.tools.r8.cf.code.CfReturn;
+import com.android.tools.r8.cf.code.CfReturnVoid;
import com.android.tools.r8.cf.code.CfStaticGet;
import com.android.tools.r8.cf.code.CfStore;
import com.android.tools.r8.errors.Unreachable;
@@ -24,6 +26,8 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.If.Type;
import com.android.tools.r8.ir.code.ValueType;
import java.util.HashMap;
import java.util.Map;
@@ -101,10 +105,14 @@
}
}
- public void print(CfReturn ret) {
+ public void print(CfReturnVoid ret) {
print("return");
}
+ public void print(CfReturn ret) {
+ print(typePrefix(ret.getType()) + "return");
+ }
+
public void print(CfPop pop) {
print("pop");
}
@@ -198,39 +206,29 @@
builder.append("goto ").append(getLabel(jump.getTarget()));
}
+ private String ifPostfix(If.Type kind) {
+ return kind.toString().toLowerCase();
+ }
+
public void print(CfIf conditional) {
indent();
- switch (conditional.getOpcode()) {
- case Opcodes.IFNULL:
- builder.append("ifnull");
- break;
- case Opcodes.IFNONNULL:
- builder.append("ifnonnull");
- break;
- case Opcodes.IFEQ:
- builder.append("ifeq");
- break;
- case Opcodes.IFNE:
- builder.append("ifne");
- break;
- case Opcodes.IFLT:
- builder.append("iflt");
- break;
- case Opcodes.IFGE:
- builder.append("ifge");
- break;
- case Opcodes.IFGT:
- builder.append("ifgt");
- break;
- case Opcodes.IFLE:
- builder.append("ifle");
- break;
- default:
- throw new Unreachable();
+ if (conditional.getType().isObject()) {
+ builder.append("if").append(conditional.getKind() == Type.EQ ? "null" : "nonnull");
+ } else {
+ builder.append("if").append(ifPostfix(conditional.getKind()));
}
builder.append(' ').append(getLabel(conditional.getTarget()));
}
+ public void print(CfIfCmp conditional) {
+ indent();
+ builder
+ .append(conditional.getType().isObject() ? "if_acmp" : "if_icmp")
+ .append(ifPostfix(conditional.getKind()))
+ .append(' ')
+ .append(getLabel(conditional.getTarget()));
+ }
+
public void print(CfLoad load) {
print(load.getType(), "load", load.getLocalIndex());
}
diff --git a/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java b/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java
index 1c7c6d9..1a60a02 100644
--- a/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java
@@ -128,6 +128,12 @@
private void performLinearScan() {
unhandled.addAll(liveIntervals);
+
+ while (!unhandled.isEmpty() && unhandled.peek().getValue().isArgument()) {
+ LiveIntervals argument = unhandled.poll();
+ assignRegisterToUnhandledInterval(argument, getNextFreeRegister(argument.getType().isWide()));
+ }
+
while (!unhandled.isEmpty()) {
LiveIntervals unhandledInterval = unhandled.poll();
int start = unhandledInterval.getStart();
diff --git a/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java b/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java
index bb76dc7..ae8e6b1 100644
--- a/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java
@@ -86,11 +86,12 @@
public void loadInValues(Instruction instruction, InstructionListIterator it) {
int topOfStack = 0;
it.previous();
- for (Value value : instruction.inValues()) {
+ for (int i = 0; i < instruction.inValues().size(); i++) {
+ Value value = instruction.inValues().get(i);
StackValue stackValue = createStackValue(value, topOfStack++);
add(load(stackValue, value), instruction, it);
value.removeUser(instruction);
- instruction.replaceValue(value, stackValue);
+ instruction.replaceValue(i, stackValue);
}
it.next();
}
diff --git a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
index d22ff65..77ecbdc 100644
--- a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
@@ -67,8 +67,10 @@
? code.method.method.getHolder()
: code.method.method.proto.parameters.values[argumentIndex];
Value outValue = instruction.outValue();
- types.put(outValue, argumentType);
- addUsers(outValue, worklist);
+ if (outValue.outType().isObject()) {
+ types.put(outValue, argumentType);
+ addUsers(outValue, worklist);
+ }
++argumentIndex;
}
// Compute the out-value type of each normal instruction with an out-value but no in values.
@@ -90,6 +92,7 @@
while (!worklist.isEmpty()) {
Value item = worklist.iterator().next();
worklist.remove(item);
+ assert item.outType().isObject();
DexType previousType = types.get(item);
DexType refinedType = computeVerificationType(item);
if (previousType != refinedType) {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index 1d946b2..b4c6755 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
-import it.unimi.dsi.fastutil.ints.Int2ReferenceMap.Entry;
import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -22,24 +21,45 @@
this.locals = locals;
}
+ private boolean isWide(DexType type) {
+ return type.isPrimitiveType() && (type.toShorty() == 'J' || type.toShorty() == 'D');
+ }
+
@Override
public void write(MethodVisitor visitor) {
- int type = F_NEW;
- int localsSize = locals.size();
- Object[] localsCopy = new Object[localsSize];
- int localIndex = 0;
- for (Entry<DexType> entry : locals.int2ReferenceEntrySet()) {
- Object typeOpcode = getType(entry.getValue());
- if (typeOpcode == Opcodes.LONG || typeOpcode == Opcodes.DOUBLE) {
- localsCopy[localIndex++] = Opcodes.TOP;
+ if (locals.isEmpty()) {
+ visitor.visitFrame(F_NEW, 0, null, 0, null);
+ return;
+ }
+ // Compute the size of locals. Absent indexes are denoted by a single-width element (ie, TOP).
+ int maxRegister = locals.lastIntKey();
+ int localsCount = 0;
+ for (int i = 0; i <= maxRegister; i++) {
+ localsCount++;
+ DexType type = locals.get(i);
+ if (type != null && isWide(type)) {
+ i++;
}
+ }
+ // Construct the locals type descriptions.
+ Object[] localsCopy = new Object[localsCount];
+ int localIndex = 0;
+ for (int i = 0; i <= maxRegister; i++) {
+ DexType type = locals.get(i);
+ Object typeOpcode = getType(type);
localsCopy[localIndex++] = typeOpcode;
+ if (type != null && isWide(type)) {
+ i++;
+ }
}
// TODO(zerny): Compute the stack types too.
- visitor.visitFrame(type, localsSize, localsCopy, 0, new Object[0]);
+ visitor.visitFrame(F_NEW, localsCount, localsCopy, 0, null);
}
private Object getType(DexType type) {
+ if (type == null) {
+ return Opcodes.TOP;
+ }
if (type == DexItemFactory.nullValueType) {
return Opcodes.NULL;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIf.java b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
index 5c7a2c7..d928ff7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.If.Type;
import com.android.tools.r8.ir.code.ValueType;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -22,6 +23,14 @@
this.target = target;
}
+ public ValueType getType() {
+ return type;
+ }
+
+ public Type getKind() {
+ return kind;
+ }
+
public CfLabel getTarget() {
return target;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
new file mode 100644
index 0000000..dc8b63f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
@@ -0,0 +1,66 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.cf.code;
+
+import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class CfIfCmp extends CfInstruction {
+
+ private final If.Type kind;
+ private final ValueType type;
+ private final CfLabel target;
+
+ public CfIfCmp(If.Type kind, ValueType type, CfLabel target) {
+ this.kind = kind;
+ this.type = type;
+ this.target = target;
+ }
+
+ public Type getKind() {
+ return kind;
+ }
+
+ public ValueType getType() {
+ return type;
+ }
+
+ public CfLabel getTarget() {
+ return target;
+ }
+
+ public int getOpcode() {
+ switch (kind) {
+ case EQ:
+ return type.isObject() ? Opcodes.IF_ACMPEQ : Opcodes.IF_ICMPEQ;
+ case GE:
+ return Opcodes.IF_ICMPGE;
+ case GT:
+ return Opcodes.IF_ICMPGT;
+ case LE:
+ return Opcodes.IF_ICMPLE;
+ case LT:
+ return Opcodes.IF_ICMPLT;
+ case NE:
+ return type.isObject() ? Opcodes.IF_ACMPNE : Opcodes.IF_ICMPNE;
+ default:
+ throw new Unreachable("Unexpected type " + type);
+ }
+ }
+
+ @Override
+ public void print(CfPrinter printer) {
+ printer.print(this);
+ }
+
+ @Override
+ public void write(MethodVisitor visitor) {
+ visitor.visitJumpInsn(getOpcode(), target.getLabel());
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
index 1a20d29..c426dbd 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
@@ -4,14 +4,43 @@
package com.android.tools.r8.cf.code;
import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.ir.code.ValueType;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class CfReturn extends CfInstruction {
+ private final ValueType type;
+
+ public CfReturn(ValueType type) {
+ this.type = type;
+ }
+
+ public ValueType getType() {
+ return type;
+ }
+
+ private int getOpcode() {
+ switch (type) {
+ case INT:
+ return Opcodes.IRETURN;
+ case FLOAT:
+ return Opcodes.FRETURN;
+ case LONG:
+ return Opcodes.LRETURN;
+ case DOUBLE:
+ return Opcodes.DRETURN;
+ case OBJECT:
+ return Opcodes.ARETURN;
+ default:
+ throw new Unreachable("Unexpected return type: " + type);
+ }
+ }
+
@Override
public void write(MethodVisitor visitor) {
- visitor.visitInsn(Opcodes.RETURN);
+ visitor.visitInsn(getOpcode());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
new file mode 100644
index 0000000..b8bfc7d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
@@ -0,0 +1,21 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.cf.code;
+
+import com.android.tools.r8.cf.CfPrinter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class CfReturnVoid extends CfInstruction {
+
+ @Override
+ public void write(MethodVisitor visitor) {
+ visitor.visitInsn(Opcodes.RETURN);
+ }
+
+ @Override
+ public void print(CfPrinter printer) {
+ printer.print(this);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/code/If.java b/src/main/java/com/android/tools/r8/ir/code/If.java
index c6e62af..37a6766 100644
--- a/src/main/java/com/android/tools/r8/ir/code/If.java
+++ b/src/main/java/com/android/tools/r8/ir/code/If.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.cf.LoadStoreHelper;
import com.android.tools.r8.cf.code.CfIf;
+import com.android.tools.r8.cf.code.CfIfCmp;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -197,7 +198,12 @@
@Override
public void buildCf(CfBuilder builder) {
- assert inValues.size() == 1;
- builder.add(new CfIf(type, inValues.get(0).type, builder.getLabel(getTrueTarget())));
+ if (inValues.size() == 1) {
+ builder.add(new CfIf(type, inValues.get(0).type, builder.getLabel(getTrueTarget())));
+ return;
+ }
+ assert inValues.size() == 2;
+ assert inValues.get(0).type == inValues.get(1).type;
+ builder.add(new CfIfCmp(type, inValues.get(0).type, builder.getLabel(getTrueTarget())));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index ca68f64..dce6226 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -149,6 +149,11 @@
}
}
+ public void replaceValue(int index, Value newValue) {
+ inValues.set(index, newValue);
+ newValue.addUser(this);
+ }
+
public void replaceDebugValue(Value oldValue, Value newValue) {
if (debugValues.remove(oldValue)) {
if (newValue.hasLocalInfo()) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Return.java b/src/main/java/com/android/tools/r8/ir/code/Return.java
index 1177abb..a9c44c6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Return.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Return.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.LoadStoreHelper;
import com.android.tools.r8.cf.code.CfReturn;
+import com.android.tools.r8.cf.code.CfReturnVoid;
import com.android.tools.r8.code.MoveType;
import com.android.tools.r8.code.ReturnObject;
import com.android.tools.r8.code.ReturnVoid;
@@ -125,6 +126,6 @@
@Override
public void buildCf(CfBuilder builder) {
- builder.add(new CfReturn());
+ builder.add(isReturnVoid() ? new CfReturnVoid() : new CfReturn(returnType));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/StackValue.java b/src/main/java/com/android/tools/r8/ir/code/StackValue.java
index 94909db..46aa5db 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StackValue.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StackValue.java
@@ -19,7 +19,7 @@
}
public static StackValue forObjectType(DexType type, int height) {
- assert DexItemFactory.nullValueType == type || type.isClassType();
+ assert DexItemFactory.nullValueType == type || type.isClassType() || type.isArrayType();
return new StackValue(type, ValueType.OBJECT, height);
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index f1c3e32..f923493 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -244,6 +244,7 @@
assert stack.isEmpty();
Collection<Value> locals = registerAllocator.getLocalsAtPosition(block.entry().getNumber());
Int2ReferenceSortedMap<DexType> mapping = new Int2ReferenceAVLTreeMap<>();
+
for (Value local : locals) {
DexType type;
switch (local.outType()) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 8207e4c..b466315 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -611,7 +611,7 @@
}
private void finalizeToCf(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
- assert method.getCode().isJarCode();
+ assert !method.getCode().isDexCode();
CfBuilder builder = new CfBuilder(method, code, options.itemFactory);
// TODO(zerny): Change the return type of CfBuilder::build CfCode once complete.
Code result = builder.build(codeRewriter, options);
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index d2b2f5e..0d2cf2a 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -62,7 +62,7 @@
private void writeClass(DexProgramClass clazz, OutputSink outputSink) throws IOException {
ClassWriter writer = new ClassWriter(0);
- writer.visitSource(clazz.sourceFile.toString(), null);
+ writer.visitSource(clazz.sourceFile != null ? clazz.sourceFile.toString() : null, null);
int version = downgrade(clazz.getClassFileVersion());
int access = clazz.accessFlags.getAsCfAccessFlags();
String desc = clazz.type.toDescriptorString();
@@ -75,10 +75,13 @@
interfaces[i] = clazz.interfaces.values[i].getInternalName();
}
writer.visit(version, access, name, signature, superName, interfaces);
- // TODO(zerny): Methods and fields.
+ // TODO(zerny): Fields.
for (DexEncodedMethod method : clazz.directMethods()) {
writeMethod(method, writer);
}
+ for (DexEncodedMethod method : clazz.virtualMethods()) {
+ writeMethod(method, writer);
+ }
writer.visitEnd();
byte[] result = writer.toByteArray();
@@ -93,7 +96,9 @@
String signature = null; // TODO(zerny): Support generic signatures.
String[] exceptions = null;
MethodVisitor visitor = writer.visitMethod(access, name, desc, signature, exceptions);
- writeCode(method.getCode(), visitor);
+ if (!method.accessFlags.isAbstract()) {
+ writeCode(method.getCode(), visitor);
+ }
}
private void writeCode(Code code, MethodVisitor visitor) {
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
index c79719a..6eb5090 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -62,6 +63,30 @@
.put("memberrebinding2.Test", match(R8_COMPILER)) // b/38187737
.build();
+ private static final Map<String, TestCondition> failingRunCf =
+ new ImmutableMap.Builder<String, TestCondition>()
+ .put("floating_point_annotations.FloatingPointValuedAnnotationTest", match(R8_COMPILER))
+ .put("filledarray.FilledArray", match(R8_COMPILER)) // missing field
+ .put("instancevariable.InstanceVariable", match(R8_COMPILER)) // missing field
+ .put("newarray.NewArray", match(R8_COMPILER)) // missing field
+ .put("regalloc.RegAlloc", match(R8_COMPILER)) // missing field
+ .put("staticfield.StaticField", match(R8_COMPILER)) // missing field
+ .put("sync.Sync", match(R8_COMPILER)) // missing field
+ .put("throwing.Throwing", match(R8_COMPILER)) // missing field
+ .put("regress_64881691.Regress", match(R8_COMPILER)) // missing field
+ .put("memberrebinding2.Memberrebinding", match(R8_COMPILER)) // missing field
+ .put("interfaceinlining.Main", match(R8_COMPILER)) // missing field
+ .put("switchmaps.Switches", match(R8_COMPILER)) // missing field
+ .put("regress_62300145.Regress", match(R8_COMPILER)) // verify <init> failed
+ .put("enclosingmethod.Main", match(R8_COMPILER)) // verify <init> failed
+ .build();
+
+ private static final Set<String> failingCompileCf =
+ new ImmutableSet.Builder<String>()
+ .add("invoke.Invoke") // outline / CF->IR
+ .add("trycatch.TryCatch") // inline / CF->IR
+ .build();
+
private static final Map<String, TestCondition> outputNotIdenticalToJVMOutput =
new ImmutableMap.Builder<String, TestCondition>()
// Traverses stack frames that contain Art specific frames.
@@ -123,16 +148,9 @@
"switchmaps.Switches",
};
- String[] javaBytecodeTests = {
- "constants.Constants",
- "hello.Hello",
- "arithmetic.Arithmetic",
- "barray.BArray",
- };
-
List<String[]> fullTestList = new ArrayList<>(tests.length * 2);
- if (!ONLY_RUN_CF_TESTS) {
- for (String test : tests) {
+ for (String test : tests) {
+ if (!ONLY_RUN_CF_TESTS) {
fullTestList.add(makeTest(Input.JAVAC, CompilerUnderTest.D8, CompilationMode.DEBUG, test));
fullTestList.add(makeTest(Input.JAVAC_ALL, CompilerUnderTest.D8, CompilationMode.DEBUG,
test));
@@ -146,16 +164,10 @@
test));
fullTestList.add(makeTest(Input.DX, CompilerUnderTest.R8, CompilationMode.RELEASE, test));
}
- }
- // TODO(zerny): Once all tests pass create the java tests in the main test loop.
- for (String test : javaBytecodeTests) {
- fullTestList.add(
- makeTest(Input.JAVAC_ALL, CompilerUnderTest.R8, CompilationMode.DEBUG, test, Output.CF));
fullTestList.add(
makeTest(
Input.JAVAC_ALL, CompilerUnderTest.R8, CompilationMode.RELEASE, test, Output.CF));
}
-
return fullTestList;
}
@@ -236,6 +248,9 @@
@Before
public void compile()
throws IOException, ProguardRuleParserException, ExecutionException, CompilationException {
+ if (output == Output.CF && failingCompileCf.contains(mainClass)) {
+ thrown.expect(Throwable.class);
+ }
switch (compiler) {
case D8: {
assertTrue(output == Output.DEX);
@@ -277,6 +292,15 @@
fail("JVM failed for: " + mainClass);
}
+ DexVm vm = ToolHelper.getDexVm();
+ TestCondition condition =
+ output == Output.CF ? failingRunCf.get(mainClass) : failingRun.get(mainClass);
+ if (condition != null && condition.test(getTool(), compiler, vm.getVersion(), mode)) {
+ thrown.expect(Throwable.class);
+ } else {
+ thrown = ExpectedException.none();
+ }
+
if (output == Output.CF) {
ToolHelper.ProcessResult result =
ToolHelper.runJava(ImmutableList.of(generated.toString()), mainClass);
@@ -291,14 +315,6 @@
return;
}
- DexVm vm = ToolHelper.getDexVm();
- TestCondition condition = failingRun.get(mainClass);
- if (condition != null && condition.test(getTool(), compiler, vm.getVersion(), mode)) {
- thrown.expect(Throwable.class);
- } else {
- thrown = ExpectedException.none();
- }
-
// Check output against Art output on original dex file.
String output =
ToolHelper.checkArtOutputIdentical(original, generated.toString(), mainClass, vm);