Version 1.3.27
Merge: Compute highestSortingString in DexCode.collectIndexedItems()
CL: https://r8-review.googlesource.com/c/r8/+/29320
Bug: 117828645
Change-Id: I30863d519b9cdc6f61e1279bef9a4687fb6bc7b4
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index b7f1455..d394692 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "1.3.26";
+ public static final String LABEL = "1.3.27";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstString.java b/src/main/java/com/android/tools/r8/code/ConstString.java
index d165de5..a5733ad 100644
--- a/src/main/java/com/android/tools/r8/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/code/ConstString.java
@@ -45,6 +45,16 @@
}
@Override
+ public ConstString asConstString() {
+ return this;
+ }
+
+ @Override
+ public boolean isConstString() {
+ return true;
+ }
+
+ @Override
public String toString(ClassNameMapper naming) {
return formatString("v" + AA + ", \"" + BBBB.toString() + "\"");
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstStringJumbo.java b/src/main/java/com/android/tools/r8/code/ConstStringJumbo.java
index 5f4c4d8..b24f86f 100644
--- a/src/main/java/com/android/tools/r8/code/ConstStringJumbo.java
+++ b/src/main/java/com/android/tools/r8/code/ConstStringJumbo.java
@@ -42,6 +42,16 @@
}
@Override
+ public ConstStringJumbo asConstStringJumbo() {
+ return this;
+ }
+
+ @Override
+ public boolean isConstStringJumbo() {
+ return true;
+ }
+
+ @Override
public String toString(ClassNameMapper naming) {
return formatString("v" + AA + ", \"" + BBBBBBBB.toString() + "\"");
}
diff --git a/src/main/java/com/android/tools/r8/code/Instruction.java b/src/main/java/com/android/tools/r8/code/Instruction.java
index c8b5154..aaf9140 100644
--- a/src/main/java/com/android/tools/r8/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/code/Instruction.java
@@ -122,6 +122,22 @@
this.offset = offset;
}
+ public ConstString asConstString() {
+ return null;
+ }
+
+ public boolean isConstString() {
+ return false;
+ }
+
+ public ConstStringJumbo asConstStringJumbo() {
+ return null;
+ }
+
+ public boolean isConstStringJumbo() {
+ return false;
+ }
+
public boolean isSimpleNop() {
return !isPayload() && this instanceof Nop;
}
diff --git a/src/main/java/com/android/tools/r8/code/InstructionFactory.java b/src/main/java/com/android/tools/r8/code/InstructionFactory.java
index 40c5f6e..14d2f4b 100644
--- a/src/main/java/com/android/tools/r8/code/InstructionFactory.java
+++ b/src/main/java/com/android/tools/r8/code/InstructionFactory.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.code;
-import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
@@ -12,8 +11,6 @@
public class InstructionFactory extends BaseInstructionFactory {
- private DexString highestSortingString = null;
-
static private Instruction readFrom(ShortBufferBytecodeStream stream,
OffsetToObjectMapping mapping) {
int high = stream.nextByte();
@@ -33,26 +30,11 @@
List<Instruction> insn = new ArrayList<>(length);
while (range.hasMore()) {
Instruction instruction = readFrom(range, mapping);
- if (instruction instanceof ConstString) {
- updateHighestSortingString(((ConstString) instruction).getString());
- } else if (instruction instanceof ConstStringJumbo) {
- updateHighestSortingString(((ConstStringJumbo) instruction).getString());
- }
insn.add(instruction);
}
return insn.toArray(new Instruction[insn.size()]);
}
- public DexString getHighestSortingString() {
- return highestSortingString;
- }
-
- private void updateHighestSortingString(DexString string) {
- if (highestSortingString == null || highestSortingString.slowCompareTo(string) < 0) {
- highestSortingString = string;
- }
- }
-
private static class ShortBufferBytecodeStream implements BytecodeStream {
private final int length;
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index d762646..0240da5 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -825,15 +825,7 @@
InstructionFactory factory = new InstructionFactory();
Instruction[] instructions =
factory.readSequenceFrom(ShortBuffer.wrap(code), 0, code.length, indexedItems);
- return new DexCode(
- registerSize,
- insSize,
- outsSize,
- instructions,
- tries,
- handlers,
- debugInfo,
- factory.getHighestSortingString());
+ return new DexCode(registerSize, insSize, outsSize, instructions, tries, handlers, debugInfo);
}
void populateIndexTables() {
diff --git a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
index b151ef8..1c18107 100644
--- a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
+++ b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
@@ -120,18 +120,20 @@
TryHandler[] newHandlers = rewriteHandlerOffsets();
DexDebugInfo newDebugInfo = rewriteDebugInfoOffsets();
// Set the new code on the method.
- DexCode code = method.getCode().asDexCode();
+ DexCode oldCode = method.getCode().asDexCode();
+ DexCode newCode =
+ new DexCode(
+ oldCode.registerSize,
+ oldCode.incomingRegisterSize,
+ oldCode.outgoingRegisterSize,
+ newInstructions.toArray(new Instruction[newInstructions.size()]),
+ newTries,
+ newHandlers,
+ newDebugInfo);
// As we have rewritten the code, we now know that its highest string index that is not
// a jumbo-string is firstJumboString (actually the previous string, but we do not have that).
- method.setCode(new DexCode(
- code.registerSize,
- code.incomingRegisterSize,
- code.outgoingRegisterSize,
- newInstructions.toArray(new Instruction[newInstructions.size()]),
- newTries,
- newHandlers,
- newDebugInfo,
- firstJumboString));
+ newCode.highestSortingString = firstJumboString;
+ method.setCode(newCode);
}
private void rewriteInstructionOffsets(List<Instruction> instructions) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index 4b52a9e..8d37b45 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -38,7 +38,7 @@
public final TryHandler[] handlers;
public final Instruction[] instructions;
- public final DexString highestSortingString;
+ public DexString highestSortingString;
private DexDebugInfo debugInfo;
public DexCode(
@@ -48,8 +48,7 @@
Instruction[] instructions,
Try[] tries,
TryHandler[] handlers,
- DexDebugInfo debugInfo,
- DexString highestSortingString) {
+ DexDebugInfo debugInfo) {
this.incomingRegisterSize = insSize;
this.registerSize = registerSize;
this.outgoingRegisterSize = outsSize;
@@ -57,7 +56,6 @@
this.tries = tries;
this.handlers = handlers;
this.debugInfo = debugInfo;
- this.highestSortingString = highestSortingString;
hashCode(); // Cache the hash code eagerly.
}
@@ -68,8 +66,14 @@
// by 1, it becomes just a regular register which is never used, and thus will be
// gone when we build an IR from this code. Rebuilding IR for methods 'staticized'
// this way is highly recommended to improve register allocation.
- return new DexCode(registerSize, incomingRegisterSize - 1, outgoingRegisterSize,
- instructions, tries, handlers, debugInfoWithoutFirstParameter(), highestSortingString);
+ return new DexCode(
+ registerSize,
+ incomingRegisterSize - 1,
+ outgoingRegisterSize,
+ instructions,
+ tries,
+ handlers,
+ debugInfoWithoutFirstParameter());
}
@Override
@@ -371,8 +375,14 @@
public void collectIndexedItems(
IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
assert instructionOffset == -1;
+ highestSortingString = null;
for (Instruction insn : instructions) {
insn.collectIndexedItems(indexedItems, method, insn.getOffset());
+ if (insn.isConstString()) {
+ updateHighestSortingString(insn.asConstString().getString());
+ } else if (insn.isConstStringJumbo()) {
+ updateHighestSortingString(insn.asConstStringJumbo().getString());
+ }
}
if (debugInfo != null) {
debugInfo.collectIndexedItems(indexedItems);
@@ -384,6 +394,14 @@
}
}
+ private void updateHighestSortingString(DexString candidate) {
+ assert candidate != null;
+ assert !(candidate instanceof DexItemBasedString);
+ if (highestSortingString == null || highestSortingString.slowCompareTo(candidate) < 0) {
+ highestSortingString = candidate;
+ }
+ }
+
public boolean usesExceptionHandling() {
return tries.length != 0;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index bca0395..c3db796 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -492,9 +492,14 @@
for (DexType type : method.proto.parameters.values) {
requiredArgRegisters += ValueType.fromDexType(type).requiredRegisters();
}
- // Passing null as highestSortingString is save, as ConstString instructions are not allowed.
- return new DexCode(Math.max(numberOfRegisters, requiredArgRegisters), requiredArgRegisters,
- outRegisters, instructions, new DexCode.Try[0], new DexCode.TryHandler[0], null, null);
+ return new DexCode(
+ Math.max(numberOfRegisters, requiredArgRegisters),
+ requiredArgRegisters,
+ outRegisters,
+ instructions,
+ new DexCode.Try[0],
+ new DexCode.TryHandler[0],
+ null);
}
public DexEncodedMethod toEmptyThrowingMethodDex() {
@@ -674,9 +679,13 @@
DexString firstJumboString = null;
if (force) {
firstJumboString = mapping.getFirstString();
- } else if (code.highestSortingString != null
- && mapping.getOffsetFor(code.highestSortingString) > Constants.MAX_NON_JUMBO_INDEX) {
- firstJumboString = mapping.getFirstJumboString();
+ } else {
+ assert code.highestSortingString != null
+ || Arrays.stream(code.instructions).noneMatch(Instruction::isConstString);
+ if (code.highestSortingString != null
+ && mapping.getOffsetFor(code.highestSortingString) > Constants.MAX_NON_JUMBO_INDEX) {
+ firstJumboString = mapping.getFirstJumboString();
+ }
}
if (firstJumboString != null) {
JumboStringRewriter rewriter =
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemBasedString.java b/src/main/java/com/android/tools/r8/graph/DexItemBasedString.java
index 34f850e..3a23ed8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemBasedString.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemBasedString.java
@@ -7,6 +7,8 @@
import com.android.tools.r8.errors.Unreachable;
import java.util.Arrays;
+// TODO(b/117828645): Introduce a DexItemBasedConstString instruction instead, as the use of
+// DexItemBasedString implies that we cannot rely on DexStrings being canonicalized.
public class DexItemBasedString extends DexString {
public final DexReference basedOn;
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 f2ecc89..ee160dc 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
@@ -36,7 +36,6 @@
@Override
public void buildDex(DexBuilder builder) {
- builder.registerStringReference(value);
int dest = builder.allocatedRegister(dest(), getNumber());
builder.add(this, new com.android.tools.r8.code.ConstString(dest, value));
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
index 1f7a684..4e11690 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
@@ -42,7 +42,6 @@
import com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair;
import com.android.tools.r8.graph.DexDebugEventBuilder;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -108,9 +107,6 @@
private int inRegisterCount = 0;
private int outRegisterCount = 0;
- // The string reference in the code with the highest index.
- private DexString highestSortingReferencedString = null;
-
// Whether or not the generated code has a backwards branch.
private boolean hasBackwardsBranch = false;
@@ -136,7 +132,6 @@
instructionToInfo = new Info[instructionNumberToIndex(ir.numberRemainingInstructions())];
inRegisterCount = 0;
outRegisterCount = 0;
- highestSortingReferencedString = null;
nextBlock = null;
}
@@ -258,15 +253,15 @@
TryInfo tryInfo = computeTryInfo();
// Return the dex code.
- DexCode code = new DexCode(
- registerAllocator.registersUsed(),
- inRegisterCount,
- outRegisterCount,
- dexInstructions.toArray(new Instruction[dexInstructions.size()]),
- tryInfo.tries,
- tryInfo.handlers,
- debugEventBuilder.build(),
- highestSortingReferencedString);
+ DexCode code =
+ new DexCode(
+ registerAllocator.registersUsed(),
+ inRegisterCount,
+ outRegisterCount,
+ dexInstructions.toArray(new Instruction[dexInstructions.size()]),
+ tryInfo.tries,
+ tryInfo.handlers,
+ debugEventBuilder.build());
return code;
}
@@ -399,13 +394,6 @@
ifsNeedingRewrite.add(block);
}
- public void registerStringReference(DexString string) {
- if (highestSortingReferencedString == null
- || string.slowCompareTo(highestSortingReferencedString) > 0) {
- highestSortingReferencedString = string;
- }
- }
-
public void requestOutgoingRegisters(int requiredRegisterCount) {
if (requiredRegisterCount > outRegisterCount) {
outRegisterCount = requiredRegisterCount;
diff --git a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
index 3b1e30a..e11b957 100644
--- a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
+++ b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
@@ -156,7 +156,6 @@
instructions,
new Try[0],
null,
- null,
null);
MethodAccessFlags flags = MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false);
DexEncodedMethod method = new DexEncodedMethod(null, flags, null, null, code);
diff --git a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
index a518a36..d672f75 100644
--- a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
+++ b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
@@ -78,8 +78,7 @@
instructions[i] = new ConstString(0, strings[startOffset + i]);
}
instructions[stringCount] = new ReturnVoid();
- DexCode code = new DexCode(1, 0, 0, instructions, new Try[0], new TryHandler[0], null,
- strings[startOffset + stringCount - 1]);
+ DexCode code = new DexCode(1, 0, 0, instructions, new Try[0], new TryHandler[0], null);
return new DexEncodedMethod(
dexItemFactory.createMethod(
holder, dexItemFactory.createProto(dexItemFactory.voidType), "theMethod"),