Merge "Create gradle target for bootstrap test and use it"
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index ec863ee..46f4876 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -476,21 +476,19 @@
ProguardMapSupplier proguardMapSupplier;
- if (options.lineNumberOptimization != LineNumberOptimization.OFF) {
- timing.begin("Line number remapping");
- ClassNameMapper classNameMapper =
- LineNumberOptimizer.run(
- application,
- appView.graphLense(),
- namingLens,
- options.lineNumberOptimization == LineNumberOptimization.IDENTITY_MAPPING);
- timing.end();
- proguardMapSupplier =
- ProguardMapSupplier.fromClassNameMapper(classNameMapper, options.minApiLevel);
- } else {
- proguardMapSupplier =
- ProguardMapSupplier.fromNamingLens(namingLens, application, options.minApiLevel);
- }
+ timing.begin("Line number remapping");
+ // When line number optimization is turned off the identity mapping for line numbers is
+ // used. We still run the line number optimizer to collect line numbers and inline frame
+ // information for the mapping file.
+ ClassNameMapper classNameMapper =
+ LineNumberOptimizer.run(
+ application,
+ appView.graphLense(),
+ namingLens,
+ options.lineNumberOptimization == LineNumberOptimization.OFF);
+ timing.end();
+ proguardMapSupplier =
+ ProguardMapSupplier.fromClassNameMapper(classNameMapper, options.minApiLevel);
// If a method filter is present don't produce output since the application is likely partial.
if (options.hasMethodsFilter()) {
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 d640a30..83f2e8e 100644
--- a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
@@ -52,23 +52,23 @@
return types.iterator().next();
}
Iterator<DexType> iterator = types.iterator();
- TypeLatticeElement join = getLatticeElement(iterator.next());
+ TypeLatticeElement result = getLatticeElement(iterator.next());
while (iterator.hasNext()) {
- join = TypeLatticeElement.join(appInfo, join, getLatticeElement(iterator.next()));
+ result = result.join(getLatticeElement(iterator.next()), appInfo);
}
// All types are reference types so the join is either a class or an array.
- if (join.isClassType()) {
- return join.asClassTypeLatticeElement().getClassType();
- } else if (join.isArrayType()) {
- return join.asArrayTypeLatticeElement().getArrayType();
+ if (result.isClassType()) {
+ return result.asClassTypeLatticeElement().getClassType();
+ } else if (result.isArrayType()) {
+ return result.asArrayTypeLatticeElement().getArrayType();
}
- throw new CompilationError("Unexpected join " + join + " of types: " +
+ throw new CompilationError("Unexpected join " + result + " of types: " +
String.join(", ",
types.stream().map(DexType::toSourceString).collect(Collectors.toList())));
}
private TypeLatticeElement getLatticeElement(DexType type) {
- return TypeLatticeElement.fromDexType(type, appInfo, true);
+ return TypeLatticeElement.fromDexType(type, true, appInfo);
}
public Map<Value, DexType> computeVerificationTypes() {
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
index 1264a26..779678d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
@@ -47,7 +47,7 @@
writer.putUleb128(delta);
}
- AdvancePC(int delta) {
+ public AdvancePC(int delta) {
this.delta = delta;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
index fa856cb..6c6fda4 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
@@ -206,7 +206,10 @@
if (localsChanged()) {
assert emittedPc != pc;
int pcDelta = emittedPc == NO_PC_INFO ? pc : pc - emittedPc;
- events.add(factory.createAdvancePC(pcDelta));
+ assert pcDelta > 0 || emittedPc == NO_PC_INFO;
+ if (pcDelta > 0) {
+ events.add(factory.createAdvancePC(pcDelta));
+ }
emittedPc = pc;
emitLocalChangeEvents(emittedLocals, pendingLocals, lastKnownLocals, events, factory);
pendingLocalChanges = false;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java
index 6b368b3..128e640 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ArrayTypeLatticeElement.java
@@ -52,7 +52,7 @@
@Override
public TypeLatticeElement arrayGet(AppInfo appInfo) {
- return fromDexType(getArrayElementType(appInfo.dexItemFactory), appInfo, true);
+ return fromDexType(getArrayElementType(appInfo.dexItemFactory), true, appInfo);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
index b8988c1..9711079 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
@@ -84,12 +84,12 @@
TypeLatticeElement derived;
if (argumentsSeen < 0) {
// Receiver
- derived = fromDexType(encodedMethod.method.holder, appInfo,
+ derived = fromDexType(encodedMethod.method.holder,
// Now we try inlining even when the receiver could be null.
- encodedMethod != context);
+ encodedMethod != context, appInfo);
} else {
DexType argType = encodedMethod.method.proto.parameters.values[argumentsSeen];
- derived = fromDexType(argType, appInfo, true);
+ derived = fromDexType(argType, true, appInfo);
}
argumentsSeen++;
updateTypeOfValue(outValue, derived);
@@ -149,8 +149,7 @@
private TypeLatticeElement computePhiType(Phi phi) {
// Type of phi(v1, v2, ..., vn) is the least upper bound of all those n operands.
- return TypeLatticeElement.join(
- appInfo, phi.getOperands().stream().map(Value::getTypeLattice));
+ return TypeLatticeElement.join(phi.getOperands().stream().map(Value::getTypeLattice), appInfo);
}
public static DexType getRefinedReceiverType(
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java
index a09039c..b63dbb2 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeLatticeElement.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.Value;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Streams;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.IdentityHashMap;
@@ -81,57 +82,55 @@
/**
* Computes the least upper bound of the current and the other elements.
*
+ * @param other {@link TypeLatticeElement} to join.
* @param appInfo {@link AppInfo}.
- * @param l1 {@link TypeLatticeElement} to join.
- * @param l2 {@link TypeLatticeElement} to join.
- * @return {@link TypeLatticeElement}, a least upper bound of {@param l1} and {@param l2}.
+ * @return {@link TypeLatticeElement}, a least upper bound of {@param this} and {@param other}.
*/
- public static TypeLatticeElement join(
- AppInfo appInfo, TypeLatticeElement l1, TypeLatticeElement l2) {
- if (l1.isBottom()) {
- return l2;
+ public TypeLatticeElement join(TypeLatticeElement other, AppInfo appInfo) {
+ if (isBottom()) {
+ return other;
}
- if (l2.isBottom()) {
- return l1;
+ if (other.isBottom()) {
+ return this;
}
- if (l1.isTop() || l2.isTop()) {
+ if (isTop() || other.isTop()) {
return TOP;
}
- if (l1.isNull()) {
- return l2.asNullable();
+ if (isNull()) {
+ return other.asNullable();
}
- if (l2.isNull()) {
- return l1.asNullable();
+ if (other.isNull()) {
+ return asNullable();
}
- if (l1.isPrimitive()) {
- return l2.isPrimitive()
+ if (isPrimitive()) {
+ return other.isPrimitive()
? PrimitiveTypeLatticeElement.join(
- l1.asPrimitiveTypeLatticeElement(), l2.asPrimitiveTypeLatticeElement())
+ asPrimitiveTypeLatticeElement(), other.asPrimitiveTypeLatticeElement())
: TOP;
}
- if (l2.isPrimitive()) {
- // By the above case, !(l1.isPrimitive())
+ if (other.isPrimitive()) {
+ // By the above case, !(isPrimitive())
return TOP;
}
- // From now on, l1 and l2 are reference types, but might be imprecise yet.
- assert l1.isReference() && l2.isReference();
- if (!l1.isPreciseType() || !l2.isPreciseType()) {
- if (l1.isReferenceInstance()) {
- return l1;
+ // From now on, this and other are reference types, but might be imprecise yet.
+ assert isReference() && other.isReference();
+ if (!isPreciseType() || !other.isPreciseType()) {
+ if (isReferenceInstance()) {
+ return this;
}
- assert l2.isReferenceInstance();
- return l2;
+ assert other.isReferenceInstance();
+ return other;
}
- // From now on, l1 and l2 are precise reference types, i.e., either ArrayType or ClassType.
- boolean isNullable = l1.isNullable() || l2.isNullable();
- if (l1.getClass() != l2.getClass()) {
+ // From now on, this and other are precise reference types, i.e., either ArrayType or ClassType.
+ boolean isNullable = isNullable() || other.isNullable();
+ if (getClass() != other.getClass()) {
return objectClassType(appInfo, isNullable);
}
- // From now on, l1.getClass() == l2.getClass()
- if (l1.isArrayType()) {
- assert l2.isArrayType();
- ArrayTypeLatticeElement a1 = l1.asArrayTypeLatticeElement();
- ArrayTypeLatticeElement a2 = l2.asArrayTypeLatticeElement();
+ // From now on, getClass() == other.getClass()
+ if (isArrayType()) {
+ assert other.isArrayType();
+ ArrayTypeLatticeElement a1 = asArrayTypeLatticeElement();
+ ArrayTypeLatticeElement a2 = other.asArrayTypeLatticeElement();
// Identical types are the same elements
if (a1.getArrayType() == a2.getArrayType()) {
return a1.isNullable() ? a1 : a2;
@@ -166,10 +165,10 @@
DexType arrayTypeLub = appInfo.dexItemFactory.createArrayType(a1Nesting, lub);
return new ArrayTypeLatticeElement(arrayTypeLub, isNullable);
}
- if (l1.isClassType()) {
- assert l2.isClassType();
- ClassTypeLatticeElement c1 = l1.asClassTypeLatticeElement();
- ClassTypeLatticeElement c2 = l2.asClassTypeLatticeElement();
+ if (isClassType()) {
+ assert other.isClassType();
+ ClassTypeLatticeElement c1 = asClassTypeLatticeElement();
+ ClassTypeLatticeElement c2 = other.asClassTypeLatticeElement();
DexType lubType =
c1.getClassType().computeLeastUpperBoundOfClasses(appInfo, c2.getClassType());
return new ClassTypeLatticeElement(lubType, isNullable,
@@ -258,47 +257,43 @@
}
public static BinaryOperator<TypeLatticeElement> joiner(AppInfo appInfo) {
- return (l1, l2) -> join(appInfo, l1, l2);
+ return (l1, l2) -> l1.join(l2, appInfo);
}
- public static TypeLatticeElement join(AppInfo appInfo, Stream<TypeLatticeElement> types) {
+ public static TypeLatticeElement join(Stream<TypeLatticeElement> types, AppInfo appInfo) {
BinaryOperator<TypeLatticeElement> joiner = joiner(appInfo);
return types.reduce(BottomTypeLatticeElement.getInstance(), joiner, joiner);
}
- public static TypeLatticeElement join(
- AppInfo appInfo, Stream<DexType> types, boolean isNullable) {
- return join(appInfo, types.map(t -> fromDexType(t, appInfo, isNullable)));
+ public static TypeLatticeElement joinTypes(
+ Iterable<DexType> types, boolean isNullable, AppInfo appInfo) {
+ return join(Streams.stream(types).map(t -> fromDexType(t, isNullable, appInfo)), appInfo);
}
/**
* Determines the strict partial order of the given {@link TypeLatticeElement}s.
*
+ * @param other expected to be *strictly* bigger than {@param this}
* @param appInfo {@link AppInfo} to compute the least upper bound of {@link TypeLatticeElement}
- * @param l1 subject {@link TypeLatticeElement}
- * @param l2 expected to be *strict* bigger than {@param l1}
- * @return {@code true} if {@param l1} is strictly less than {@param l2}.
+ * @return {@code true} if {@param this} is strictly less than {@param other}.
*/
- public static boolean strictlyLessThan(
- AppInfo appInfo, TypeLatticeElement l1, TypeLatticeElement l2) {
- if (l1.equals(l2)) {
+ public boolean strictlyLessThan(TypeLatticeElement other, AppInfo appInfo) {
+ if (equals(other)) {
return false;
}
- TypeLatticeElement lub = join(appInfo, Stream.of(l1, l2));
- return !l1.equals(lub) && l2.equals(lub);
+ TypeLatticeElement lub = join(other, appInfo);
+ return !equals(lub) && other.equals(lub);
}
/**
* Determines the partial order of the given {@link TypeLatticeElement}s.
*
+ * @param other expected to be bigger than or equal to {@param this}
* @param appInfo {@link AppInfo} to compute the least upper bound of {@link TypeLatticeElement}
- * @param l1 subject {@link TypeLatticeElement}
- * @param l2 expected to be bigger than or equal to {@param l1}
- * @return {@code true} if {@param l1} is less than or equal to {@param l2}.
+ * @return {@code true} if {@param this} is less than or equal to {@param other}.
*/
- public static boolean lessThanOrEqual(
- AppInfo appInfo, TypeLatticeElement l1, TypeLatticeElement l2) {
- return l1.equals(l2) || strictlyLessThan(appInfo, l1, l2);
+ public boolean lessThanOrEqual(TypeLatticeElement other, AppInfo appInfo) {
+ return equals(other) || strictlyLessThan(other, appInfo);
}
/**
@@ -404,14 +399,14 @@
}
public static TypeLatticeElement classClassType(AppInfo appInfo) {
- return fromDexType(appInfo.dexItemFactory.classType, appInfo, false);
+ return fromDexType(appInfo.dexItemFactory.classType, false, appInfo);
}
public static TypeLatticeElement stringClassType(AppInfo appInfo) {
- return fromDexType(appInfo.dexItemFactory.stringType, appInfo, false);
+ return fromDexType(appInfo.dexItemFactory.stringType, false, appInfo);
}
- public static TypeLatticeElement fromDexType(DexType type, AppInfo appInfo, boolean isNullable) {
+ public static TypeLatticeElement fromDexType(DexType type, boolean isNullable, AppInfo appInfo) {
if (type == DexItemFactory.nullValueType) {
return NULL;
}
@@ -483,8 +478,8 @@
}
public TypeLatticeElement checkCast(AppInfo appInfo, DexType castType) {
- TypeLatticeElement castTypeLattice = fromDexType(castType, appInfo, isNullable());
- if (lessThanOrEqual(appInfo, this, castTypeLattice)) {
+ TypeLatticeElement castTypeLattice = fromDexType(castType, isNullable(), appInfo);
+ if (lessThanOrEqual(castTypeLattice, appInfo)) {
return this;
}
return castTypeLattice;
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
index 7caaff9..705bb97 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
@@ -366,7 +366,7 @@
if (downcast != null) {
Value receiver = invoke.inValues().get(0);
TypeLatticeElement castTypeLattice = TypeLatticeElement.fromDexType(
- downcast, appInfo, receiver.getTypeLattice().isNullable());
+ downcast, receiver.getTypeLattice().isNullable(), appInfo);
CheckCast castInstruction =
new CheckCast(code.createValue(castTypeLattice), receiver, downcast);
castInstruction.setPosition(invoke.getPosition());
diff --git a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
index 8d461bd..03d718f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
+++ b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
@@ -133,12 +133,12 @@
TypeLatticeElement outType = outValue().getTypeLattice();
TypeLatticeElement castType =
- TypeLatticeElement.fromDexType(getType(), appInfo, inType.isNullable());
+ TypeLatticeElement.fromDexType(getType(), inType.isNullable(), appInfo);
- if (TypeLatticeElement.lessThanOrEqual(appInfo, inType, castType)) {
+ if (inType.lessThanOrEqual(castType, appInfo)) {
// Cast can be removed. Check that it is sound to replace all users of the out-value by the
// in-value.
- assert TypeLatticeElement.lessThanOrEqual(appInfo, inType, outType);
+ assert inType.lessThanOrEqual(outType, appInfo);
// TODO(b/72693244): Consider checking equivalence. This requires that the types are always
// as precise as possible, though, meaning that almost all changes to the IR must be followed
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
index 401656c..7aa9a62 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
@@ -105,7 +105,7 @@
@Override
public TypeLatticeElement evaluate(AppInfo appInfo) {
- return TypeLatticeElement.fromDexType(appInfo.dexItemFactory.classType, appInfo, false);
+ return TypeLatticeElement.fromDexType(appInfo.dexItemFactory.classType, false, appInfo);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java b/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
index ffc4359..95aa81c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
@@ -91,7 +91,7 @@
@Override
public TypeLatticeElement evaluate(AppInfo appInfo) {
- return TypeLatticeElement.fromDexType(appInfo.dexItemFactory.methodHandleType, appInfo, false);
+ return TypeLatticeElement.fromDexType(appInfo.dexItemFactory.methodHandleType, false, appInfo);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
index 81d7b28..d258839 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
@@ -91,7 +91,7 @@
@Override
public TypeLatticeElement evaluate(AppInfo appInfo) {
- return TypeLatticeElement.fromDexType(appInfo.dexItemFactory.methodTypeType, appInfo, false);
+ return TypeLatticeElement.fromDexType(appInfo.dexItemFactory.methodTypeType, false, appInfo);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstString.java b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
index 85fd784..e05a55f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
@@ -133,6 +133,6 @@
@Override
public TypeLatticeElement evaluate(AppInfo appInfo) {
- return TypeLatticeElement.fromDexType(appInfo.dexItemFactory.stringType, appInfo, false);
+ return TypeLatticeElement.fromDexType(appInfo.dexItemFactory.stringType, false, appInfo);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
index 0c8c372..3d30b82 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
@@ -135,7 +135,7 @@
@Override
public TypeLatticeElement evaluate(AppInfo appInfo) {
- return TypeLatticeElement.fromDexType(field.type, appInfo, true);
+ return TypeLatticeElement.fromDexType(field.type, true, appInfo);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Invoke.java b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
index b755336..468f3d05 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Invoke.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
@@ -280,6 +280,6 @@
if (returnType.isVoidType()) {
throw new Unreachable("void methods have no type.");
}
- return TypeLatticeElement.fromDexType(returnType, appInfo, true);
+ return TypeLatticeElement.fromDexType(returnType, true, appInfo);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index 562b33d..8166f6e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -105,7 +105,7 @@
if (targets.get(i) == currentBlock) {
DexType guard = guards.get(i);
exceptionTypes.add(
- guard == dexItemFactory.catchAllType
+ guard == DexItemFactory.catchAllType
? dexItemFactory.throwableType
: guard);
}
@@ -122,8 +122,6 @@
@Override
public TypeLatticeElement evaluate(AppInfo appInfo) {
Set<DexType> exceptionTypes = collectExceptionTypes(getBlock(), appInfo.dexItemFactory);
- return TypeLatticeElement.join(
- appInfo,
- exceptionTypes.stream().map(t -> TypeLatticeElement.fromDexType(t, appInfo, false)));
+ return TypeLatticeElement.joinTypes(exceptionTypes, false, appInfo);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
index 29b263f..18a60d4 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
@@ -107,7 +107,7 @@
@Override
public TypeLatticeElement evaluate(AppInfo appInfo) {
- return TypeLatticeElement.fromDexType(clazz, appInfo, false);
+ return TypeLatticeElement.fromDexType(clazz, false, appInfo);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
index 9ef7ed4..e767246 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
@@ -145,7 +145,7 @@
@Override
public TypeLatticeElement evaluate(AppInfo appInfo) {
- return TypeLatticeElement.fromDexType(field.type, appInfo, true);
+ return TypeLatticeElement.fromDexType(field.type, true, appInfo);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index b471e12..1853e8b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -680,8 +680,7 @@
Position position = source.getCanonicalDebugPositionAtOffset(moveExceptionItem.targetOffset);
if (moveExceptionDest >= 0) {
Set<DexType> exceptionTypes = MoveException.collectExceptionTypes(currentBlock, getFactory());
- TypeLatticeElement typeLattice = TypeLatticeElement.join(appInfo,
- exceptionTypes.stream().map(t -> TypeLatticeElement.fromDexType(t, appInfo, false)));
+ TypeLatticeElement typeLattice = TypeLatticeElement.joinTypes(exceptionTypes, false, appInfo);
Value out = writeRegister(moveExceptionDest, typeLattice, ThrowingInfo.NO_THROW, null);
MoveException moveException = new MoveException(out);
moveException.setPosition(position);
@@ -731,7 +730,7 @@
DebugLocalInfo local = getOutgoingLocal(register);
// TODO(b/72693244): Update nullability if this is for building inlinee's IR.
TypeLatticeElement receiver =
- TypeLatticeElement.fromDexType(method.method.getHolder(), appInfo, false);
+ TypeLatticeElement.fromDexType(method.method.getHolder(), false, appInfo);
Value value = writeRegister(register, receiver, ThrowingInfo.NO_THROW, local);
addInstruction(new Argument(value));
value.markAsThis();
@@ -872,7 +871,7 @@
public void addCheckCast(int value, DexType type) {
Value in = readRegister(value, ValueType.OBJECT);
TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(type, appInfo, in.getTypeLattice().isNullable());
+ TypeLatticeElement.fromDexType(type, in.getTypeLattice().isNullable(), appInfo);
Value out = writeRegister(value, castTypeLattice, ThrowingInfo.CAN_THROW);
CheckCast instruction = new CheckCast(out, in, type);
assert instruction.instructionTypeCanThrow();
@@ -931,7 +930,7 @@
null /* sourceString */);
}
TypeLatticeElement typeLattice =
- TypeLatticeElement.fromDexType(appInfo.dexItemFactory.methodHandleType, appInfo, false);
+ TypeLatticeElement.fromDexType(appInfo.dexItemFactory.methodHandleType, false, appInfo);
Value out = writeRegister(dest, typeLattice, ThrowingInfo.CAN_THROW);
ConstMethodHandle instruction = new ConstMethodHandle(out, methodHandle);
add(instruction);
@@ -945,7 +944,7 @@
null /* sourceString */);
}
TypeLatticeElement typeLattice =
- TypeLatticeElement.fromDexType(appInfo.dexItemFactory.methodTypeType, appInfo, false);
+ TypeLatticeElement.fromDexType(appInfo.dexItemFactory.methodTypeType, false, appInfo);
Value out = writeRegister(dest, typeLattice, ThrowingInfo.CAN_THROW);
ConstMethodType instruction = new ConstMethodType(out, methodType);
add(instruction);
@@ -1104,7 +1103,7 @@
MemberType type = MemberType.fromDexType(field.type);
Value in = readRegister(object, ValueType.OBJECT);
Value out = writeRegister(
- dest, TypeLatticeElement.fromDexType(field.type, appInfo, true), ThrowingInfo.CAN_THROW);
+ dest, TypeLatticeElement.fromDexType(field.type, true, appInfo), ThrowingInfo.CAN_THROW);
out.setKnownToBeBoolean(type == MemberType.BOOLEAN);
InstanceGet instruction = new InstanceGet(type, out, in, field);
assert instruction.instructionTypeCanThrow();
@@ -1415,7 +1414,7 @@
public void addNewArrayEmpty(int dest, int size, DexType type) {
assert type.isArrayType();
Value in = readRegister(size, ValueType.INT);
- TypeLatticeElement arrayTypeLattice = TypeLatticeElement.fromDexType(type, appInfo, false);
+ TypeLatticeElement arrayTypeLattice = TypeLatticeElement.fromDexType(type, false, appInfo);
Value out = writeRegister(dest, arrayTypeLattice, ThrowingInfo.CAN_THROW);
NewArrayEmpty instruction = new NewArrayEmpty(out, in, type);
assert instruction.instructionTypeCanThrow();
@@ -1427,7 +1426,7 @@
}
public void addNewInstance(int dest, DexType type) {
- TypeLatticeElement instanceType = TypeLatticeElement.fromDexType(type, appInfo, false);
+ TypeLatticeElement instanceType = TypeLatticeElement.fromDexType(type, false, appInfo);
Value out = writeRegister(dest, instanceType, ThrowingInfo.CAN_THROW);
NewInstance instruction = new NewInstance(type, out);
assert instruction.instructionTypeCanThrow();
@@ -1455,7 +1454,7 @@
public void addStaticGet(int dest, DexField field) {
MemberType type = MemberType.fromDexType(field.type);
Value out = writeRegister(
- dest, TypeLatticeElement.fromDexType(field.type, appInfo, true), ThrowingInfo.CAN_THROW);
+ dest, TypeLatticeElement.fromDexType(field.type, true, appInfo), ThrowingInfo.CAN_THROW);
out.setKnownToBeBoolean(type == MemberType.BOOLEAN);
StaticGet instruction = new StaticGet(type, out, field);
assert instruction.instructionTypeCanThrow();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index 129ed58..22113f8 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -277,7 +277,7 @@
if (lambdaInstanceValue == null) {
// The out value might be empty in case it was optimized out.
lambdaInstanceValue = code.createValue(
- TypeLatticeElement.fromDexType(lambdaClass.type, appInfo, true));
+ TypeLatticeElement.fromDexType(lambdaClass.type, true, appInfo));
}
// For stateless lambdas we replace InvokeCustom instruction with StaticGet
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
index c805494..1b13398 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
@@ -337,7 +337,7 @@
// new-instance v0, StringBuilder
TypeLatticeElement stringBuilderTypeLattice =
- TypeLatticeElement.fromDexType(factory.stringBuilderType, appInfo, false);
+ TypeLatticeElement.fromDexType(factory.stringBuilderType, false, appInfo);
Value sbInstance = code.createValue(stringBuilderTypeLattice);
appendInstruction(new NewInstance(factory.stringBuilderType, sbInstance));
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index f8b85de..93df273 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -297,7 +297,7 @@
BasicBlock rethrowBlock = BasicBlock.createRethrowBlock(
code,
lastSelfRecursiveCall.getPosition(),
- TypeLatticeElement.fromDexType(guard, appInfo, true));
+ TypeLatticeElement.fromDexType(guard, true, appInfo));
code.blocks.add(rethrowBlock);
// Add catch handler to the block containing the last recursive call.
newBlock.addCatchHandler(rethrowBlock, guard);
@@ -1660,11 +1660,11 @@
if (inTypeLattice.isPreciseType() || inTypeLattice.isNull()) {
TypeLatticeElement outTypeLattice = outValue.getTypeLattice();
TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(castType, appInfo, inTypeLattice.isNullable());
+ TypeLatticeElement.fromDexType(castType, inTypeLattice.isNullable(), appInfo);
assert inTypeLattice.nullElement().lessThanOrEqual(outTypeLattice.nullElement());
- if (TypeLatticeElement.lessThanOrEqual(appInfo, inTypeLattice, castTypeLattice)) {
+ if (inTypeLattice.lessThanOrEqual(castTypeLattice, appInfo)) {
// 1) Trivial cast.
// A a = ...
// A a' = (A) a;
@@ -1672,7 +1672,7 @@
// A < B
// A a = ...
// B b = (B) a;
- assert TypeLatticeElement.lessThanOrEqual(appInfo, inTypeLattice, outTypeLattice);
+ assert inTypeLattice.lessThanOrEqual(outTypeLattice, appInfo);
needToRemoveTrivialPhis = needToRemoveTrivialPhis || outValue.numberOfPhiUsers() != 0;
removeOrReplaceByDebugLocalWrite(checkCast, it, inValue, outValue);
} else {
@@ -3013,7 +3013,7 @@
DexType javaLangSystemType = dexItemFactory.createType("Ljava/lang/System;");
DexType javaIoPrintStreamType = dexItemFactory.createType("Ljava/io/PrintStream;");
Value out = code.createValue(
- TypeLatticeElement.fromDexType(javaIoPrintStreamType, appInfo, false));
+ TypeLatticeElement.fromDexType(javaIoPrintStreamType, false, appInfo));
DexProto proto = dexItemFactory.createProto(dexItemFactory.voidType, dexItemFactory.objectType);
DexMethod print = dexItemFactory.createMethod(javaIoPrintStreamType, proto, "print");
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index 37cfb44..e7b6ca8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -110,14 +110,13 @@
Value receiver = invoke.getReceiver();
TypeLatticeElement receiverTypeLattice = receiver.getTypeLattice();
TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(holderType, appInfo, receiverTypeLattice.isNullable());
+ TypeLatticeElement.fromDexType(holderType, receiverTypeLattice.isNullable(), appInfo);
// Avoid adding trivial cast and up-cast.
// We should not use strictlyLessThan(castType, receiverType), which detects downcast,
// due to side-casts, e.g., A (unused) < I, B < I, and cast from A to B.
// TODO(b/72693244): Soon, there won't be a value with imprecise type at this point.
if (!receiverTypeLattice.isPreciseType()
- || !TypeLatticeElement.lessThanOrEqual(
- appInfo, receiverTypeLattice, castTypeLattice)) {
+ || !receiverTypeLattice.lessThanOrEqual(castTypeLattice, appInfo)) {
Value newReceiver = null;
// If this value is ever downcast'ed to the same holder type before, and that casted
// value is safely accessible, i.e., the current line is dominated by that cast, use it.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
index 538d7be..51da91d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
@@ -115,7 +115,7 @@
NewInstance patchedNewInstance = new NewInstance(
group.getGroupClassType(),
context.code.createValue(
- TypeLatticeElement.fromDexType(newInstance.clazz, context.appInfo, false)));
+ TypeLatticeElement.fromDexType(newInstance.clazz, false, context.appInfo)));
context.instructions().replaceCurrentInstruction(patchedNewInstance);
}
@@ -160,7 +160,7 @@
// Since all captured values of non-primitive types are stored in fields of type
// java.lang.Object, we need to cast them to appropriate type to satisfy the verifier.
TypeLatticeElement castTypeLattice =
- TypeLatticeElement.fromDexType(fieldType, context.appInfo, false);
+ TypeLatticeElement.fromDexType(fieldType, false, context.appInfo);
Value newValue = context.code.createValue(castTypeLattice, newInstanceGet.getLocalInfo());
newInstanceGet.outValue().replaceUsers(newValue);
CheckCast cast = new CheckCast(newValue, newInstanceGet.outValue(), fieldType);
@@ -187,7 +187,7 @@
new StaticGet(
staticGet.getType(),
context.code.createValue(
- TypeLatticeElement.fromDexType(staticGet.getField().type, context.appInfo, true)),
+ TypeLatticeElement.fromDexType(staticGet.getField().type, true, context.appInfo)),
mapSingletonInstanceField(context.factory, staticGet.getField())));
}
@@ -222,7 +222,7 @@
private Value createValueForType(CodeProcessor context, DexType returnType) {
return returnType == context.factory.voidType ? null :
context.code.createValue(
- TypeLatticeElement.fromDexType(returnType, context.appInfo, true));
+ TypeLatticeElement.fromDexType(returnType, true, context.appInfo));
}
private List<Value> mapInitializerArgs(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 669baf9..ac3a8af 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -273,7 +273,7 @@
new StaticGet(
MemberType.fromDexType(field.type),
code.createValue(
- TypeLatticeElement.fromDexType(field.type, classStaticizer.appInfo, true),
+ TypeLatticeElement.fromDexType(field.type, true, classStaticizer.appInfo),
outValue.getLocalInfo()),
field
)
@@ -303,7 +303,7 @@
Value newOutValue = method.proto.returnType.isVoidType() ? null
: code.createValue(
TypeLatticeElement.fromDexType(
- method.proto.returnType, classStaticizer.appInfo, true),
+ method.proto.returnType, true, classStaticizer.appInfo),
outValue == null ? null : outValue.getLocalInfo());
it.replaceCurrentInstruction(
new InvokeStatic(newMethod, newOutValue, invoke.inValues()));
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
index f45a3de..c47a7bd 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
@@ -401,7 +401,7 @@
builder.append(minifiedRange).append(':');
}
builder.append(signature);
- if (originalRange != null) {
+ if (originalRange != null && !minifiedRange.equals(originalRange)) {
builder.append(":").append(originalRange);
}
builder.append(" -> ").append(renamedName);
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 828a463..e6fd878 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -41,8 +41,7 @@
public enum LineNumberOptimization {
OFF,
- ON,
- IDENTITY_MAPPING
+ ON
}
public final DexItemFactory itemFactory;
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 66490b2..e81d920 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -10,6 +10,16 @@
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexDebugEvent;
+import com.android.tools.r8.graph.DexDebugEvent.AdvanceLine;
+import com.android.tools.r8.graph.DexDebugEvent.AdvancePC;
+import com.android.tools.r8.graph.DexDebugEvent.Default;
+import com.android.tools.r8.graph.DexDebugEvent.EndLocal;
+import com.android.tools.r8.graph.DexDebugEvent.RestartLocal;
+import com.android.tools.r8.graph.DexDebugEvent.SetEpilogueBegin;
+import com.android.tools.r8.graph.DexDebugEvent.SetFile;
+import com.android.tools.r8.graph.DexDebugEvent.SetInlineFrame;
+import com.android.tools.r8.graph.DexDebugEvent.SetPrologueEnd;
+import com.android.tools.r8.graph.DexDebugEvent.StartLocal;
import com.android.tools.r8.graph.DexDebugEventBuilder;
import com.android.tools.r8.graph.DexDebugEventVisitor;
import com.android.tools.r8.graph.DexDebugInfo;
@@ -41,86 +51,6 @@
public class LineNumberOptimizer {
- // EventFilter is a visitor for DebugEvents, splits events into two sinks:
- // - Forwards non-positional events unchanged into a BypassedEventReceiver
- // - Forwards positional events, accumulated into DexDebugPositionStates, into
- // positionEventReceiver.
- private static class EventFilter implements DexDebugEventVisitor {
- private final BypassedEventReceiver bypassedEventReceiver;
- private final PositionEventReceiver positionEventReceiver;
-
- private interface BypassedEventReceiver {
- void receiveBypassedEvent(DexDebugEvent event);
- }
-
- private interface PositionEventReceiver {
- void receivePositionEvent(DexDebugPositionState positionState);
- }
-
- private final DexDebugPositionState positionState;
-
- private EventFilter(
- int startLine,
- DexMethod method,
- BypassedEventReceiver bypassedEventReceiver,
- PositionEventReceiver positionEventReceiver) {
- positionState = new DexDebugPositionState(startLine, method);
- this.bypassedEventReceiver = bypassedEventReceiver;
- this.positionEventReceiver = positionEventReceiver;
- }
-
- @Override
- public void visit(DexDebugEvent.SetPrologueEnd event) {
- bypassedEventReceiver.receiveBypassedEvent(event);
- }
-
- @Override
- public void visit(DexDebugEvent.SetEpilogueBegin event) {
- bypassedEventReceiver.receiveBypassedEvent(event);
- }
-
- @Override
- public void visit(DexDebugEvent.StartLocal event) {
- bypassedEventReceiver.receiveBypassedEvent(event);
- }
-
- @Override
- public void visit(DexDebugEvent.EndLocal event) {
- bypassedEventReceiver.receiveBypassedEvent(event);
- }
-
- @Override
- public void visit(DexDebugEvent.RestartLocal event) {
- bypassedEventReceiver.receiveBypassedEvent(event);
- }
-
- @Override
- public void visit(DexDebugEvent.AdvancePC advancePC) {
- positionState.visit(advancePC);
- }
-
- @Override
- public void visit(DexDebugEvent.AdvanceLine advanceLine) {
- positionState.visit(advanceLine);
- }
-
- @Override
- public void visit(DexDebugEvent.SetInlineFrame setInlineFrame) {
- positionState.visit(setInlineFrame);
- }
-
- @Override
- public void visit(DexDebugEvent.Default defaultEvent) {
- positionState.visit(defaultEvent);
- positionEventReceiver.receivePositionEvent(positionState);
- }
-
- @Override
- public void visit(DexDebugEvent.SetFile setFile) {
- positionState.visit(setFile);
- }
- }
-
// PositionRemapper is a stateful function which takes a position (represented by a
// DexDebugPositionState) and returns a remapped Position.
private interface PositionRemapper {
@@ -165,6 +95,11 @@
this.processedEvents = processedEvents;
}
+ private void emitAdvancePc(int pc) {
+ processedEvents.add(new AdvancePC(pc - previousPc));
+ previousPc = pc;
+ }
+
private void emitPositionEvents(int currentPc, Position currentPosition) {
if (previousPosition == null) {
startLine = currentPosition.line;
@@ -255,7 +190,6 @@
for (DexEncodedMethod method : methods) {
List<MappedPosition> mappedPositions = new ArrayList<>();
-
Code code = method.getCode();
if (code != null) {
if (code.isDexCode() && doesContainPositions(code.asDexCode())) {
@@ -469,36 +403,96 @@
DexDebugInfo debugInfo = dexCode.getDebugInfo();
List<DexDebugEvent> processedEvents = new ArrayList<>();
- // Our pipeline will be:
- // [debugInfo.events] -> eventFilter -> positionRemapper -> positionEventEmitter ->
- // [processedEvents]
PositionEventEmitter positionEventEmitter =
new PositionEventEmitter(application.dexItemFactory, method.method, processedEvents);
- EventFilter eventFilter =
- new EventFilter(
- debugInfo.startLine,
- method.method,
- processedEvents::add,
- positionState -> {
- int currentLine = positionState.getCurrentLine();
- assert currentLine >= 0;
- Position position =
- positionRemapper.createRemappedPosition(
- positionState.getCurrentLine(),
- positionState.getCurrentFile(),
- positionState.getCurrentMethod(),
- positionState.getCurrentCallerPosition());
- mappedPositions.add(
- new MappedPosition(
- positionState.getCurrentMethod(),
- currentLine,
- positionState.getCurrentCallerPosition(),
- position.line));
- positionEventEmitter.emitPositionEvents(positionState.getCurrentPc(), position);
- });
+ // Debug event visitor to map line numbers.
+ // TODO(117268618): Cleanup the duplicate pc tracking.
+ DexDebugEventVisitor visitor =
+ new DexDebugEventVisitor() {
+ DexDebugPositionState state =
+ new DexDebugPositionState(debugInfo.startLine, method.method);
+ int currentPc = 0;
+
+ private void flushPc() {
+ if (currentPc != state.getCurrentPc()) {
+ positionEventEmitter.emitAdvancePc(state.getCurrentPc());
+ currentPc = state.getCurrentPc();
+ }
+ }
+
+ @Override
+ public void visit(AdvancePC advancePC) {
+ state.visit(advancePC);
+ }
+
+ @Override
+ public void visit(AdvanceLine advanceLine) {
+ state.visit(advanceLine);
+ }
+
+ @Override
+ public void visit(SetInlineFrame setInlineFrame) {
+ state.visit(setInlineFrame);
+ }
+
+ @Override
+ public void visit(Default defaultEvent) {
+ state.visit(defaultEvent);
+ int currentLine = state.getCurrentLine();
+ assert currentLine >= 0;
+ Position position =
+ positionRemapper.createRemappedPosition(
+ state.getCurrentLine(),
+ state.getCurrentFile(),
+ state.getCurrentMethod(),
+ state.getCurrentCallerPosition());
+ mappedPositions.add(
+ new MappedPosition(
+ state.getCurrentMethod(),
+ currentLine,
+ state.getCurrentCallerPosition(),
+ position.line));
+ positionEventEmitter.emitPositionEvents(state.getCurrentPc(), position);
+ currentPc = state.getCurrentPc();
+ }
+
+ @Override
+ public void visit(SetFile setFile) {
+ processedEvents.add(setFile);
+ }
+
+ @Override
+ public void visit(SetPrologueEnd setPrologueEnd) {
+ processedEvents.add(setPrologueEnd);
+ }
+
+ @Override
+ public void visit(SetEpilogueBegin setEpilogueBegin) {
+ processedEvents.add(setEpilogueBegin);
+ }
+
+ @Override
+ public void visit(StartLocal startLocal) {
+ flushPc();
+ processedEvents.add(startLocal);
+ }
+
+ @Override
+ public void visit(EndLocal endLocal) {
+ flushPc();
+ processedEvents.add(endLocal);
+ }
+
+ @Override
+ public void visit(RestartLocal restartLocal) {
+ flushPc();
+ processedEvents.add(restartLocal);
+ }
+ };
+
for (DexDebugEvent event : debugInfo.events) {
- event.accept(eventFilter);
+ event.accept(visitor);
}
DexDebugInfo optimizedDebugInfo =
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 3adece1..515d191 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -105,6 +105,9 @@
private static final String PROGUARD6_0_1 = "third_party/proguard/proguard6.0.1/bin/proguard";
private static final String PROGUARD = PROGUARD5_2_1;
+ private static final String RETRACE6_0_1 = "third_party/proguard/proguard6.0.1/bin/retrace";
+ private static final String RETRACE = RETRACE6_0_1;
+
public static final Path R8_JAR = Paths.get(LIBS_DIR, "r8.jar");
public static final Path R8_LIB_JAR = Paths.get(LIBS_DIR, "r8lib_with_deps.jar");
@@ -525,6 +528,13 @@
return PROGUARD6_0_1 + ".sh";
}
+ private static String getRetraceScript() {
+ if (isWindows()) {
+ return RETRACE + ".bat";
+ }
+ return RETRACE + ".sh";
+ }
+
private static Path getDxExecutablePath() {
String toolsDir = toolsDir();
String executableName = toolsDir.equals("windows") ? "dx.bat" : "dx";
@@ -1499,6 +1509,23 @@
return runProguard(getProguard6Script(), inJar, outJar, configs, map);
}
+ public static ProcessResult runRetraceRaw(Path map, Path stackTrace) throws IOException {
+ List<String> command = new ArrayList<>();
+ command.add(getRetraceScript());
+ command.add(map.toString());
+ command.add(stackTrace.toString());
+ ProcessBuilder builder = new ProcessBuilder(command);
+ return ToolHelper.runProcess(builder);
+ }
+
+ public static String runRetrace(Path map, Path stackTrace) throws IOException {
+ ProcessResult result = runRetraceRaw(map, stackTrace);
+ if (result.exitCode != 0) {
+ fail("Retrace failed, exit code " + result.exitCode + ", stderr:\n" + result.stderr);
+ }
+ return result.stdout;
+ }
+
public static class ProcessResult {
public final int exitCode;
diff --git a/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java b/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
index 616256e..78e9a56 100644
--- a/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LineNumberOptimizationTest.java
@@ -96,12 +96,6 @@
}
@Test
- public void testIdentityCompilation() throws Throwable {
- // Compilation will fail if the identity translation does.
- makeConfig(LineNumberOptimization.IDENTITY_MAPPING, true, false, runtimeKind);
- }
-
- @Test
public void testNotOptimized() throws Throwable {
testRelease(
makeConfig(LineNumberOptimization.OFF, false, false, runtimeKind), ORIGINAL_LINE_NUMBERS);
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
index 109a6cb..bd0f8fb 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/NullabilityTest.java
@@ -120,9 +120,9 @@
DexType mainClass = appInfo.dexItemFactory.createType(
DescriptorUtils.javaTypeToDescriptor(NonNullAfterInvoke.class.getCanonicalName()));
Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices = ImmutableMap.of(
- InvokeVirtual.class, fromDexType(appInfo.dexItemFactory.stringType, appInfo, true),
- NonNull.class, fromDexType(appInfo.dexItemFactory.stringType, appInfo, false),
- NewInstance.class, fromDexType(assertionErrorType, appInfo, false));
+ InvokeVirtual.class, fromDexType(appInfo.dexItemFactory.stringType, true, appInfo),
+ NonNull.class, fromDexType(appInfo.dexItemFactory.stringType, false, appInfo),
+ NewInstance.class, fromDexType(assertionErrorType, false, appInfo));
forEachOutValue(irCode, (v, l) -> verifyClassTypeLattice(expectedLattices, mainClass, v, l));
});
}
@@ -136,9 +136,9 @@
DexType mainClass = appInfo.dexItemFactory.createType(
DescriptorUtils.javaTypeToDescriptor(NonNullAfterInvoke.class.getCanonicalName()));
Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices = ImmutableMap.of(
- InvokeVirtual.class, fromDexType(appInfo.dexItemFactory.stringType, appInfo, true),
- NonNull.class, fromDexType(appInfo.dexItemFactory.stringType, appInfo, false),
- NewInstance.class, fromDexType(assertionErrorType, appInfo, false));
+ InvokeVirtual.class, fromDexType(appInfo.dexItemFactory.stringType, true, appInfo),
+ NonNull.class, fromDexType(appInfo.dexItemFactory.stringType, false, appInfo),
+ NewInstance.class, fromDexType(assertionErrorType, false, appInfo));
forEachOutValue(irCode, (v, l) -> verifyClassTypeLattice(expectedLattices, mainClass, v, l));
});
}
@@ -153,8 +153,8 @@
DescriptorUtils.javaTypeToDescriptor(NonNullAfterArrayAccess.class.getCanonicalName()));
Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices = ImmutableMap.of(
// An element inside a non-null array could be null.
- ArrayGet.class, fromDexType(appInfo.dexItemFactory.stringType, appInfo, true),
- NewInstance.class, fromDexType(assertionErrorType, appInfo, false));
+ ArrayGet.class, fromDexType(appInfo.dexItemFactory.stringType, true, appInfo),
+ NewInstance.class, fromDexType(assertionErrorType, false, appInfo));
forEachOutValue(irCode, (v, l) -> {
if (l.isArrayType()) {
ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
@@ -179,8 +179,8 @@
DescriptorUtils.javaTypeToDescriptor(NonNullAfterArrayAccess.class.getCanonicalName()));
Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices = ImmutableMap.of(
// An element inside a non-null array could be null.
- ArrayGet.class, fromDexType(appInfo.dexItemFactory.stringType, appInfo, true),
- NewInstance.class, fromDexType(assertionErrorType, appInfo, false));
+ ArrayGet.class, fromDexType(appInfo.dexItemFactory.stringType, true, appInfo),
+ NewInstance.class, fromDexType(assertionErrorType, false, appInfo));
forEachOutValue(irCode, (v, l) -> {
if (l.isArrayType()) {
ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
@@ -206,11 +206,11 @@
DexType testClass = appInfo.dexItemFactory.createType(
DescriptorUtils.javaTypeToDescriptor(FieldAccessTest.class.getCanonicalName()));
Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices = ImmutableMap.of(
- Argument.class, fromDexType(testClass, appInfo, true),
- NonNull.class, fromDexType(testClass, appInfo, false),
+ Argument.class, fromDexType(testClass, true, appInfo),
+ NonNull.class, fromDexType(testClass, false, appInfo),
// instance may not be initialized.
- InstanceGet.class, fromDexType(appInfo.dexItemFactory.stringType, appInfo, true),
- NewInstance.class, fromDexType(assertionErrorType, appInfo, false));
+ InstanceGet.class, fromDexType(appInfo.dexItemFactory.stringType, true, appInfo),
+ NewInstance.class, fromDexType(assertionErrorType, false, appInfo));
forEachOutValue(irCode, (v, l) -> verifyClassTypeLattice(expectedLattices, mainClass, v, l));
});
}
@@ -226,11 +226,11 @@
DexType testClass = appInfo.dexItemFactory.createType(
DescriptorUtils.javaTypeToDescriptor(FieldAccessTest.class.getCanonicalName()));
Map<Class<? extends Instruction>, TypeLatticeElement> expectedLattices = ImmutableMap.of(
- Argument.class, fromDexType(testClass, appInfo, true),
- NonNull.class, fromDexType(testClass, appInfo, false),
+ Argument.class, fromDexType(testClass, true, appInfo),
+ NonNull.class, fromDexType(testClass, false, appInfo),
// instance may not be initialized.
- InstanceGet.class, fromDexType(appInfo.dexItemFactory.stringType, appInfo, true),
- NewInstance.class, fromDexType(assertionErrorType, appInfo, false));
+ InstanceGet.class, fromDexType(appInfo.dexItemFactory.stringType, true, appInfo),
+ NewInstance.class, fromDexType(assertionErrorType, false, appInfo));
forEachOutValue(irCode, (v, l) -> verifyClassTypeLattice(expectedLattices, mainClass, v, l));
});
}
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java
index 8d956a8..08a220f 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeLatticeTest.java
@@ -75,7 +75,7 @@
}
private TypeLatticeElement element(DexType type) {
- return TypeLatticeElement.fromDexType(type, appInfo, true);
+ return TypeLatticeElement.fromDexType(type, true, appInfo);
}
private ArrayTypeLatticeElement array(int nesting, DexType base) {
@@ -84,15 +84,15 @@
private TypeLatticeElement join(TypeLatticeElement... elements) {
assertTrue(elements.length > 1);
- return TypeLatticeElement.join(appInfo, Arrays.stream(elements));
+ return TypeLatticeElement.join(Arrays.stream(elements), appInfo);
}
private boolean strictlyLessThan(TypeLatticeElement l1, TypeLatticeElement l2) {
- return TypeLatticeElement.strictlyLessThan(appInfo, l1, l2);
+ return l1.strictlyLessThan(l2, appInfo);
}
private boolean lessThanOrEqual(TypeLatticeElement l1, TypeLatticeElement l2) {
- return TypeLatticeElement.lessThanOrEqual(appInfo, l1, l2);
+ return l1.lessThanOrEqual(l2, appInfo);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/RetraceTest.java b/src/test/java/com/android/tools/r8/naming/retrace/RetraceTest.java
new file mode 100644
index 0000000..7ef1c3f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/naming/retrace/RetraceTest.java
@@ -0,0 +1,135 @@
+// Copyright (c) 2018, 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.naming.retrace;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.BiConsumer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class RetraceTest extends TestBase {
+ private Backend backend;
+ private CompilationMode mode;
+
+ @Parameters(name = "Backend: {0}, mode: {1}")
+ public static Collection<Object[]> data() {
+ List<Object[]> parameters = new ArrayList<>();
+ for (Backend backend : Backend.values()) {
+ for (CompilationMode mode : CompilationMode.values()) {
+ parameters.add(new Object[] {backend, mode});
+ }
+ }
+ return parameters;
+ }
+
+ public RetraceTest(Backend backend, CompilationMode mode) {
+ this.backend = backend;
+ this.mode = mode;
+ }
+
+ private List<String> retrace(String map, List<String> stackTrace) throws IOException {
+ Path t = temp.newFolder().toPath();
+ Path mapFile = t.resolve("map");
+ Path stackTraceFile = t.resolve("stackTrace");
+ FileUtils.writeTextFile(mapFile, map);
+ FileUtils.writeTextFile(stackTraceFile, stackTrace);
+ return StringUtils.splitLines(ToolHelper.runRetrace(mapFile, stackTraceFile));
+ }
+
+ private List<String> extractStackTrace(ProcessResult result) {
+ ImmutableList.Builder<String> builder = ImmutableList.builder();
+ List<String> stderr = StringUtils.splitLines(result.stderr);
+ Iterator<String> iterator = stderr.iterator();
+ while (iterator.hasNext()) {
+ String line = iterator.next();
+ if (line.startsWith("Exception in thread \"main\"")) {
+ break;
+ }
+ }
+ iterator.forEachRemaining(builder::add);
+ return builder.build();
+ }
+
+ public void runTest(Class<?> mainClass, BiConsumer<List<String>, List<String>> checker)
+ throws Exception {
+ StringBuilder proguardMapBuilder = new StringBuilder();
+ AndroidApp output =
+ ToolHelper.runR8(
+ R8Command.builder()
+ .setMode(mode)
+ .addClassProgramData(ToolHelper.getClassAsBytes(mainClass), Origin.unknown())
+ .addProguardConfiguration(
+ ImmutableList.of(keepMainProguardConfiguration(mainClass)), Origin.unknown())
+ .setProgramConsumer(emptyConsumer(backend))
+ .setProguardMapConsumer((string, ignore) -> proguardMapBuilder.append(string))
+ .build());
+
+ ProcessResult result = runOnVMRaw(output, mainClass, backend);
+ List<String> stackTrace = extractStackTrace(result);
+ List<String> retracesStackTrace = retrace(proguardMapBuilder.toString(), stackTrace);
+ checker.accept(stackTrace, retracesStackTrace);
+ }
+
+ @Test
+ public void test() throws Exception {
+ runTest(
+ Main.class,
+ (List<String> stackTrace, List<String> retracesStackTrace) -> {
+ assertEquals(
+ mode == CompilationMode.RELEASE, stackTrace.size() != retracesStackTrace.size());
+ if (mode == CompilationMode.DEBUG) {
+ assertThat(stackTrace.get(0), not(containsString("method2")));
+ assertThat(stackTrace.get(1), not(containsString("method1")));
+ assertThat(stackTrace.get(2), containsString("main"));
+ }
+ assertEquals(3, retracesStackTrace.size());
+ assertThat(retracesStackTrace.get(0), containsString("method2"));
+ assertThat(retracesStackTrace.get(1), containsString("method1"));
+ assertThat(retracesStackTrace.get(2), containsString("main"));
+ });
+ }
+}
+
+class Main {
+ public static void method2(int i) {
+ System.out.println("In method2");
+ throw null;
+ }
+
+ public static void method1(String s) {
+ System.out.println("In method1");
+ for (int i = 0; i < 10; i++) {
+ method2(Integer.parseInt(s));
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println("In main");
+ method1("1");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/KeepAttributesTest.java b/src/test/java/com/android/tools/r8/shaking/KeepAttributesTest.java
index b518683..96ce54a 100644
--- a/src/test/java/com/android/tools/r8/shaking/KeepAttributesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/KeepAttributesTest.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -13,23 +13,36 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.debuginfo.DebugInfoInspector;
-import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.forceproguardcompatibility.keepattributes.TestKeepAttributes;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.AndroidAppConsumers;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+@RunWith(Parameterized.class)
public class KeepAttributesTest extends TestBase {
- public static final Class CLASS = TestKeepAttributes.class;
+ private static final Class CLASS = TestKeepAttributes.class;
+
+ @Parameters(name = "{0}")
+ public static Backend[] parameters() {
+ return new Backend[] { Backend.CF, Backend.DEX};
+ }
+
+ private final Backend backend;
+
+ public KeepAttributesTest(Backend backend) {
+ this.backend = backend;
+ }
@Test
public void keepAllAttributesInDebugMode()
@@ -37,10 +50,9 @@
List<String> keepRules = ImmutableList.of(
"-keep class ** { *; }"
);
- CodeInspector inspector = compile(keepRules, CompilationMode.DEBUG);
- DebugInfoInspector debugInfo = debugInfoForMain(inspector);
- checkLineNumbers(true, debugInfo);
- checkLocals(true, debugInfo);
+ MethodSubject mainMethod = compileRunAndGetMain(keepRules, CompilationMode.DEBUG);
+ assertTrue(mainMethod.hasLineNumberTable());
+ assertTrue(mainMethod.hasLocalVariableTable());
}
@Test
@@ -49,10 +61,9 @@
List<String> keepRules = ImmutableList.of(
"-keep class ** { *; }"
);
- CodeInspector inspector = compile(keepRules, CompilationMode.RELEASE);
- DebugInfoInspector debugInfo = debugInfoForMain(inspector);
- checkLineNumbers(false, debugInfo);
- checkLocals(false, debugInfo);
+ MethodSubject mainMethod = compileRunAndGetMain(keepRules, CompilationMode.RELEASE);
+ assertFalse(mainMethod.hasLineNumberTable());
+ assertFalse(mainMethod.hasLocalVariableTable());
}
@Test
@@ -62,10 +73,9 @@
"-keep class ** { *; }",
"-keepattributes " + ProguardKeepAttributes.LINE_NUMBER_TABLE
);
- CodeInspector inspector = compile(keepRules, CompilationMode.RELEASE);
- DebugInfoInspector debugInfo = debugInfoForMain(inspector);
- checkLineNumbers(true, debugInfo);
- checkLocals(false, debugInfo);
+ MethodSubject mainMethod = compileRunAndGetMain(keepRules, CompilationMode.RELEASE);
+ assertTrue(mainMethod.hasLineNumberTable());
+ assertFalse(mainMethod.hasLocalVariableTable());
}
@Test
@@ -78,11 +88,10 @@
+ ", "
+ ProguardKeepAttributes.LOCAL_VARIABLE_TABLE
);
- CodeInspector inspector = compile(keepRules, CompilationMode.RELEASE);
- DebugInfoInspector debugInfo = debugInfoForMain(inspector);
- checkLineNumbers(true, debugInfo);
+ MethodSubject mainMethod = compileRunAndGetMain(keepRules, CompilationMode.RELEASE);
+ assertTrue(mainMethod.hasLineNumberTable());
// Locals are never included in release builds.
- checkLocals(false, debugInfo);
+ assertFalse(mainMethod.hasLocalVariableTable());
}
@Test
@@ -93,7 +102,7 @@
);
// Compiling with a keep rule for locals but no line results in an error in R8.
try {
- compile(keepRules, CompilationMode.RELEASE);
+ compileRunAndGetMain(keepRules, CompilationMode.RELEASE);
} catch (CompilationFailedException e) {
assertTrue(e.getCause().getMessage().contains(ProguardKeepAttributes.LOCAL_VARIABLE_TABLE));
assertTrue(e.getCause().getMessage().contains(ProguardKeepAttributes.LINE_NUMBER_TABLE));
@@ -102,7 +111,7 @@
fail("Expected error");
}
- private CodeInspector compile(List<String> keepRules, CompilationMode mode)
+ private MethodSubject compileRunAndGetMain(List<String> keepRules, CompilationMode mode)
throws CompilationFailedException, IOException, ExecutionException {
AndroidAppConsumers sink = new AndroidAppConsumers();
R8.run(
@@ -111,30 +120,14 @@
.addProgramFiles(
ToolHelper.getClassFilesForTestDirectory(
ToolHelper.getClassFileForTestClass(CLASS).getParent()))
- .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
+ .addLibraryFiles(runtimeJar(backend))
.addProguardConfiguration(keepRules, Origin.unknown())
- .setProgramConsumer(sink.wrapProgramConsumer(emptyConsumer(Backend.DEX)))
+ .setProgramConsumer(sink.wrapProgramConsumer(emptyConsumer(backend)))
.build());
AndroidApp app = sink.build();
CodeInspector codeInspector = new CodeInspector(app);
- runOnArt(app, CLASS.getTypeName());
- return codeInspector;
+ runOnVM(app, CLASS.getTypeName(), backend);
+ return codeInspector.clazz(CLASS).mainMethod();
}
- private DebugInfoInspector debugInfoForMain(CodeInspector inspector) {
- return new DebugInfoInspector(
- inspector,
- CLASS.getTypeName(),
- new MethodSignature("main", "void", Collections.singleton("java.lang.String[]")));
- }
-
- private void checkLineNumbers(boolean expected, DebugInfoInspector debugInfo) {
- assertEquals("Expected " + (expected ? "line entries" : "no line entries"),
- expected, debugInfo.getEntries().stream().anyMatch(e -> e.lineEntry));
- }
-
- private void checkLocals(boolean expected, DebugInfoInspector debugInfo) {
- assertEquals("Expected " + (expected ? "locals" : "no locals"),
- expected, debugInfo.getEntries().stream().anyMatch(e -> !e.locals.isEmpty()));
- }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
index 1396be9..adee8cf 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
@@ -78,4 +78,14 @@
public String getFinalSignatureAttribute() {
return null;
}
+
+ @Override
+ public boolean hasLineNumberTable() {
+ return false;
+ }
+
+ @Override
+ public boolean hasLocalVariableTable() {
+ return false;
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index 3fe8186..f205594 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -4,12 +4,22 @@
package com.android.tools.r8.utils.codeinspector;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfPosition;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.Code;
+import com.android.tools.r8.graph.DexCode;
+import com.android.tools.r8.graph.DexDebugEvent;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.signature.GenericSignatureParser;
import java.util.Iterator;
+import java.util.ListIterator;
import java.util.function.Predicate;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.LineNumberNode;
public class FoundMethodSubject extends MethodSubject {
@@ -134,6 +144,69 @@
}
@Override
+ public boolean hasLineNumberTable() {
+ Code code = getMethod().getCode();
+ if (code.isDexCode()) {
+ DexCode dexCode = code.asDexCode();
+ if (dexCode.getDebugInfo() != null) {
+ for (DexDebugEvent event : dexCode.getDebugInfo().events) {
+ if (event instanceof DexDebugEvent.Default) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ if (code.isCfCode()) {
+ for (CfInstruction insn : code.asCfCode().getInstructions()) {
+ if (insn instanceof CfPosition) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (code.isJarCode()) {
+ ListIterator<AbstractInsnNode> it = code.asJarCode().getNode().instructions.iterator();
+ while (it.hasNext()) {
+ if (it.next() instanceof LineNumberNode) {
+ return true;
+ }
+ }
+ return false;
+ }
+ throw new Unreachable("Unexpected code type: " + code.getClass().getSimpleName());
+ }
+
+ @Override
+ public boolean hasLocalVariableTable() {
+ Code code = getMethod().getCode();
+ if (code.isDexCode()) {
+ DexCode dexCode = code.asDexCode();
+ if (dexCode.getDebugInfo() != null) {
+ for (DexString parameter : dexCode.getDebugInfo().parameters) {
+ if (parameter != null) {
+ return true;
+ }
+ }
+ for (DexDebugEvent event : dexCode.getDebugInfo().events) {
+ if (event instanceof DexDebugEvent.StartLocal) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ if (code.isCfCode()) {
+ return !code.asCfCode().getLocalVariables().isEmpty();
+ }
+ if (code.isJarCode()) {
+ return code.asJarCode().getNode().localVariables != null
+ && !code.asJarCode().getNode().localVariables.isEmpty();
+ }
+ throw new Unreachable("Unexpected code type: " + code.getClass().getSimpleName());
+ }
+
+ @Override
public String toString() {
return dexMethod.toSourceString();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
index 6eaaf5f..55030ca 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
@@ -32,4 +32,8 @@
Predicate<InstructionSubject> filter) {
return null;
}
+
+ public abstract boolean hasLineNumberTable();
+
+ public abstract boolean hasLocalVariableTable();
}