Ensure instruction iterators update IR metadata
Change-Id: Iecf7791970eb2e9d1565ae1c05d215c5a417ebff
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 59aae89..ec6710b 100644
--- a/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java
@@ -156,15 +156,14 @@
// locals alive for their entire live range. In release mode the liveness is all that matters
// and we do not actually want locals information in the output.
if (appView.options().debug) {
- LinearScanRegisterAllocator.computeDebugInfo(blocks, liveIntervals, this, liveAtEntrySets);
+ LinearScanRegisterAllocator.computeDebugInfo(
+ code, blocks, liveIntervals, this, liveAtEntrySets);
}
}
private void computeNeedsRegister() {
- InstructionIterator it = code.instructionIterator();
- while (it.hasNext()) {
- Instruction next = it.next();
- Value outValue = next.outValue();
+ for (Instruction instruction : code.instructions()) {
+ Value outValue = instruction.outValue();
if (outValue != null) {
boolean isStackValue =
(outValue instanceof StackValue) || (outValue instanceof StackValues);
@@ -505,10 +504,10 @@
private void applyInstructionsBackwardsToRegisterLiveness(
BasicBlock block, IntSet liveRegisters, int suffixSize) {
- Iterator<Instruction> iterator = block.getInstructions().descendingIterator();
+ InstructionIterator iterator = block.iterator(block.getInstructions().size());
int instructionsLeft = suffixSize;
- while (--instructionsLeft >= 0 && iterator.hasNext()) {
- Instruction current = iterator.next();
+ while (--instructionsLeft >= 0 && iterator.hasPrevious()) {
+ Instruction current = iterator.previous();
Value outValue = current.outValue();
if (outValue != null && outValue.needsRegister()) {
int register = getRegisterForValue(outValue);
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 70f5ade..339f961 100644
--- a/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java
@@ -99,7 +99,7 @@
clonableConstants = new IdentityHashMap<>();
blockIterator = code.listIterator();
while (blockIterator.hasNext()) {
- InstructionListIterator it = blockIterator.next().listIterator();
+ InstructionListIterator it = blockIterator.next().listIterator(code);
while (it.hasNext()) {
it.next().insertLoadAndStores(it, this);
}
@@ -128,7 +128,7 @@
moves.add(new PhiMove(phi, value));
}
}
- InstructionListIterator it = pred.listIterator(pred.getInstructions().size());
+ InstructionListIterator it = pred.listIterator(code, pred.getInstructions().size());
Instruction exit = it.previous();
assert pred.exit() == exit;
movePhis(moves, it, exit.getPosition());
@@ -201,7 +201,7 @@
boolean hasCatchHandlers = instruction.getBlock().hasCatchHandlers();
if (hasCatchHandlers && instruction.instructionTypeCanThrow()) {
storeBlock = it.split(this.code, this.blockIterator);
- it = storeBlock.listIterator();
+ it = storeBlock.listIterator(code);
}
add(store, storeBlock, instruction.getPosition(), it);
if (hasCatchHandlers && !instruction.instructionTypeCanThrow()) {
@@ -223,7 +223,7 @@
BasicBlock insertBlock = instruction.getBlock();
if (insertBlock.hasCatchHandlers() && instruction.instructionTypeCanThrow()) {
insertBlock = it.split(this.code, this.blockIterator);
- it = insertBlock.listIterator();
+ it = insertBlock.listIterator(code);
}
instruction.swapOutValue(newOutValue);
add(new Pop(newOutValue), insertBlock, instruction.getPosition(), it);
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
index 83ce19e..b8834e5 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ClassInitializationAnalysis.java
@@ -24,6 +24,7 @@
import com.android.tools.r8.ir.code.InstanceGet;
import com.android.tools.r8.ir.code.InstancePut;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeInterface;
import com.android.tools.r8.ir.code.InvokeStatic;
@@ -38,7 +39,6 @@
import com.google.common.collect.Streams;
import java.util.ArrayDeque;
import java.util.Deque;
-import java.util.Iterator;
import java.util.Set;
/**
@@ -119,7 +119,7 @@
// Visit all the instructions in all the blocks that dominate `block`.
for (BasicBlock dominator : dominatorTree.dominatorBlocks(block, Inclusive.NO)) {
AnalysisAssumption assumption = getAssumptionForDominator(dominator, block);
- Iterator<Instruction> instructionIterator = dominator.iterator();
+ InstructionIterator instructionIterator = dominator.iterator();
while (instructionIterator.hasNext()) {
Instruction previous = instructionIterator.next();
if (previous.definitelyTriggersClassInitialization(
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java b/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java
index 61ecf71..01a7e3d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/TypeChecker.java
@@ -14,7 +14,6 @@
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.InstancePut;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.Return;
import com.android.tools.r8.ir.code.StaticPut;
import com.android.tools.r8.ir.code.Throw;
@@ -38,9 +37,7 @@
}
public boolean check(IRCode code) {
- InstructionIterator instructionIterator = code.instructionIterator();
- while (instructionIterator.hasNext()) {
- Instruction instruction = instructionIterator.next();
+ for (Instruction instruction : code.instructions()) {
if (instruction.isInstancePut()) {
if (!check(instruction.asInstancePut())) {
return false;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java b/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java
index 775553b..79081ee 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java
@@ -80,36 +80,38 @@
List<BasicBlock> blockToAnalyze = new ArrayList<>();
mapping.entrySet().stream()
- .filter((entry) -> entry.getValue().isConst())
- .forEach((entry) -> {
- Value value = entry.getKey();
- ConstNumber evaluatedConst = entry.getValue().asConst().getConstNumber();
- if (value.definition != evaluatedConst) {
- if (value.isPhi()) {
- // D8 relies on dead code removal to get rid of the dead phi itself.
- if (value.numberOfAllUsers() != 0) {
- BasicBlock block = value.asPhi().getBlock();
- blockToAnalyze.add(block);
- // Create a new constant, because it can be an existing constant that flow directly
- // into the phi.
- ConstNumber newConst = ConstNumber.copyOf(code, evaluatedConst);
- InstructionListIterator iterator = block.listIterator();
- Instruction inst = iterator.nextUntil((i) -> !i.isMoveException());
- newConst.setPosition(inst.getPosition());
- if (!inst.isDebugPosition()) {
- iterator.previous();
+ .filter(entry -> entry.getValue().isConst())
+ .forEach(
+ entry -> {
+ Value value = entry.getKey();
+ ConstNumber evaluatedConst = entry.getValue().asConst().getConstNumber();
+ if (value.definition != evaluatedConst) {
+ if (value.isPhi()) {
+ // D8 relies on dead code removal to get rid of the dead phi itself.
+ if (value.numberOfAllUsers() != 0) {
+ BasicBlock block = value.asPhi().getBlock();
+ blockToAnalyze.add(block);
+ // Create a new constant, because it can be an existing constant that flow
+ // directly
+ // into the phi.
+ ConstNumber newConst = ConstNumber.copyOf(code, evaluatedConst);
+ InstructionListIterator iterator = block.listIterator(code);
+ Instruction inst = iterator.nextUntil(i -> !i.isMoveException());
+ newConst.setPosition(inst.getPosition());
+ if (!inst.isDebugPosition()) {
+ iterator.previous();
+ }
+ iterator.add(newConst);
+ value.replaceUsers(newConst.outValue());
+ }
+ } else {
+ BasicBlock block = value.definition.getBlock();
+ InstructionListIterator iterator = block.listIterator(code);
+ iterator.nextUntil(i -> i == value.definition);
+ iterator.replaceCurrentInstruction(evaluatedConst);
}
- iterator.add(newConst);
- value.replaceUsers(newConst.outValue());
}
- } else {
- BasicBlock block = value.definition.getBlock();
- InstructionListIterator iterator = block.listIterator();
- Instruction toReplace = iterator.nextUntil((i) -> i == value.definition);
- iterator.replaceCurrentInstruction(evaluatedConst);
- }
- }
- });
+ });
for (BasicBlock block : blockToAnalyze) {
block.deduplicatePhis();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
index 118ea7a..e447e7a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
@@ -121,7 +121,7 @@
infoValue.definition.replace(
new ConstString(
code.createValue(stringType), encoder.encodeInfo(protoMessageInfo), throwingInfo),
- code.metadata());
+ code);
}
private void rewriteObjectsArgumentToNewMessageInfo(
@@ -131,8 +131,7 @@
ProtoMessageInfo protoMessageInfo) {
// Position iterator immediately before the call to newMessageInfo().
BasicBlock block = newMessageInfoInvoke.getBlock();
- InstructionListIterator instructionIterator =
- block.listIterator(newMessageInfoInvoke).recordChangesToMetadata(code);
+ InstructionListIterator instructionIterator = block.listIterator(code, newMessageInfoInvoke);
Instruction previous = instructionIterator.previous();
instructionIterator.setInsertionPosition(newMessageInfoInvoke.getPosition());
assert previous == newMessageInfoInvoke;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java
index 90f6e25..ddc98e2 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java
@@ -22,7 +22,7 @@
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.DexItemBasedConstString;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.NewArrayEmpty;
import com.android.tools.r8.ir.code.StaticGet;
@@ -283,7 +283,7 @@
}
// Create an iterator for the block of interest.
- InstructionListIterator instructionIterator = newArrayEmpty.getBlock().listIterator();
+ InstructionIterator instructionIterator = newArrayEmpty.getBlock().iterator();
instructionIterator.nextUntil(instruction -> instruction == newArrayEmpty);
return new ThrowingIterator<Value, InvalidRawMessageInfoException>() {
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index b018ce7..cf29fdc 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -93,8 +93,8 @@
return localsAtEntry;
}
- public void replaceLastInstruction(Instruction instruction) {
- InstructionListIterator iterator = listIterator(getInstructions().size());
+ public void replaceLastInstruction(Instruction instruction, IRCode code) {
+ InstructionListIterator iterator = listIterator(code, getInstructions().size());
iterator.previous();
iterator.replaceCurrentInstruction(instruction);
}
@@ -562,6 +562,10 @@
return instructions;
}
+ public Iterable<Instruction> instructionsAfter(Instruction instruction) {
+ return () -> iterator(instruction);
+ }
+
public boolean isEmpty() {
return instructions.isEmpty();
}
@@ -578,7 +582,7 @@
public Instruction exceptionalExit() {
assert hasCatchHandlers();
- ListIterator<Instruction> it = listIterator(instructions.size());
+ InstructionIterator it = iterator(instructions.size());
while (it.hasPrevious()) {
Instruction instruction = it.previous();
if (instruction.instructionTypeCanThrow()) {
@@ -1321,7 +1325,7 @@
*
* @param blockNumber the block number of the block
* @param theIf the if instruction
- * @param instruction the instruction to place before the if instruction
+ * @param instructions the instructions to place before the if instruction
*/
public static BasicBlock createIfBlock(int blockNumber, If theIf, Instruction... instructions) {
BasicBlock block = new BasicBlock();
@@ -1494,7 +1498,7 @@
// visible to exceptional successors.
private boolean verifyNoValuesAfterThrowingInstruction() {
if (hasCatchHandlers()) {
- ListIterator<Instruction> iterator = listIterator(instructions.size());
+ InstructionIterator iterator = iterator(instructions.size());
while (iterator.hasPrevious()) {
Instruction instruction = iterator.previous();
if (instruction.instructionTypeCanThrow()) {
@@ -1507,26 +1511,38 @@
}
public InstructionIterator iterator() {
- return new BasicBlockInstructionListIterator(this);
+ return new BasicBlockInstructionIterator(this);
}
- public InstructionListIterator listIterator() {
- return new BasicBlockInstructionListIterator(this);
+ public InstructionIterator iterator(int index) {
+ return new BasicBlockInstructionIterator(this, index);
}
- public InstructionListIterator listIterator(int index) {
- return new BasicBlockInstructionListIterator(this, index);
+ public InstructionIterator iterator(Instruction instruction) {
+ return new BasicBlockInstructionIterator(this, instruction);
+ }
+
+ public InstructionListIterator listIterator(IRCode code) {
+ return listIterator(code.metadata());
+ }
+
+ public InstructionListIterator listIterator(IRMetadata metadata) {
+ return new BasicBlockInstructionListIterator(metadata, this);
+ }
+
+ public InstructionListIterator listIterator(IRCode code, int index) {
+ return new BasicBlockInstructionListIterator(code.metadata(), this, index);
}
/**
* Creates an instruction list iterator starting at <code>instruction</code>.
*
- * The cursor will be positioned after <code>instruction</code>. Calling <code>next</code> on
+ * <p>The cursor will be positioned after <code>instruction</code>. Calling <code>next</code> on
* the returned iterator will return the instruction after <code>instruction</code>. Calling
* <code>previous</code> will return <code>instruction</code>.
*/
- public InstructionListIterator listIterator(Instruction instruction) {
- return new BasicBlockInstructionListIterator(this, instruction);
+ public InstructionListIterator listIterator(IRCode code, Instruction instruction) {
+ return new BasicBlockInstructionListIterator(code.metadata(), this, instruction);
}
/**
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
new file mode 100644
index 0000000..f0771c3
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, 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.ir.code;
+
+import java.util.ListIterator;
+
+public class BasicBlockInstructionIterator implements InstructionIterator {
+
+ private final ListIterator<Instruction> instructionIterator;
+
+ BasicBlockInstructionIterator(BasicBlock block) {
+ this.instructionIterator = block.getInstructions().listIterator();
+ }
+
+ BasicBlockInstructionIterator(BasicBlock block, int index) {
+ this.instructionIterator = block.getInstructions().listIterator(index);
+ }
+
+ BasicBlockInstructionIterator(BasicBlock block, Instruction instruction) {
+ this(block);
+ nextUntil(x -> x == instruction);
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return instructionIterator.hasPrevious();
+ }
+
+ @Override
+ public Instruction previous() {
+ return instructionIterator.previous();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return instructionIterator.hasNext();
+ }
+
+ @Override
+ public Instruction next() {
+ return instructionIterator.next();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
index f0ed3fc..90c1569 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java
@@ -21,7 +21,6 @@
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
@@ -33,27 +32,24 @@
protected Instruction current;
protected Position position = null;
- private IRMetadata metadata;
+ private final IRMetadata metadata;
- BasicBlockInstructionListIterator(BasicBlock block) {
+ BasicBlockInstructionListIterator(IRMetadata metadata, BasicBlock block) {
this.block = block;
this.listIterator = block.getInstructions().listIterator();
+ this.metadata = metadata;
}
- BasicBlockInstructionListIterator(BasicBlock block, int index) {
+ BasicBlockInstructionListIterator(IRMetadata metadata, BasicBlock block, int index) {
this.block = block;
this.listIterator = block.getInstructions().listIterator(index);
- }
-
- BasicBlockInstructionListIterator(BasicBlock block, Instruction instruction) {
- this(block);
- nextUntil((x) -> x == instruction);
- }
-
- @Override
- public BasicBlockInstructionListIterator recordChangesToMetadata(IRMetadata metadata) {
this.metadata = metadata;
- return this;
+ }
+
+ BasicBlockInstructionListIterator(
+ IRMetadata metadata, BasicBlock block, Instruction instruction) {
+ this(metadata, block);
+ nextUntil(x -> x == instruction);
}
@Override
@@ -94,10 +90,10 @@
}
/**
- * Adds an instruction to the block. The instruction will be added just before the current
- * cursor position.
+ * Adds an instruction to the block. The instruction will be added just before the current cursor
+ * position.
*
- * The instruction will be assigned to the block it is added to.
+ * <p>The instruction will be assigned to the block it is added to.
*
* @param instruction The instruction to add.
*/
@@ -109,16 +105,14 @@
instruction.setPosition(position);
}
listIterator.add(instruction);
- if (metadata != null) {
- metadata.record(instruction);
- }
+ metadata.record(instruction);
}
/**
- * Replaces the last instruction returned by {@link #next} or {@link #previous} with the
- * specified instruction.
+ * Replaces the last instruction returned by {@link #next} or {@link #previous} with the specified
+ * instruction.
*
- * The instruction will be assigned to the block it is added to.
+ * <p>The instruction will be assigned to the block it is added to.
*
* @param instruction The instruction to replace with.
*/
@@ -133,10 +127,10 @@
* Remove the current instruction (aka the {@link Instruction} returned by the previous call to
* {@link #next}.
*
- * The current instruction will be completely detached from the instruction stream with uses
- * of its in-values removed.
+ * <p>The current instruction will be completely detached from the instruction stream with uses of
+ * its in-values removed.
*
- * If the current instruction produces an out-value this out value must not have any users.
+ * <p>If the current instruction produces an out-value this out value must not have any users.
*/
@Override
public void remove() {
@@ -164,6 +158,15 @@
}
@Override
+ public void removeInstructionIgnoreOutValue() {
+ if (current == null) {
+ throw new IllegalStateException();
+ }
+ listIterator.remove();
+ current = null;
+ }
+
+ @Override
public void removeOrReplaceByDebugLocalRead() {
if (current == null) {
throw new IllegalStateException();
@@ -193,9 +196,7 @@
listIterator.remove();
listIterator.add(newInstruction);
current.clearBlock();
- if (metadata != null) {
- metadata.record(newInstruction);
- }
+ metadata.record(newInstruction);
}
@Override
@@ -327,7 +328,7 @@
BasicBlock newBlock = split(code, blocksIterator);
assert blocksIterator == null || IteratorUtils.peekPrevious(blocksIterator) == newBlock;
// Skip the requested number of instructions and split again.
- InstructionListIterator iterator = newBlock.listIterator();
+ InstructionListIterator iterator = newBlock.listIterator(code);
for (int i = 0; i < instructions; i++) {
iterator.next();
}
@@ -337,7 +338,7 @@
}
private boolean canThrow(IRCode code) {
- Iterator<Instruction> iterator = code.instructionIterator();
+ InstructionIterator iterator = code.instructionIterator();
while (iterator.hasNext()) {
boolean throwing = iterator.next().instructionTypeCanThrow();
if (throwing) {
@@ -357,7 +358,7 @@
// one throwing instruction in each block.
// NOTE: This iterator is replaced in the loop below, so that the iteration continues in
// the new block after the iterated block is split.
- InstructionListIterator instructionsIterator = inlinedBlock.listIterator();
+ InstructionListIterator instructionsIterator = inlinedBlock.listIterator(code);
BasicBlock currentBlock = inlinedBlock;
while (currentBlock != null && instructionsIterator.hasNext()) {
assert !currentBlock.hasCatchHandlers();
@@ -383,7 +384,7 @@
BasicBlock b = blocksIterator.next();
assert b == nextBlock;
// Switch iteration to the split block.
- instructionsIterator = nextBlock.listIterator();
+ instructionsIterator = nextBlock.listIterator(code);
} else {
instructionsIterator = null;
}
@@ -497,15 +498,15 @@
// the inlinee (by the call to appendCatchHandlers() later in this method), so we don't
// need to do anything about that here.
BasicBlock inlineEntry = entryBlock;
- entryBlock = entryBlock.listIterator().split(inlinee);
- entryBlockIterator = entryBlock.listIterator();
+ entryBlock = entryBlock.listIterator(code).split(inlinee);
+ entryBlockIterator = entryBlock.listIterator(code);
// Insert cast instruction into the new block.
inlineEntry.getInstructions().addFirst(castInstruction);
castInstruction.setBlock(inlineEntry);
assert castInstruction.getBlock().getInstructions().size() == 2;
} else {
castInstruction.setBlock(entryBlock);
- entryBlockIterator = entryBlock.listIterator();
+ entryBlockIterator = entryBlock.listIterator(code);
entryBlockIterator.add(castInstruction);
}
@@ -516,7 +517,7 @@
removeArgumentInstruction(entryBlockIterator, argument);
i++;
} else {
- entryBlockIterator = entryBlock.listIterator();
+ entryBlockIterator = entryBlock.listIterator(code);
}
// Map the remaining argument values.
@@ -560,16 +561,16 @@
// Split before return and unlink return.
BasicBlock returnBlock = inlineeIterator.split(inlinee);
inlineExit = returnBlock.unlinkSinglePredecessor();
- InstructionListIterator returnBlockIterator = returnBlock.listIterator();
+ InstructionListIterator returnBlockIterator = returnBlock.listIterator(code);
returnBlockIterator.next();
- returnBlockIterator.remove(); // This clears out the users from the return.
+ returnBlockIterator.remove(); // This clears out the users from the return.
assert !returnBlockIterator.hasNext();
inlinee.blocks.remove(returnBlock);
// Leaving the invoke block in the graph as an empty block. Still unlink its predecessor as
// the exit block of the inlinee will become its new predecessor.
invokeBlock.unlinkSinglePredecessor();
- InstructionListIterator invokeBlockIterator = invokeBlock.listIterator();
+ InstructionListIterator invokeBlockIterator = invokeBlock.listIterator(code);
invokeBlockIterator.next();
invokeBlockIterator.remove();
invokeSuccessor = invokeBlock;
@@ -633,7 +634,7 @@
private InstructionListIterator ensureSingleReturnInstruction(
AppView<?> appView, IRCode code, List<BasicBlock> normalExits) {
if (normalExits.size() == 1) {
- InstructionListIterator it = normalExits.get(0).listIterator();
+ InstructionListIterator it = normalExits.get(0).listIterator(code);
it.nextUntil(Instruction::isReturn);
it.previous();
return it;
@@ -673,7 +674,7 @@
newReturn.setPosition(Position.none());
newExitBlock.add(newReturn);
for (BasicBlock exitBlock : normalExits) {
- InstructionListIterator it = exitBlock.listIterator(exitBlock.getInstructions().size());
+ InstructionListIterator it = exitBlock.listIterator(code, exitBlock.getInstructions().size());
Instruction oldExit = it.previous();
assert oldExit.isReturn();
it.replaceCurrentInstruction(new Goto());
@@ -682,6 +683,6 @@
newExitBlock.close(null);
code.blocks.add(newExitBlock);
assert code.isConsistentSSA();
- return newExitBlock.listIterator();
+ return newExitBlock.listIterator(code);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockIterator.java
index 26305b7..d9fc837 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockIterator.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.ir.code;
-import java.util.Iterator;
import java.util.ListIterator;
public class BasicBlockIterator implements ListIterator<BasicBlock> {
@@ -79,7 +78,7 @@
throw new IllegalStateException();
}
// Remove all instructions from the block before removing the block.
- Iterator<Instruction> iterator = current.iterator();
+ InstructionListIterator iterator = current.listIterator(code);
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
instruction.clearDebugValues();
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index bc53af5..9198796 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -31,7 +31,6 @@
import java.util.Deque;
import java.util.HashSet;
import java.util.IdentityHashMap;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
@@ -198,9 +197,9 @@
// normal successor.
assert liveStack.isEmpty()
|| block.getSuccessors().size() - exceptionalSuccessors.size() == 1;
- Iterator<Instruction> iterator = block.getInstructions().descendingIterator();
- while (iterator.hasNext()) {
- Instruction instruction = iterator.next();
+ InstructionIterator iterator = block.listIterator(this, block.getInstructions().size());
+ while (iterator.hasPrevious()) {
+ Instruction instruction = iterator.previous();
Value outValue = instruction.outValue();
if (outValue != null) {
if (outValue instanceof StackValue) {
@@ -703,7 +702,7 @@
private boolean consistentBlockInstructions() {
boolean argumentsAllowed = true;
for (BasicBlock block : blocks) {
- block.consistentBlockInstructions(
+ assert block.consistentBlockInstructions(
argumentsAllowed,
options.debug || method.getOptimizationInfo().isReachabilitySensitive());
argumentsAllowed = false;
@@ -823,6 +822,10 @@
}
public InstructionIterator instructionIterator() {
+ return new IRCodeInstructionIterator(this);
+ }
+
+ public InstructionListIterator instructionListIterator() {
return new IRCodeInstructionListIterator(this);
}
@@ -853,11 +856,9 @@
}
public int numberRemainingInstructions() {
- InstructionIterator it = instructionIterator();
- while (it.hasNext()) {
- Instruction i = it.next();
- if (i.getNumber() == -1) {
- i.setNumber(nextInstructionNumber);
+ for (Instruction instruction : instructions()) {
+ if (instruction.getNumber() == -1) {
+ instruction.setNumber(nextInstructionNumber);
nextInstructionNumber += INSTRUCTION_NUMBER_DELTA;
}
}
@@ -874,7 +875,7 @@
public List<Value> collectArguments(boolean ignoreReceiver) {
final List<Value> arguments = new ArrayList<>();
- Iterator<Instruction> iterator = entryBlock().iterator();
+ InstructionIterator iterator = entryBlock().iterator();
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
if (instruction.isArgument()) {
@@ -893,7 +894,7 @@
if (method.accessFlags.isStatic()) {
return null;
}
- Instruction firstArg = entryBlock().listIterator().nextUntil(Instruction::isArgument);
+ Instruction firstArg = entryBlock().iterator().nextUntil(Instruction::isArgument);
assert firstArg != null;
Value thisValue = firstArg.asArgument().outValue();
assert thisValue.isThis();
@@ -942,9 +943,7 @@
}
private boolean computeAllThrowingInstructionsHavePositions() {
- InstructionIterator it = instructionIterator();
- while (it.hasNext()) {
- Instruction instruction = it.next();
+ for (Instruction instruction : instructions()) {
if (instruction.instructionTypeCanThrow()
&& !instruction.isConstString()
&& !instruction.isDexItemBasedConstString()
@@ -1029,7 +1028,7 @@
}
return result;
} else {
- Iterable<Instruction> result = () -> source.listIterator(instruction);
+ Iterable<Instruction> result = () -> source.iterator(instruction);
for (BasicBlock block : blocksReachableFromSource) {
result = Iterables.concat(result, block.getInstructions());
}
@@ -1129,7 +1128,7 @@
public Position findFirstNonNonePosition() {
Instruction rightAfterArguments =
- entryBlock().listIterator().nextUntil(instr -> !instr.isArgument());
+ entryBlock().iterator().nextUntil(instr -> !instr.isArgument());
Position firstNonArgumentPosition = rightAfterArguments.getPosition();
Set<BasicBlock> visitedBlocks = new HashSet<>();
while (rightAfterArguments != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionIterator.java b/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionIterator.java
new file mode 100644
index 0000000..4f131a0
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionIterator.java
@@ -0,0 +1,59 @@
+// Copyright (c) 2019, 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.ir.code;
+
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+public class IRCodeInstructionIterator implements InstructionIterator {
+
+ private final ListIterator<BasicBlock> blockIterator;
+ private InstructionListIterator instructionIterator;
+
+ private final IRCode code;
+
+ public IRCodeInstructionIterator(IRCode code) {
+ this.blockIterator = code.listIterator();
+ this.code = code;
+ this.instructionIterator = blockIterator.next().listIterator(code);
+ }
+
+ @Override
+ public boolean hasNext() {
+ return instructionIterator.hasNext() || blockIterator.hasNext();
+ }
+
+ @Override
+ public Instruction next() {
+ if (instructionIterator.hasNext()) {
+ return instructionIterator.next();
+ }
+ if (!blockIterator.hasNext()) {
+ throw new NoSuchElementException();
+ }
+ instructionIterator = blockIterator.next().listIterator(code);
+ assert instructionIterator.hasNext();
+ return instructionIterator.next();
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return instructionIterator.hasPrevious() || blockIterator.hasPrevious();
+ }
+
+ @Override
+ public Instruction previous() {
+ if (instructionIterator.hasPrevious()) {
+ return instructionIterator.previous();
+ }
+ if (!blockIterator.hasPrevious()) {
+ throw new NoSuchElementException();
+ }
+ BasicBlock block = blockIterator.previous();
+ instructionIterator = block.listIterator(code, block.getInstructions().size());
+ assert instructionIterator.hasPrevious();
+ return instructionIterator.previous();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java
index c7f8414..60e06c6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java
@@ -18,11 +18,12 @@
private final ListIterator<BasicBlock> blockIterator;
private InstructionListIterator instructionIterator;
- private IRMetadata metadata;
+ private final IRCode code;
public IRCodeInstructionListIterator(IRCode code) {
- blockIterator = code.listIterator();
- instructionIterator = blockIterator.next().listIterator();
+ this.blockIterator = code.listIterator();
+ this.code = code;
+ this.instructionIterator = blockIterator.next().listIterator(code);
}
@Override
@@ -67,12 +68,6 @@
}
@Override
- public IRCodeInstructionListIterator recordChangesToMetadata(IRMetadata metadata) {
- this.metadata = metadata;
- return this;
- }
-
- @Override
public boolean hasNext() {
return instructionIterator.hasNext() || blockIterator.hasNext();
}
@@ -85,7 +80,7 @@
if (!blockIterator.hasNext()) {
throw new NoSuchElementException();
}
- instructionIterator = blockIterator.next().listIterator();
+ instructionIterator = blockIterator.next().listIterator(code);
assert instructionIterator.hasNext();
return instructionIterator.next();
}
@@ -104,7 +99,7 @@
throw new NoSuchElementException();
}
BasicBlock block = blockIterator.previous();
- instructionIterator = block.listIterator(block.getInstructions().size());
+ instructionIterator = block.listIterator(code, block.getInstructions().size());
assert instructionIterator.hasPrevious();
return instructionIterator.previous();
}
@@ -122,9 +117,6 @@
@Override
public void add(Instruction instruction) {
instructionIterator.add(instruction);
- if (metadata != null) {
- metadata.record(instruction);
- }
}
@Override
@@ -135,17 +127,11 @@
@Override
public void set(Instruction instruction) {
instructionIterator.set(instruction);
- if (metadata != null) {
- metadata.record(instruction);
- }
}
@Override
public void replaceCurrentInstruction(Instruction newInstruction) {
instructionIterator.replaceCurrentInstruction(newInstruction);
- if (metadata != null) {
- metadata.record(newInstruction);
- }
}
@Override
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 e9de61e..33309d2 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
@@ -270,15 +270,12 @@
block = null;
}
- public void removeOrReplaceByDebugLocalRead() {
- getBlock().listIterator(this).removeOrReplaceByDebugLocalRead();
+ public void removeOrReplaceByDebugLocalRead(IRCode code) {
+ getBlock().listIterator(code, this).removeOrReplaceByDebugLocalRead();
}
- public void replace(Instruction newInstruction, IRMetadata metadata) {
- getBlock()
- .listIterator(this)
- .recordChangesToMetadata(metadata)
- .replaceCurrentInstruction(newInstruction);
+ public void replace(Instruction newInstruction, IRCode code) {
+ getBlock().listIterator(code, this).replaceCurrentInstruction(newInstruction);
}
/**
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstructionIterator.java b/src/main/java/com/android/tools/r8/ir/code/InstructionIterator.java
index d957147..539f0d7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstructionIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstructionIterator.java
@@ -4,42 +4,48 @@
package com.android.tools.r8.ir.code;
-import com.android.tools.r8.errors.Unreachable;
-import java.util.ListIterator;
+import java.util.Iterator;
-public interface InstructionIterator
- extends ListIterator<Instruction>, NextUntilIterator<Instruction> {
+public interface InstructionIterator extends Iterator<Instruction>, NextUntilIterator<Instruction> {
- default InstructionIterator recordChangesToMetadata(IRCode code) {
- return recordChangesToMetadata(code.metadata());
+ /** @deprecated Use {@link InstructionListIterator#remove()} instead. */
+ @Deprecated
+ @Override
+ default void remove() {
+ throw new UnsupportedOperationException("remove");
}
- default InstructionIterator recordChangesToMetadata(IRMetadata metadata) {
- throw new Unreachable(
- "Method recordChangesToMetadata(IRMetadata) not implemented for "
- + getClass().getTypeName());
- }
+ boolean hasPrevious();
+
+ Instruction previous();
+
/**
- * Replace the current instruction (aka the {@link Instruction} returned by the previous call to
- * {@link #next} with the passed in <code>newInstruction</code>.
- * <p>
- * The current instruction will be completely detached from the instruction stream with uses
- * of its in-values removed.
- * <p>
- * If the current instruction produces an out-value the new instruction must also produce
- * an out-value, and all uses of the current instructions out-value will be replaced by the
- * new instructions out-value.
- * <p>
- * The debug information of the current instruction will be attached to the new instruction.
+ * Peek the next instruction.
*
- * @param newInstruction the instruction to insert instead of the current.
+ * @return what will be returned by calling {@link #next}. If there is no next instruction <code>
+ * null</code> is returned.
*/
- void replaceCurrentInstruction(Instruction newInstruction);
-
+ default Instruction peekNext() {
+ Instruction next = null;
+ if (hasNext()) {
+ next = next();
+ previous();
+ }
+ return next;
+ }
/**
- * Safe removal function that will insert a DebugLocalRead to take over the debug values if any
- * are associated with the current instruction.
+ * Peek the previous instruction.
+ *
+ * @return what will be returned by calling {@link #previous}. If there is no previous instruction
+ * <code>null</code> is returned.
*/
- void removeOrReplaceByDebugLocalRead();
+ default Instruction peekPrevious() {
+ Instruction previous = null;
+ if (hasPrevious()) {
+ previous = previous();
+ next();
+ }
+ return previous;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java
index 773bc13..f4ff24a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.ir.code;
-import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexType;
@@ -14,49 +14,40 @@
import java.util.Set;
public interface InstructionListIterator
- extends InstructionIterator, PreviousUntilIterator<Instruction> {
+ extends InstructionIterator, ListIterator<Instruction>, PreviousUntilIterator<Instruction> {
/**
- * Peek the previous instruction.
+ * Replace the current instruction (aka the {@link Instruction} returned by the previous call to
+ * {@link #next} with the passed in <code>newInstruction</code>.
*
- * @return what will be returned by calling {@link #previous}. If there is no previous instruction
- * <code>null</code> is returned.
+ * <p>The current instruction will be completely detached from the instruction stream with uses of
+ * its in-values removed.
+ *
+ * <p>If the current instruction produces an out-value the new instruction must also produce an
+ * out-value, and all uses of the current instructions out-value will be replaced by the new
+ * instructions out-value.
+ *
+ * <p>The debug information of the current instruction will be attached to the new instruction.
+ *
+ * @param newInstruction the instruction to insert instead of the current.
*/
- default Instruction peekPrevious() {
- Instruction previous = null;
- if (hasPrevious()) {
- previous = previous();
- next();
- }
- return previous;
+ void replaceCurrentInstruction(Instruction newInstruction);
+
+ // Do not show a deprecation warning for InstructionListIterator.remove().
+ @SuppressWarnings("deprecation")
+ @Override
+ void remove();
+
+ // Removes the current instruction, even if it has an out-value that is used.
+ default void removeInstructionIgnoreOutValue() {
+ throw new Unimplemented();
}
/**
- * Peek the next instruction.
- *
- * @return what will be returned by calling {@link #next}. If there is no next instruction
- * <code>null</code> is returned.
+ * Safe removal function that will insert a DebugLocalRead to take over the debug values if any
+ * are associated with the current instruction.
*/
- default Instruction peekNext() {
- Instruction next = null;
- if (hasNext()) {
- next = next();
- previous();
- }
- return next;
- }
-
- @Override
- default InstructionListIterator recordChangesToMetadata(IRCode code) {
- return recordChangesToMetadata(code.metadata());
- }
-
- @Override
- default InstructionListIterator recordChangesToMetadata(IRMetadata metadata) {
- throw new Unreachable(
- "Method recordChangesToMetadata(IRMetadata) not implemented for "
- + getClass().getTypeName());
- }
+ void removeOrReplaceByDebugLocalRead();
default void setInsertionPosition(Position position) {
// Intentionally empty.
diff --git a/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionIterator.java b/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java
similarity index 90%
rename from src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionIterator.java
rename to src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java
index c14da47..2c76690 100644
--- a/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java
@@ -11,18 +11,21 @@
import java.util.ListIterator;
import java.util.Set;
-public class LinearFlowInstructionIterator implements InstructionIterator, InstructionListIterator {
+public class LinearFlowInstructionListIterator implements InstructionListIterator {
+
+ private final IRCode code;
private BasicBlock currentBlock;
private InstructionListIterator currentBlockIterator;
- public LinearFlowInstructionIterator(BasicBlock block) {
- this(block, 0);
+ public LinearFlowInstructionListIterator(IRCode code, BasicBlock block) {
+ this(code, block, 0);
}
- public LinearFlowInstructionIterator(BasicBlock block, int index) {
+ public LinearFlowInstructionListIterator(IRCode code, BasicBlock block, int index) {
+ this.code = code;
this.currentBlock = block;
- this.currentBlockIterator = block.listIterator(index);
+ this.currentBlockIterator = block.listIterator(code, index);
// If index is pointing after the last instruction, and it is a goto with a linear edge,
// we have to move the pointer. This is achieved by calling previous and next.
if (index > 0) {
@@ -119,7 +122,7 @@
target = candidate;
}
currentBlock = target;
- currentBlockIterator = currentBlock.listIterator();
+ currentBlockIterator = currentBlock.listIterator(code);
return currentBlockIterator.next();
}
@@ -156,7 +159,7 @@
return currentBlockIterator.previous();
}
currentBlock = target;
- currentBlockIterator = currentBlock.listIterator(currentBlock.getInstructions().size());
+ currentBlockIterator = currentBlock.listIterator(code, currentBlock.getInstructions().size());
// Iterate over the jump.
currentBlockIterator.previous();
return currentBlockIterator.previous();
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index 591df9e..3208833 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -856,9 +856,7 @@
// creation.
Set<Instruction> consumedInstructions = Sets.newIdentityHashSet();
- InstructionListIterator instructionIterator = definition.getBlock().listIterator(definition);
- while (instructionIterator.hasNext()) {
- Instruction instruction = instructionIterator.next();
+ for (Instruction instruction : definition.getBlock().instructionsAfter(definition)) {
if (instruction.isArrayPut()) {
ArrayPut arrayPut = instruction.asArrayPut();
Value array = arrayPut.array().getAliasedValue();
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 7d6bfb0..db2d7bb 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
@@ -36,7 +36,6 @@
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Inc;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.JumpInstruction;
@@ -221,7 +220,7 @@
private void rewriteNots() {
for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction current = it.next();
if (!current.isNot()) {
@@ -357,7 +356,7 @@
private void rewriteIincPatterns() {
for (BasicBlock block : code.blocks) {
- ListIterator<Instruction> it = block.getInstructions().listIterator();
+ InstructionListIterator it = block.listIterator(code);
// Test that we have enough instructions for iinc.
while (IINC_PATTERN_SIZE <= block.getInstructions().size() - it.nextIndex()) {
Instruction loadOrConst1 = it.next();
@@ -403,11 +402,11 @@
|| position != store.getPosition()) {
continue;
}
- it.remove();
+ it.removeInstructionIgnoreOutValue();
it.next();
- it.remove();
+ it.removeInstructionIgnoreOutValue();
it.next();
- it.remove();
+ it.removeInstructionIgnoreOutValue();
it.next();
Inc inc = new Inc(store.outValue(), load.inValues().get(0), increment);
inc.setPosition(position);
@@ -430,9 +429,7 @@
pendingFrame = null;
}
}
- InstructionIterator it = block.iterator();
- while (it.hasNext()) {
- Instruction instruction = it.next();
+ for (Instruction instruction : block.getInstructions()) {
if (fallthrough && instruction.isGoto()) {
assert block.exit() == instruction;
return;
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 ba9a714..75c2a15 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
@@ -50,6 +50,7 @@
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.IntSwitch;
import com.android.tools.r8.ir.code.JumpInstruction;
import com.android.tools.r8.ir.code.Move;
@@ -203,9 +204,8 @@
// Compute offsets.
offset = 0;
- InstructionIterator it = ir.instructionIterator();
- while (it.hasNext()) {
- Info info = getInfo(it.next());
+ for (com.android.tools.r8.ir.code.Instruction instruction : ir.instructions()) {
+ Info info = getInfo(instruction);
info.setOffset(offset);
offset += info.computeSize(this);
++numberOfInstructions;
@@ -216,19 +216,17 @@
DexDebugEventBuilder debugEventBuilder = new DexDebugEventBuilder(ir, options);
List<Instruction> dexInstructions = new ArrayList<>(numberOfInstructions);
int instructionOffset = 0;
- InstructionIterator instructionIterator = ir.instructionIterator();
- while (instructionIterator.hasNext()) {
- com.android.tools.r8.ir.code.Instruction ir = instructionIterator.next();
- Info info = getInfo(ir);
+ for (com.android.tools.r8.ir.code.Instruction irInstruction : ir.instructions()) {
+ Info info = getInfo(irInstruction);
int previousInstructionCount = dexInstructions.size();
info.addInstructions(this, dexInstructions);
int instructionStartOffset = instructionOffset;
while (previousInstructionCount < dexInstructions.size()) {
- Instruction instruction = dexInstructions.get(previousInstructionCount++);
- instruction.setOffset(instructionOffset);
- instructionOffset += instruction.getSize();
+ Instruction dexInstruction = dexInstructions.get(previousInstructionCount++);
+ dexInstruction.setOffset(instructionOffset);
+ instructionOffset += dexInstruction.getSize();
}
- debugEventBuilder.add(instructionStartOffset, instructionOffset, ir);
+ debugEventBuilder.add(instructionStartOffset, instructionOffset, irInstruction);
}
// Workaround dalvik tracing bug, where the dalvik tracing JIT can end up tracing
@@ -397,9 +395,7 @@
BasicBlock nextBlock =
blockIndex + 1 < code.blocks.size() ? code.blocks.get(blockIndex + 1) : null;
- InstructionIterator iterator = currentBlock.iterator();
- while (iterator.hasNext()) {
- com.android.tools.r8.ir.code.Instruction instruction = iterator.next();
+ for (com.android.tools.r8.ir.code.Instruction instruction : currentBlock.getInstructions()) {
if (instruction.isDebugPosition()) {
if (unresolvedPosition == null
&& currentMaterializedPosition == instruction.getPosition()) {
@@ -444,7 +440,7 @@
}
// Remove all unneeded positions.
if (!toRemove.isEmpty()) {
- InstructionIterator it = code.instructionIterator();
+ InstructionListIterator it = code.instructionListIterator();
int i = 0;
while (it.hasNext() && i < toRemove.size()) {
if (it.next() == toRemove.get(i)) {
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 cf72ee6..04bcfa8 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
@@ -414,9 +414,10 @@
// Flag indicating if any values have imprecise types.
private boolean hasImpreciseValues = false;
- // Flag indicating if a const string is ever loaded.
-
- // Flag indicating if the code has a monitor instruction.
+ // Information about which kinds of instructions that may be present in the IR. This information
+ // is sound (i.e., if the IR has a const-string instruction then metadata.mayHaveConstString()
+ // returns true) but not necessarily complete (i.e., if metadata.mayHaveConstString() returns true
+ // then the IR does not necessarily contain a const-string instruction).
private final IRMetadata metadata = new IRMetadata();
public IRBuilder(DexEncodedMethod method, AppView<?> appView, SourceCode source, Origin origin) {
@@ -558,7 +559,7 @@
// Insert definitions for all uninitialized local values.
if (uninitializedDebugLocalValues != null) {
Position position = entryBlock.getPosition();
- InstructionListIterator it = entryBlock.listIterator();
+ InstructionListIterator it = entryBlock.listIterator(metadata);
it.nextUntil(i -> !i.isArgument());
it.previous();
for (List<Value> values : uninitializedDebugLocalValues.values()) {
@@ -633,7 +634,7 @@
return;
}
for (BasicBlock block : blocks) {
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(metadata);
Position current = null;
while (it.hasNext()) {
Instruction instruction = it.next();
@@ -646,7 +647,6 @@
it.removeOrReplaceByDebugLocalRead();
} else {
current = position;
- metadata.record(instruction);
}
} else if (position.isSome() && !position.synthetic && !position.equals(current)) {
DebugPosition positionChange = new DebugPosition();
@@ -655,7 +655,6 @@
it.add(positionChange);
it.next();
current = position;
- metadata.record(positionChange);
}
}
}
@@ -823,7 +822,6 @@
public void add(Instruction ir) {
assert !ir.isJumpInstruction();
addInstruction(ir);
- metadata.record(ir);
}
private RemovedArgumentInfo getRemovedArgumentInfo() {
@@ -2210,6 +2208,7 @@
// Private instruction helpers.
private void addInstruction(Instruction ir) {
addInstruction(ir, source.getCurrentPosition());
+ metadata.record(ir);
}
private void addInstruction(Instruction ir, Position position) {
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 3c66edf..eabba6f 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
@@ -1587,7 +1587,7 @@
// Only if the constructor contains a super constructor call taking only parameters as
// inputs.
for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
Instruction superConstructorCall = it.nextUntil((i) ->
i.isInvokeDirect() &&
i.asInvokeDirect().getInvokedMethod().name == options.itemFactory.constructorMethodName &&
@@ -1630,7 +1630,7 @@
factory.intDescriptor,
new DexString[] {factory.longDescriptor}));
for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
Instruction firstMaterializing = it.nextUntil(IRConverter::isNotPseudoInstruction);
if (!isLongMul(firstMaterializing)) {
continue;
@@ -1645,7 +1645,7 @@
Value outOfMul = firstMaterializing.outValue();
for (Value inOfAddOrSub : secondMaterializing.inValues()) {
if (isAliasOf(inOfAddOrSub, outOfMul)) {
- it = block.listIterator();
+ it = block.listIterator(code);
it.nextUntil(i -> i == firstMaterializing);
Value longValue = firstMaterializing.inValues().get(0);
InvokeStatic invokeLongSignum =
@@ -1707,7 +1707,7 @@
BasicBlock split = it.split(code);
assert split.hasCatchHandlers();
assert !block.hasCatchHandlers();
- it = block.listIterator(block.getInstructions().size() - 1);
+ it = block.listIterator(code, block.getInstructions().size() - 1);
}
instruction.setPosition(addBefore.getPosition());
it.add(instruction);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index ae94a4e..a02bf6c 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -121,7 +121,7 @@
mayHaveUnreachableBlocks |= unlinkDeadCatchHandlers(block);
}
}
- InstructionListIterator iterator = block.listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (current.isInvokeCustom()) {
@@ -277,7 +277,7 @@
// Split the block to ensure no instructions after throwing instructions.
iterator
.split(code, blocks)
- .listIterator()
+ .listIterator(code)
.add(constantReturnMaterializingInstruction);
} else {
iterator.add(constantReturnMaterializingInstruction);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchConverter.java
index f1396b8..964fcd1 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchConverter.java
@@ -289,8 +289,7 @@
insertionBlock.link(fallthroughBlock);
JumpInstruction exit = insertionBlock.exit();
exit.replace(
- new StringSwitch(value, keys, targetBlockIndices, i + numberOfCatchHandlers),
- code.metadata());
+ new StringSwitch(value, keys, targetBlockIndices, i + numberOfCatchHandlers), code);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java b/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java
index 4cf5299..d163c21 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java
@@ -112,7 +112,7 @@
if (previous == null) {
// Replace the string-switch instruction by a goto instruction.
- block.exit().replace(new Goto(newBlock), code.metadata());
+ block.exit().replace(new Goto(newBlock), code);
block.link(newBlock);
} else {
// Set the fallthrough block for the previously added if-instruction.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index b178863..d534cf6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -24,7 +24,7 @@
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.conversion.IRConverter;
@@ -94,7 +94,7 @@
return; // Nothing to do!
}
- InstructionIterator iterator = code.instructionIterator();
+ InstructionListIterator iterator = code.instructionListIterator();
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
if (!instruction.isInvokeMethod()) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/D8NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/D8NestBasedAccessDesugaring.java
index b159ef7..95a70df 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/D8NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/D8NestBasedAccessDesugaring.java
@@ -59,7 +59,7 @@
ListIterator<BasicBlock> blocks = code.listIterator();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
- InstructionListIterator instructions = block.listIterator();
+ InstructionListIterator instructions = block.listIterator(code);
while (instructions.hasNext()) {
Instruction instruction = instructions.next();
if (instruction.isInvokeMethod() && !instruction.isInvokeSuper()) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 0681e81..a241bf9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -204,7 +204,7 @@
AppInfo appInfo = appView.appInfo();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
- InstructionListIterator instructions = block.listIterator();
+ InstructionListIterator instructions = block.listIterator(code);
while (instructions.hasNext()) {
Instruction instruction = instructions.next();
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 9dff900..fb64572 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
@@ -117,7 +117,7 @@
ListIterator<BasicBlock> blocks = code.listIterator();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
- InstructionListIterator instructions = block.listIterator();
+ InstructionListIterator instructions = block.listIterator(code);
while (instructions.hasNext()) {
Instruction instruction = instructions.next();
if (instruction.isInvokeCustom()) {
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 785799d..834a492 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
@@ -117,7 +117,7 @@
ListIterator<BasicBlock> blocks = code.listIterator();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
- InstructionListIterator instructions = block.listIterator().recordChangesToMetadata(code);
+ InstructionListIterator instructions = block.listIterator(code);
while (instructions.hasNext()) {
Instruction instruction = instructions.next();
if (!instruction.isInvokeCustom()) {
@@ -382,7 +382,7 @@
// located right before the iterator point and new blocks created while copying
// handles break this expectation.
List<BasicBlock> newBlocks = new ArrayList<>();
- InstructionListIterator it = currentBlock.listIterator();
+ InstructionListIterator it = currentBlock.listIterator(code);
while (it.hasNext()) {
Instruction instruction = it.next();
if (instruction.instructionTypeCanThrow() && it.hasNext()) {
@@ -391,7 +391,7 @@
BasicBlock newBlock = it.split(code, blocks);
newBlocks.add(newBlock);
// Follow with the next block.
- it = newBlock.listIterator();
+ it = newBlock.listIterator(code);
}
}
// Copy catch handlers after all blocks are split.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java
index efa0901..eb7cc6d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/TwrCloseResourceRewriter.java
@@ -22,7 +22,7 @@
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.synthetic.TemplateMethodCode;
@@ -76,7 +76,7 @@
// Rewrites calls to $closeResource() method. Can be invoked concurrently.
public void rewriteMethodCode(IRCode code) {
- InstructionIterator iterator = code.instructionIterator();
+ InstructionListIterator iterator = code.instructionListIterator();
AppInfo appInfo = appView.appInfo();
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssumeDynamicTypeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/AssumeDynamicTypeRemover.java
index 0c1ffad..257d002 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssumeDynamicTypeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssumeDynamicTypeRemover.java
@@ -90,7 +90,7 @@
if (blocksToBeRemoved.contains(block)) {
continue;
}
- InstructionListIterator instructionIterator = block.listIterator();
+ InstructionListIterator instructionIterator = block.listIterator(code);
while (instructionIterator.hasNext()) {
Instruction instruction = instructionIterator.next();
if (instruction.isAssumeDynamicType()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
index 8589552..ae8ec3d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
@@ -37,7 +37,6 @@
import com.android.tools.r8.ir.code.FieldInstruction;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.StaticGet;
@@ -168,7 +167,7 @@
// Note: Traversing code.instructions(), and not unnecessaryStaticPuts(), to ensure
// deterministic iteration order.
- InstructionIterator instructionIterator = code.instructionIterator();
+ InstructionListIterator instructionIterator = code.instructionListIterator();
while (instructionIterator.hasNext()) {
Instruction instruction = instructionIterator.next();
if (!instruction.isStaticPut()
@@ -196,7 +195,7 @@
// Remove the instructions collected for removal.
if (unnecessaryInstructions.size() > 0) {
- IteratorUtils.removeIf(code.instructionIterator(), unnecessaryInstructions::contains);
+ IteratorUtils.removeIf(code.instructionListIterator(), unnecessaryInstructions::contains);
}
// If we are in R8, and we have removed all static-put instructions to some field, then record
@@ -325,9 +324,7 @@
BasicBlock block = code.entryBlock();
while (!block.isMarked(color) && block.getPredecessors().size() <= 1) {
block.mark(color);
- InstructionListIterator it = block.listIterator();
- while (it.hasNext()) {
- Instruction instruction = it.next();
+ for (Instruction instruction : block.getInstructions()) {
if (instruction.isArrayPut()) {
// Array stores do not impact our ability to move constants into the class definition,
// as long as the instructions do not throw.
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 24b3f6e..28557ac 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
@@ -182,7 +182,7 @@
// is not nullable. This is fixed by rerunning the type analysis for the affected values.
Set<Value> valuesThatRequireWidening = Sets.newIdentityHashSet();
- InstructionIterator it = code.instructionIterator();
+ InstructionListIterator it = code.instructionListIterator();
boolean needToCheckTrivialPhis = false;
while (it.hasNext()) {
Instruction instruction = it.next();
@@ -255,7 +255,7 @@
// Rewrite 'throw new NullPointerException()' to 'throw null'.
public void rewriteThrowNullPointerException(IRCode code) {
for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction instruction = it.next();
// Check for 'new-instance NullPointerException' with 2 users, not declaring a local and
@@ -421,11 +421,9 @@
// there is nothing to do.
return;
}
- InstructionIterator it = code.instructionIterator();
int selfRecursionFanOut = 0;
Instruction lastSelfRecursiveCall = null;
- while (it.hasNext()) {
- Instruction i = it.next();
+ for (Instruction i : code.instructions()) {
if (i.isInvokeMethod() && i.asInvokeMethod().getInvokedMethod() == code.method.method) {
selfRecursionFanOut++;
lastSelfRecursiveCall = i;
@@ -435,7 +433,7 @@
assert lastSelfRecursiveCall != null;
// Split out the last recursive call in its own block.
InstructionListIterator splitIterator =
- lastSelfRecursiveCall.getBlock().listIterator(lastSelfRecursiveCall);
+ lastSelfRecursiveCall.getBlock().listIterator(code, lastSelfRecursiveCall);
splitIterator.previous();
BasicBlock newBlock = splitIterator.split(code, 1);
// Generate rethrow block.
@@ -863,7 +861,7 @@
ListIterator<BasicBlock> blocksIterator = code.listIterator();
while (blocksIterator.hasNext()) {
BasicBlock block = blocksIterator.next();
- InstructionListIterator iterator = block.listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
if (instruction.isIntSwitch()) {
@@ -1090,7 +1088,7 @@
targets,
switchInsn.getFallthroughBlockIndex());
// Replace the switch itself.
- exit.replace(newSwitch, code.metadata());
+ exit.replace(newSwitch, code);
// If the original input to the switch is now unused, remove it too. It is not dead
// as it might have side-effects but we ignore these here.
Instruction arrayGet = info.arrayGet;
@@ -1368,10 +1366,7 @@
IRCode code, DexClass clazz, Function<DexType, DexClass> typeToClass) {
Value receiver = code.getThis();
- InstructionIterator it = code.instructionIterator();
- while (it.hasNext()) {
- Instruction insn = it.next();
-
+ for (Instruction insn : code.instructions()) {
if (insn.isReturn()) {
continue;
}
@@ -1455,14 +1450,10 @@
// and assign this instance to a static final field of the same class.
//
private synchronized TrivialInitializer computeClassInitializerInfo(IRCode code, DexClass clazz) {
- InstructionIterator it = code.instructionIterator();
-
Value createdSingletonInstance = null;
DexField singletonField = null;
- while (it.hasNext()) {
- Instruction insn = it.next();
-
+ for (Instruction insn : code.instructions()) {
if (insn.isConstNumber()) {
continue;
}
@@ -1578,9 +1569,7 @@
// We found a NPE (or similar exception) throwing code.
// Combined with the above CONDITIONAL_EFFECT, the code checks NPE on the value.
for (BasicBlock predecessor : currentBlock.getPredecessors()) {
- Instruction last =
- predecessor.listIterator(predecessor.getInstructions().size()).previous();
- if (isNullCheck(last, value)) {
+ if (isNullCheck(predecessor.exit(), value)) {
return InstructionEffect.DESIRED_EFFECT;
}
}
@@ -1652,11 +1641,11 @@
}
/**
- * Returns true if the given instruction is {@code v <- new-instance NullPointerException},
- * and the next instruction is {@code invoke-direct v, NullPointerException.<init>()}.
+ * Returns true if the given instruction is {@code v <- new-instance NullPointerException}, and
+ * the next instruction is {@code invoke-direct v, NullPointerException.<init>()}.
*/
private static boolean isInstantiationOfNullPointerException(
- Instruction instruction, InstructionListIterator it, DexItemFactory dexItemFactory) {
+ Instruction instruction, InstructionIterator it, DexItemFactory dexItemFactory) {
if (!instruction.isNewInstance()
|| instruction.asNewInstance().clazz != dexItemFactory.npeType) {
return false;
@@ -1708,7 +1697,7 @@
* <p>Note: we do not track phis so we may return false negative. This is a conservative approach.
*/
private static boolean alwaysTriggerExpectedEffectBeforeAnythingElse(
- IRCode code, BiFunction<Instruction, InstructionListIterator, InstructionEffect> function) {
+ IRCode code, BiFunction<Instruction, InstructionIterator, InstructionEffect> function) {
final int color = code.reserveMarkingColor();
try {
ArrayDeque<BasicBlock> worklist = new ArrayDeque<>();
@@ -1721,7 +1710,7 @@
assert currentBlock.isMarked(color);
InstructionEffect result = InstructionEffect.NO_EFFECT;
- InstructionListIterator it = currentBlock.listIterator();
+ InstructionIterator it = currentBlock.iterator();
while (result == InstructionEffect.NO_EFFECT && it.hasNext()) {
result = function.apply(it.next(), it);
}
@@ -1810,7 +1799,7 @@
if (blocksToBeRemoved.contains(block)) {
continue;
}
- InstructionListIterator iterator = block.listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (current.isInvokeMethod()) {
@@ -1960,7 +1949,7 @@
}
}
- InstructionIterator iterator = code.instructionIterator();
+ InstructionListIterator iterator = code.instructionListIterator();
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (current.isInvokeMethod()) {
@@ -1998,7 +1987,7 @@
}
private Value blockWithSingleConstNumberAndGoto(BasicBlock block) {
- InstructionIterator iterator = block.iterator();
+ InstructionIterator iterator = block.iterator();
Instruction constNumber = iterator.nextUntil(this::isNotDebugInstruction);
if (constNumber == null || !constNumber.isConstNumber()) {
return null;
@@ -2008,7 +1997,7 @@
}
private Value blockWithAssertionsDisabledFieldPut(BasicBlock block) {
- InstructionIterator iterator = block.iterator();
+ InstructionIterator iterator = block.iterator();
Instruction fieldPut = iterator.nextUntil(this::isNotDebugInstruction);
return fieldPut != null
&& isAssertionsDisabledFieldPut(fieldPut) ? fieldPut.inValues().get(0) : null;
@@ -2082,7 +2071,7 @@
// removal.
TypeAnalysis typeAnalysis = new TypeAnalysis(appView);
Set<Value> affectedValues = Sets.newIdentityHashSet();
- InstructionIterator it = code.instructionIterator();
+ InstructionListIterator it = code.instructionListIterator();
boolean needToRemoveTrivialPhis = false;
while (it.hasNext()) {
Instruction current = it.next();
@@ -2117,7 +2106,7 @@
// Returns true if the given check-cast instruction was removed.
private RemoveCheckCastInstructionIfTrivialResult removeCheckCastInstructionIfTrivial(
- CheckCast checkCast, InstructionIterator it, IRCode code, Set<Value> affectedValues) {
+ CheckCast checkCast, InstructionListIterator it, IRCode code, Set<Value> affectedValues) {
Value inValue = checkCast.object();
Value outValue = checkCast.outValue();
DexType castType = checkCast.getType();
@@ -2179,7 +2168,7 @@
// Returns true if the given instance-of instruction was removed.
private boolean removeInstanceOfInstructionIfTrivial(
- InstanceOf instanceOf, InstructionIterator it, IRCode code) {
+ InstanceOf instanceOf, InstructionListIterator it, IRCode code) {
// If the instance-of type is not accessible in the current context, we should not remove the
// instance-of instruction in order to preserve IllegalAccessError.
if (!isTypeVisibleFromContext(appView, code.method.method.holder, instanceOf.type())) {
@@ -2261,7 +2250,7 @@
}
public static void removeOrReplaceByDebugLocalWrite(
- Instruction currentInstruction, InstructionIterator it, Value inValue, Value outValue) {
+ Instruction currentInstruction, InstructionListIterator it, Value inValue, Value outValue) {
if (outValue.hasLocalInfo() && outValue.getLocalInfo() != inValue.getLocalInfo()) {
DebugLocalWrite debugLocalWrite = new DebugLocalWrite(outValue, inValue);
it.replaceCurrentInstruction(debugLocalWrite);
@@ -2286,7 +2275,7 @@
// of register needed (and thereby code size as well).
public void splitRangeInvokeConstants(IRCode code) {
for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction current = it.next();
if (current.isInvoke() && current.asInvoke().requiredArgumentRegisters() > 5) {
@@ -2325,7 +2314,7 @@
*/
public void useDedicatedConstantForLitInstruction(IRCode code) {
for (BasicBlock block : code.blocks) {
- InstructionListIterator instructionIterator = block.listIterator();
+ InstructionListIterator instructionIterator = block.listIterator(code);
while (instructionIterator.hasNext()) {
Instruction currentInstruction = instructionIterator.next();
if (shouldBeLitInstruction(currentInstruction)) {
@@ -2471,7 +2460,7 @@
for (Instruction instruction : instructions) {
if (instruction.outValue().numberOfPhiUsers() != 0 || instruction.isConstString()) {
// Add constant into the dominator block of usages.
- insertConstantInBlock(instruction, block);
+ insertConstantInBlock(instruction, block, code);
} else {
assert instruction.isConstNumber();
ConstNumber constNumber = instruction.asConstNumber();
@@ -2481,7 +2470,7 @@
for (Instruction user : constantValue.uniqueUsers()) {
ConstNumber newCstNum = ConstNumber.copyOf(code, constNumber);
newCstNum.setPosition(user.getPosition());
- InstructionListIterator iterator = user.getBlock().listIterator(user);
+ InstructionListIterator iterator = user.getBlock().listIterator(code, user);
iterator.previous();
iterator.add(newCstNum);
user.replaceValue(constantValue, newCstNum.outValue());
@@ -2492,7 +2481,7 @@
} else {
// Add constant into the dominator block of usages.
for (Instruction instruction : instructions) {
- insertConstantInBlock(instruction, block);
+ insertConstantInBlock(instruction, block, code);
}
}
}
@@ -2506,10 +2495,7 @@
Supplier<DominatorTree> dominatorTreeMemoization,
Map<BasicBlock, List<Instruction>> addConstantInBlock,
Predicate<ConstInstruction> selector) {
-
- InstructionListIterator it = block.listIterator();
- while (it.hasNext()) {
- Instruction next = it.next();
+ for (Instruction next : block.getInstructions()) {
if (!next.isConstInstruction()) {
continue;
}
@@ -2565,9 +2551,9 @@
}
}
- private void insertConstantInBlock(Instruction instruction, BasicBlock block) {
+ private void insertConstantInBlock(Instruction instruction, BasicBlock block, IRCode code) {
boolean hasCatchHandlers = block.hasCatchHandlers();
- InstructionListIterator insertAt = block.listIterator();
+ InstructionListIterator insertAt = block.listIterator(code);
// Place the instruction as late in the block as we can. It needs to go before users
// and if we have catch handlers it needs to be placed before the throwing instruction.
insertAt.nextUntil(i ->
@@ -2618,7 +2604,7 @@
Set<BasicBlock> visitedBlocks = Sets.newIdentityHashSet();
// We allow the array instantiations to cross block boundaries as long as it hasn't encountered
// an instruction instance that can throw an exception.
- InstructionListIterator it = block.listIterator();
+ InstructionIterator it = block.iterator();
it.nextUntil(i -> i == newArray);
do {
visitedBlocks.add(block);
@@ -2659,7 +2645,7 @@
}
BasicBlock nextBlock = block.exit().isGoto() ? block.exit().asGoto().getTarget() : null;
block = nextBlock != null && !visitedBlocks.contains(nextBlock) ? nextBlock : null;
- it = block != null ? block.listIterator() : null;
+ it = block != null ? block.iterator() : null;
} while (it != null);
return null;
}
@@ -2697,7 +2683,7 @@
Map<Value, Instruction> instructionToInsertForArray = new HashMap<>();
Map<Value, Integer> storesToRemoveForArray = new HashMap<>();
// First pass: identify candidates and insert fill array data instruction.
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction instruction = it.next();
if (instruction.getLocalInfo() != null
@@ -2758,7 +2744,7 @@
Set<BasicBlock> visitedBlocks = Sets.newIdentityHashSet();
do {
visitedBlocks.add(block);
- it = block.listIterator();
+ it = block.listIterator(code);
while (it.hasNext()) {
Instruction instruction = it.next();
if (instruction.isArrayPut()) {
@@ -2800,10 +2786,8 @@
&& !from.getPosition().equals(to.getPosition())) {
return true;
}
- InstructionListIterator iterator = from.getBlock().listIterator(from);
Position position = null;
- while (iterator.hasNext()) {
- Instruction instruction = iterator.next();
+ for (Instruction instruction : from.getBlock().instructionsAfter(from)) {
if (position == null) {
if (instruction.getPosition().isSome()) {
position = instruction.getPosition();
@@ -2830,12 +2814,12 @@
if (!phi.hasLocalInfo() && phi.numberOfUsers() == 1 && phi.numberOfAllUsers() == 1) {
Instruction instruction = phi.singleUniqueUser();
if (instruction.isDebugLocalWrite()) {
- removeDebugWriteOfPhi(phi, instruction.asDebugLocalWrite());
+ removeDebugWriteOfPhi(code, phi, instruction.asDebugLocalWrite());
}
}
}
- InstructionListIterator iterator = block.listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction prevInstruction = iterator.peekPrevious();
Instruction instruction = iterator.next();
@@ -2868,9 +2852,10 @@
}
}
- private void removeDebugWriteOfPhi(Phi phi, DebugLocalWrite write) {
+ private void removeDebugWriteOfPhi(IRCode code, Phi phi, DebugLocalWrite write) {
assert write.src() == phi;
- for (InstructionListIterator iterator = phi.getBlock().listIterator(); iterator.hasNext(); ) {
+ InstructionListIterator iterator = phi.getBlock().listIterator(code);
+ while (iterator.hasNext()) {
Instruction next = iterator.next();
if (!next.isDebugLocalWrite()) {
// If the debug write is not in the block header bail out.
@@ -2892,11 +2877,9 @@
private static class CSEExpressionEquivalence extends Equivalence<Instruction> {
- private final IRCode code;
private final InternalOptions options;
- private CSEExpressionEquivalence(IRCode code, InternalOptions options) {
- this.code = code;
+ private CSEExpressionEquivalence(InternalOptions options) {
this.options = options;
}
@@ -2999,9 +2982,8 @@
private boolean hasCSECandidate(IRCode code, int noCandidate) {
for (BasicBlock block : code.blocks) {
- InstructionListIterator iterator = block.listIterator();
- while (iterator.hasNext()) {
- if (isCSEInstructionCandidate(iterator.next())) {
+ for (Instruction instruction : block.getInstructions()) {
+ if (isCSEInstructionCandidate(instruction)) {
return true;
}
}
@@ -3015,14 +2997,14 @@
if (hasCSECandidate(code, noCandidate)) {
final ListMultimap<Wrapper<Instruction>, Value> instructionToValue =
ArrayListMultimap.create();
- final CSEExpressionEquivalence equivalence = new CSEExpressionEquivalence(code, options);
+ final CSEExpressionEquivalence equivalence = new CSEExpressionEquivalence(options);
final DominatorTree dominatorTree = new DominatorTree(code);
for (int i = 0; i < dominatorTree.getSortedBlocks().length; i++) {
BasicBlock block = dominatorTree.getSortedBlocks()[i];
if (block.isMarked(noCandidate)) {
continue;
}
- InstructionListIterator iterator = block.listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
if (isCSEInstructionCandidate(instruction)) {
@@ -3057,8 +3039,8 @@
continue;
}
if (block.exit().isIf()) {
- flipIfBranchesIfNeeded(block);
- rewriteIfWithConstZero(block);
+ flipIfBranchesIfNeeded(code, block);
+ rewriteIfWithConstZero(code, block);
if (simplifyKnownBooleanCondition(code, block)) {
continue;
@@ -3250,10 +3232,11 @@
if (ifInstruction.isZeroTest()) {
changed |=
- replaceDominatedConstNumbers(0, lhs, trueTarget, constantsByValue, dominatorTree);
+ replaceDominatedConstNumbers(0, lhs, trueTarget, constantsByValue, code, dominatorTree);
if (lhs.knownToBeBoolean()) {
changed |=
- replaceDominatedConstNumbers(1, lhs, falseTarget, constantsByValue, dominatorTree);
+ replaceDominatedConstNumbers(
+ 1, lhs, falseTarget, constantsByValue, code, dominatorTree);
}
} else {
assert rhs != null;
@@ -3261,22 +3244,42 @@
ConstNumber lhsAsNumber = lhs.getConstInstruction().asConstNumber();
changed |=
replaceDominatedConstNumbers(
- lhsAsNumber.getRawValue(), rhs, trueTarget, constantsByValue, dominatorTree);
+ lhsAsNumber.getRawValue(),
+ rhs,
+ trueTarget,
+ constantsByValue,
+ code,
+ dominatorTree);
if (lhs.knownToBeBoolean() && rhs.knownToBeBoolean()) {
changed |=
replaceDominatedConstNumbers(
- negateBoolean(lhsAsNumber), rhs, falseTarget, constantsByValue, dominatorTree);
+ negateBoolean(lhsAsNumber),
+ rhs,
+ falseTarget,
+ constantsByValue,
+ code,
+ dominatorTree);
}
} else {
assert rhs.isConstNumber();
ConstNumber rhsAsNumber = rhs.getConstInstruction().asConstNumber();
changed |=
replaceDominatedConstNumbers(
- rhsAsNumber.getRawValue(), lhs, trueTarget, constantsByValue, dominatorTree);
+ rhsAsNumber.getRawValue(),
+ lhs,
+ trueTarget,
+ constantsByValue,
+ code,
+ dominatorTree);
if (lhs.knownToBeBoolean() && rhs.knownToBeBoolean()) {
changed |=
replaceDominatedConstNumbers(
- negateBoolean(rhsAsNumber), lhs, falseTarget, constantsByValue, dominatorTree);
+ negateBoolean(rhsAsNumber),
+ lhs,
+ falseTarget,
+ constantsByValue,
+ code,
+ dominatorTree);
}
}
}
@@ -3328,6 +3331,7 @@
Value newValue,
BasicBlock dominator,
Supplier<Long2ReferenceMap<List<ConstNumber>>> constantsByValueSupplier,
+ IRCode code,
Supplier<DominatorTree> dominatorTree) {
if (newValue.hasLocalInfo()) {
// We cannot replace a constant with a value that has local info, because that could change
@@ -3378,7 +3382,7 @@
if (dominatorTree.get().dominatedBy(block, dominator)) {
if (newValue.getTypeLattice().lessThanOrEqual(value.getTypeLattice(), appView)) {
value.replaceUsers(newValue);
- block.listIterator(constNumber).removeOrReplaceByDebugLocalRead();
+ block.listIterator(code, constNumber).removeOrReplaceByDebugLocalRead();
constantWithValueIterator.remove();
changed = true;
} else if (value.getTypeLattice().isNullType()) {
@@ -3410,7 +3414,7 @@
if (block.getNumber() != 0 && block.getPredecessors().isEmpty()) {
continue;
}
- InstructionListIterator insnIterator = block.listIterator();
+ InstructionListIterator insnIterator = block.listIterator(code);
while (insnIterator.hasNext()) {
Instruction insn = insnIterator.next();
if (!insn.isInvokeMethod()) {
@@ -3443,7 +3447,7 @@
assert gotoInsn.isGoto();
assert insnIterator.hasNext();
BasicBlock throwNullBlock = insnIterator.split(code, blockIterator);
- InstructionListIterator throwNullInsnIterator = throwNullBlock.listIterator();
+ InstructionListIterator throwNullInsnIterator = throwNullBlock.listIterator(code);
// Insert 'null' constant.
ConstNumber nullConstant = code.createConstNull(gotoInsn.getLocalInfo());
@@ -3582,9 +3586,11 @@
if (firstInstruction.isDebugPosition()) {
assert b.getPredecessors().size() == 1;
BasicBlock predecessorBlock = b.getPredecessors().get(0);
- InstructionListIterator it = predecessorBlock.listIterator(predecessorBlock.exit());
+ InstructionIterator it = predecessorBlock.iterator(predecessorBlock.exit());
Instruction previousPosition = null;
- while (it.hasPrevious() && !(previousPosition = it.previous()).isDebugPosition());
+ while (it.hasPrevious() && !(previousPosition = it.previous()).isDebugPosition()) {
+ // Intentionally empty.
+ }
if (previousPosition != null) {
return previousPosition.getPosition() == firstInstruction.getPosition();
}
@@ -3599,12 +3605,12 @@
IRCode code, BasicBlock block, If theIf, BasicBlock target, BasicBlock deadTarget) {
deadTarget.unlinkSinglePredecessorSiblingsAllowed();
assert theIf == block.exit();
- block.replaceLastInstruction(new Goto());
+ block.replaceLastInstruction(new Goto(), code);
assert block.exit().isGoto();
assert block.exit().asGoto().getTarget() == target;
}
- private void rewriteIfWithConstZero(BasicBlock block) {
+ private void rewriteIfWithConstZero(IRCode code, BasicBlock block) {
If theIf = block.exit().asIf();
if (theIf.isZeroTest()) {
return;
@@ -3617,20 +3623,20 @@
if (leftValue.isConstNumber()) {
if (leftValue.getConstInstruction().asConstNumber().isZero()) {
If ifz = new If(theIf.getType().forSwappedOperands(), rightValue);
- block.replaceLastInstruction(ifz);
+ block.replaceLastInstruction(ifz, code);
assert block.exit() == ifz;
}
} else {
if (rightValue.getConstInstruction().asConstNumber().isZero()) {
If ifz = new If(theIf.getType(), leftValue);
- block.replaceLastInstruction(ifz);
+ block.replaceLastInstruction(ifz, code);
assert block.exit() == ifz;
}
}
}
}
- private boolean flipIfBranchesIfNeeded(BasicBlock block) {
+ private boolean flipIfBranchesIfNeeded(IRCode code, BasicBlock block) {
If theIf = block.exit().asIf();
BasicBlock trueTarget = theIf.getTrueTarget();
BasicBlock fallthrough = theIf.fallthroughBlock();
@@ -3646,13 +3652,13 @@
// on older Android versions.
List<Value> inValues = theIf.inValues();
If newIf = new If(theIf.getType().inverted(), inValues);
- block.replaceLastInstruction(newIf);
+ block.replaceLastInstruction(newIf, code);
block.swapSuccessors(trueTarget, fallthrough);
return true;
}
public void rewriteConstantEnumMethodCalls(IRCode code) {
- InstructionIterator iterator = code.instructionIterator().recordChangesToMetadata(code);
+ InstructionListIterator iterator = code.instructionListIterator();
while (iterator.hasNext()) {
Instruction current = iterator.next();
@@ -3723,7 +3729,7 @@
return;
}
- InstructionIterator iterator = code.instructionIterator();
+ InstructionListIterator iterator = code.instructionListIterator();
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (current.isInvokeMethod()) {
@@ -3756,7 +3762,7 @@
return;
}
- InstructionIterator iterator = code.instructionIterator();
+ InstructionListIterator iterator = code.instructionListIterator();
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (current.isInvokeMethod()) {
@@ -3829,7 +3835,7 @@
}
Int2IntMap previousMapping = new Int2IntOpenHashMap();
Int2IntMap mapping = new Int2IntOpenHashMap();
- ListIterator<Instruction> it = block.getInstructions().listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction instruction = it.next();
if (instruction.isMove()) {
@@ -3839,7 +3845,7 @@
int src = allocator.getRegisterForValue(move.src(), move.getNumber());
int mappedSrc = mapping.getOrDefault(src, src);
mapping.put(dst, mappedSrc);
- it.remove();
+ it.removeInstructionIgnoreOutValue();
}
} else if (instruction.isDebugLocalsChange()) {
DebugLocalsChange change = instruction.asDebugLocalsChange();
@@ -3861,7 +3867,7 @@
IntSet clobberedRegisters = new IntOpenHashSet();
// Backwards instruction scan collecting the registers used by actual instructions.
boolean inEntrySpillMoves = false;
- InstructionListIterator it = block.listIterator(block.getInstructions().size());
+ InstructionIterator it = block.iterator(block.getInstructions().size());
while (it.hasPrevious()) {
Instruction instruction = it.previous();
if (instruction == postSpillLocalsChange) {
@@ -3923,7 +3929,7 @@
ThrowableMethods throwableMethods = dexItemFactory.throwableMethods;
for (BasicBlock block : code.blocks) {
- InstructionListIterator iterator = block.listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (current.isInvokeMethod()) {
@@ -4001,7 +4007,7 @@
public void logArgumentTypes(DexEncodedMethod method, IRCode code) {
List<Value> arguments = code.collectArguments();
BasicBlock block = code.entryBlock();
- InstructionListIterator iterator = block.listIterator().recordChangesToMetadata(code);
+ InstructionListIterator iterator = block.listIterator(code);
// Attach some synthetic position to all inserted code.
Position position = Position.synthetic(1, method.method, null);
@@ -4079,10 +4085,10 @@
isNullBlock.link(successor);
// Fill code into the blocks.
- iterator = isNullBlock.listIterator();
+ iterator = isNullBlock.listIterator(code);
iterator.setInsertionPosition(position);
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, nul)));
- iterator = isNotNullBlock.listIterator();
+ iterator = isNotNullBlock.listIterator(code);
iterator.setInsertionPosition(position);
value = code.createValue(TypeLatticeElement.classClassType(appView, definitelyNotNull()));
iterator.add(new InvokeVirtual(dexItemFactory.objectMethods.getClass, value,
@@ -4090,7 +4096,7 @@
iterator.add(new InvokeVirtual(print, null, ImmutableList.of(out, value)));
}
- iterator = eol.listIterator();
+ iterator = eol.listIterator(code);
iterator.setInsertionPosition(position);
if (i == arguments.size() - 1) {
iterator.add(new InvokeVirtual(printLn, null, ImmutableList.of(out, closeParenthesis)));
@@ -4104,23 +4110,20 @@
}
public static void ensureDirectStringNewToInit(IRCode code, DexItemFactory dexItemFactory) {
- for (BasicBlock block : code.blocks) {
- for (InstructionListIterator it = block.listIterator(); it.hasNext(); ) {
- Instruction instruction = it.next();
- if (instruction.isInvokeDirect()) {
- InvokeDirect invoke = instruction.asInvokeDirect();
- DexMethod method = invoke.getInvokedMethod();
- if (dexItemFactory.isConstructor(method)
- && method.holder == dexItemFactory.stringType
- && invoke.getReceiver().isPhi()) {
- NewInstance newInstance = findNewInstance(invoke.getReceiver().asPhi());
- replaceTrivialNewInstancePhis(newInstance.outValue());
- if (invoke.getReceiver().isPhi()) {
- throw new CompilationError(
- "Failed to remove trivial phis between new-instance and <init>");
- }
- newInstance.markNoSpilling();
+ for (Instruction instruction : code.instructions()) {
+ if (instruction.isInvokeDirect()) {
+ InvokeDirect invoke = instruction.asInvokeDirect();
+ DexMethod method = invoke.getInvokedMethod();
+ if (dexItemFactory.isConstructor(method)
+ && method.holder == dexItemFactory.stringType
+ && invoke.getReceiver().isPhi()) {
+ NewInstance newInstance = findNewInstance(invoke.getReceiver().asPhi());
+ replaceTrivialNewInstancePhis(newInstance.outValue());
+ if (invoke.getReceiver().isPhi()) {
+ throw new CompilationError(
+ "Failed to remove trivial phis between new-instance and <init>");
}
+ newInstance.markNoSpilling();
}
}
}
@@ -4257,7 +4260,7 @@
ListIterator<BasicBlock> blocks = code.listIterator();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction instruction = it.next();
if (instruction.isArithmeticBinop() || instruction.isNeg()) {
@@ -4280,12 +4283,12 @@
block.hasCatchHandlers() ? it.split(code, blocks) : block;
if (blockWithInvokeNaN != block) {
// If we split, add the invoke at the end of the original block.
- it = block.listIterator(block.getInstructions().size());
+ it = block.listIterator(code, block.getInstructions().size());
it.previous();
it.add(invokeIsNaN);
// Continue iteration in the split block.
block = blockWithInvokeNaN;
- it = block.listIterator();
+ it = block.listIterator(code);
} else {
// Otherwise, add it to the current block.
it.add(invokeIsNaN);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java b/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
index 00b4540..04bdf84 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
@@ -99,46 +99,43 @@
});
// Collect usages of constants that can be canonicalized.
- for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
- while (it.hasNext()) {
- Instruction current = it.next();
- // Interested in ConstNumber, (DexItemBased)?ConstString, and ConstClass
- if (!current.isConstNumber()
- && !current.isConstString()
- && !current.isDexItemBasedConstString()
- && !current.isConstClass()) {
- continue;
- }
- // Do not canonicalize ConstClass that may have side effects. Its original instructions
- // will not be removed by dead code remover due to the side effects.
- if (current.isConstClass()
- && current.instructionMayHaveSideEffects(appView, code.method.method.holder)) {
- continue;
- }
- // Do not canonicalize ConstString instructions if there are monitor operations in the code.
- // That could lead to unbalanced locking and could lead to situations where OOM exceptions
- // could leave a synchronized method without unlocking the monitor.
- if ((current.isConstString() || current.isDexItemBasedConstString())
- && code.metadata().mayHaveMonitorInstruction()) {
- continue;
- }
- // Constants with local info must not be canonicalized and must be filtered.
- if (current.outValue().hasLocalInfo()) {
- continue;
- }
- // Constants that are used by invoke range are not canonicalized to be compliant with the
- // optimization splitRangeInvokeConstant that gives the register allocator more freedom in
- // assigning register to ranged invokes which can greatly reduce the number of register
- // needed (and thereby code size as well). Thus no need to do a transformation that should
- // be removed later by another optimization.
- if (constantUsedByInvokeRange(current.asConstInstruction())) {
- continue;
- }
- List<Value> oldValuesDefinedByConstant = valuesDefinedByConstant.computeIfAbsent(
- current.asConstInstruction(), k -> new ArrayList<>());
- oldValuesDefinedByConstant.add(current.outValue());
+ for (Instruction current : code.instructions()) {
+ // Interested in ConstNumber, (DexItemBased)?ConstString, and ConstClass
+ if (!current.isConstNumber()
+ && !current.isConstString()
+ && !current.isDexItemBasedConstString()
+ && !current.isConstClass()) {
+ continue;
}
+ // Do not canonicalize ConstClass that may have side effects. Its original instructions
+ // will not be removed by dead code remover due to the side effects.
+ if (current.isConstClass()
+ && current.instructionMayHaveSideEffects(appView, code.method.method.holder)) {
+ continue;
+ }
+ // Do not canonicalize ConstString instructions if there are monitor operations in the code.
+ // That could lead to unbalanced locking and could lead to situations where OOM exceptions
+ // could leave a synchronized method without unlocking the monitor.
+ if ((current.isConstString() || current.isDexItemBasedConstString())
+ && code.metadata().mayHaveMonitorInstruction()) {
+ continue;
+ }
+ // Constants with local info must not be canonicalized and must be filtered.
+ if (current.outValue().hasLocalInfo()) {
+ continue;
+ }
+ // Constants that are used by invoke range are not canonicalized to be compliant with the
+ // optimization splitRangeInvokeConstant that gives the register allocator more freedom in
+ // assigning register to ranged invokes which can greatly reduce the number of register
+ // needed (and thereby code size as well). Thus no need to do a transformation that should
+ // be removed later by another optimization.
+ if (constantUsedByInvokeRange(current.asConstInstruction())) {
+ continue;
+ }
+ List<Value> oldValuesDefinedByConstant =
+ valuesDefinedByConstant.computeIfAbsent(
+ current.asConstInstruction(), k -> new ArrayList<>());
+ oldValuesDefinedByConstant.add(current.outValue());
}
if (valuesDefinedByConstant.isEmpty()) {
@@ -210,7 +207,7 @@
// Insert the constant instruction at the start of the block right after the argument
// instructions. It is important that the const instruction is put before any instruction
// that can throw exceptions (since the value could be used on the exceptional edge).
- InstructionListIterator it = entryBlock.listIterator();
+ InstructionListIterator it = entryBlock.listIterator(code);
while (it.hasNext()) {
if (!it.next().isArgument()) {
it.previous();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index 16a5d2a..8dc27fd 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -86,7 +86,7 @@
}
private void removeDeadInstructions(Queue<BasicBlock> worklist, IRCode code, BasicBlock block) {
- InstructionListIterator iterator = block.listIterator(block.getInstructions().size());
+ InstructionListIterator iterator = block.listIterator(code, block.getInstructions().size());
while (iterator.hasPrevious()) {
Instruction current = iterator.previous();
// Remove unused invoke results.
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 998de0d..bebbbf4 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
@@ -52,7 +52,7 @@
ListIterator<BasicBlock> blocks = code.listIterator();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction current = it.next();
@@ -191,13 +191,13 @@
block.hasCatchHandlers() ? it.split(code, blocks) : block;
if (blockWithDevirtualizedInvoke != block) {
// If we split, add the new checkcast at the end of the currently visiting block.
- it = block.listIterator(block.getInstructions().size());
+ it = block.listIterator(code, block.getInstructions().size());
it.previous();
it.add(checkCast);
// Update the dominator tree after the split.
dominatorTree = new DominatorTree(code);
// Restore the cursor.
- it = blockWithDevirtualizedInvoke.listIterator();
+ it = blockWithDevirtualizedInvoke.listIterator(code);
assert it.peekNext() == devirtualizedInvoke;
it.next();
} else {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
index 97e0417..ace7a3b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DynamicTypeOptimization.java
@@ -52,7 +52,7 @@
// instructions.
private void insertAssumeDynamicTypeInstructionsInBlock(
IRCode code, ListIterator<BasicBlock> blockIterator, BasicBlock block) {
- InstructionListIterator instructionIterator = block.listIterator();
+ InstructionListIterator instructionIterator = block.listIterator(code);
while (instructionIterator.hasNext()) {
Instruction current = instructionIterator.next();
if (current.isInvokeMethod()) {
@@ -103,7 +103,7 @@
if (insertionBlock == block) {
instructionIterator.add(assumeInstruction);
} else {
- insertionBlock.listIterator().add(assumeInstruction);
+ insertionBlock.listIterator(code).add(assumeInstruction);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/EnumInfoMapCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/EnumInfoMapCollector.java
index 3f02176..2472589 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/EnumInfoMapCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/EnumInfoMapCollector.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.StaticPut;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -55,9 +54,7 @@
DexEncodedMethod initializer = clazz.getClassInitializer();
IRCode code = initializer.getCode().buildIR(initializer, appView, clazz.origin);
Map<DexField, EnumValueInfo> valueInfoMap = new IdentityHashMap<>();
- InstructionIterator it = code.instructionIterator();
- while (it.hasNext()) {
- Instruction insn = it.next();
+ for (Instruction insn : code.instructions()) {
if (!insn.isStaticPut()) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java b/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
index 29392f4..0195c84 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
@@ -52,6 +52,7 @@
* // Update users of vx, vy, and vz.
*/
public class IdempotentFunctionCallCanonicalizer {
+
// Threshold to limit the number of invocation canonicalization.
private static final int MAX_CANONICALIZED_CALL = 15;
@@ -80,10 +81,14 @@
"# invoke canonicalization (program): %s", numberOfProgramCallCanonicalization);
assert histogramOfCanonicalizationCandidatesPerMethod != null;
Log.info(getClass(), "------ histogram of invoke canonicalization candidates ------");
- histogramOfCanonicalizationCandidatesPerMethod.forEach((length, count) -> {
- Log.info(getClass(),
- "%s: %s (%s)", length, StringUtils.times("*", Math.min(count, 53)), count);
- });
+ histogramOfCanonicalizationCandidatesPerMethod.forEach(
+ (length, count) ->
+ Log.info(
+ getClass(),
+ "%s: %s (%s)",
+ length,
+ StringUtils.times("*", Math.min(count, 53)),
+ count));
}
public void canonicalize(IRCode code) {
@@ -108,9 +113,7 @@
DexType context = code.method.method.holder;
// Collect invocations along with arguments.
for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
- while (it.hasNext()) {
- Instruction current = it.next();
+ for (Instruction current : block.getInstructions()) {
if (!current.isInvokeMethod()) {
continue;
}
@@ -228,7 +231,7 @@
if (!deadInvocations.isEmpty()) {
for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction current = it.next();
if (!current.isInvokeMethod()) {
@@ -264,7 +267,7 @@
BasicBlock entryBlock = code.entryBlock();
// Insert the canonicalized invoke after in values.
int numberOfInValuePassed = 0;
- InstructionListIterator it = entryBlock.listIterator();
+ InstructionListIterator it = entryBlock.listIterator(code);
while (it.hasNext()) {
Instruction current = it.next();
if (current.hasOutValue() && canonicalizedInvoke.inValues().contains(current.outValue())) {
@@ -287,7 +290,7 @@
BasicBlock entryBlock = code.entryBlock();
// Insert the canonicalized invocation at the start of the block right after the argument
// instructions.
- InstructionListIterator it = entryBlock.listIterator();
+ InstructionListIterator it = entryBlock.listIterator(code);
while (it.hasNext()) {
if (!it.next().isArgument()) {
it.previous();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index f91ac1a..b1f231e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -106,16 +106,14 @@
}
if (appView.options().canHaveDalvikIntUsedAsNonIntPrimitiveTypeBug()
- && returnsIntAsBoolean(code, method, appView)) {
+ && returnsIntAsBoolean(code, method)) {
return ConstraintWithTarget.NEVER;
}
ConstraintWithTarget result = ConstraintWithTarget.ALWAYS;
InliningConstraints inliningConstraints =
new InliningConstraints(appView, GraphLense.getIdentityLense());
- InstructionIterator it = code.instructionIterator();
- while (it.hasNext()) {
- Instruction instruction = it.next();
+ for (Instruction instruction : code.instructions()) {
ConstraintWithTarget state =
instructionAllowedForInlining(instruction, inliningConstraints, method.method.holder);
if (state == ConstraintWithTarget.NEVER) {
@@ -128,12 +126,12 @@
return result;
}
- private boolean returnsIntAsBoolean(IRCode code, DexEncodedMethod method, AppView appView) {
+ private boolean returnsIntAsBoolean(IRCode code, DexEncodedMethod method) {
DexType returnType = method.method.proto.returnType;
for (BasicBlock basicBlock : code.blocks) {
- InstructionListIterator instructionListIterator = basicBlock.listIterator();
- while (instructionListIterator.hasNext()) {
- Instruction instruction = instructionListIterator.nextUntil(Instruction::isReturn);
+ InstructionIterator instructionIterator = basicBlock.iterator();
+ while (instructionIterator.hasNext()) {
+ Instruction instruction = instructionIterator.nextUntil(Instruction::isReturn);
if (instruction != null) {
if (returnType.isBooleanType() && !instruction.inValues().get(0).knownToBeBoolean()) {
return true;
@@ -576,7 +574,8 @@
// Insert a new block between the last argument instruction and the first actual
// instruction of the method.
- BasicBlock throwBlock = entryBlock.listIterator(arguments.size()).split(code, 0, null);
+ BasicBlock throwBlock =
+ entryBlock.listIterator(code, arguments.size()).split(code, 0, null);
assert !throwBlock.hasCatchHandlers();
// Link the entry block to the successor of the newly inserted block.
@@ -587,12 +586,12 @@
// with an `if-eqz` instruction that jumps to the newly inserted block if the receiver
// is null.
If ifInstruction = new If(If.Type.EQ, receiver);
- entryBlock.replaceLastInstruction(ifInstruction);
+ entryBlock.replaceLastInstruction(ifInstruction, code);
assert ifInstruction.getTrueTarget() == throwBlock;
assert ifInstruction.fallthroughBlock() == continuationBlock;
// Replace the single goto instruction in the newly inserted block by `throw null`.
- InstructionListIterator iterator = throwBlock.listIterator();
+ InstructionListIterator iterator = throwBlock.listIterator(code);
Value nullValue = iterator.insertConstNullInstruction(code, appView.options());
iterator.next();
iterator.replaceCurrentInstruction(new Throw(nullValue));
@@ -804,7 +803,7 @@
if (blocksToRemove.contains(block)) {
continue;
}
- InstructionListIterator iterator = block.listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (current.isInvokeMethod()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index 2326b45..813b6e0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -233,7 +233,7 @@
}
replacement.setPosition(current.getPosition());
if (current.getBlock().hasCatchHandlers()) {
- iterator.split(code, blocks).listIterator().recordChangesToMetadata(code).add(replacement);
+ iterator.split(code, blocks).listIterator(code).add(replacement);
} else {
iterator.add(replacement);
}
@@ -315,7 +315,7 @@
replacement.setPosition(current.getPosition());
current.moveDebugValues(replacement);
if (current.getBlock().hasCatchHandlers()) {
- iterator.split(code, blocks).listIterator().recordChangesToMetadata(code).add(replacement);
+ iterator.split(code, blocks).listIterator(code).add(replacement);
} else {
iterator.add(replacement);
}
@@ -457,7 +457,7 @@
nonNullValue, knownToBeNonNullValue, current, appView);
nonNull.setPosition(appView.options().debug ? current.getPosition() : Position.none());
if (current.getBlock().hasCatchHandlers()) {
- iterator.split(code, blocks).listIterator().recordChangesToMetadata(code).add(nonNull);
+ iterator.split(code, blocks).listIterator(code).add(nonNull);
} else {
iterator.add(nonNull);
}
@@ -475,7 +475,7 @@
ListIterator<BasicBlock> blocks = code.listIterator();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
- InstructionListIterator iterator = block.listIterator().recordChangesToMetadata(code);
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (current.isInvokeMethod()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/NestUtils.java b/src/main/java/com/android/tools/r8/ir/optimize/NestUtils.java
index bae9b27..c6694f4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/NestUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/NestUtils.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeInterface;
import com.android.tools.r8.ir.code.InvokeMethod;
@@ -43,7 +43,7 @@
public static void rewriteNestCallsForInlining(
IRCode code, DexType callerHolder, AppView<?> appView) {
// This method is called when inlining code into the nest member callerHolder.
- InstructionIterator iterator = code.instructionIterator();
+ InstructionListIterator iterator = code.instructionListIterator();
DexClass callerHolderClass = appView.definitionFor(callerHolder);
assert callerHolderClass != null;
assert code.method.method.holder != callerHolder;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java b/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
index 07f6039..84247d0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/NonNullTracker.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.If.Type;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Value;
@@ -69,7 +70,7 @@
// 1) invocations that call non-overridable library methods that are known to return non null.
// 2) instructions that implicitly indicate receiver/array is not null.
// 3) parameters that are not null after the invocation.
- InstructionListIterator iterator = block.listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (current.isInvokeMethod()
@@ -201,7 +202,7 @@
Assume<NonNullAssumption> nonNull =
Assume.createAssumeNonNullInstruction(
nonNullValue, knownToBeNonNullValue, theIf, appView);
- InstructionListIterator targetIterator = target.listIterator();
+ InstructionListIterator targetIterator = target.listIterator(code);
nonNull.setPosition(targetIterator.next().getPosition());
targetIterator.previous();
targetIterator.add(nonNull);
@@ -261,7 +262,7 @@
Set<BasicBlock> dominatedBlocks = Sets.newIdentityHashSet();
for (BasicBlock dominatee : dominatorTree.dominatedBlocks(blockWithNonNullInstruction)) {
dominatedBlocks.add(dominatee);
- InstructionListIterator dominateeIterator = dominatee.listIterator();
+ InstructionIterator dominateeIterator = dominatee.iterator();
if (dominatee == blockWithNonNullInstruction && !split) {
// In the block where the non null instruction will be inserted, skip instructions up to
// and including the insertion point.
@@ -307,7 +308,7 @@
nonNull.setPosition(current.getPosition());
if (blockWithNonNullInstruction != block) {
// If we split, add non-null IR on top of the new split block.
- blockWithNonNullInstruction.listIterator().add(nonNull);
+ blockWithNonNullInstruction.listIterator(code).add(nonNull);
} else {
// Otherwise, just add it to the current block at the position of the iterator.
iterator.add(nonNull);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 2fe484e..4837545 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -1237,7 +1237,7 @@
// and none had a position. The code no longer has the previous property.
code.setAllThrowingInstructionsHavePositions(false);
}
- InstructionListIterator endIterator = block.listIterator(end - 1);
+ InstructionListIterator endIterator = block.listIterator(code, end - 1);
Instruction instructionBeforeEnd = endIterator.next();
invalidateInstructionArray(); // Because we're about to modify the original linked list.
instructionBeforeEnd.clearBlock();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
index bdd4d7ff..c0a67fc 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
@@ -328,7 +328,7 @@
|| (successorBlock == null && first.exit().isReturn());
BasicBlock newBlock = new BasicBlock();
newBlock.setNumber(blockNumber);
- InstructionListIterator from = first.listIterator(first.getInstructions().size());
+ InstructionIterator from = first.iterator(first.getInstructions().size());
Int2ReferenceMap<DebugLocalInfo> newBlockEntryLocals = null;
if (first.getLocalsAtEntry() != null) {
newBlockEntryLocals = new Int2ReferenceOpenHashMap<>(first.getLocalsAtEntry());
@@ -411,8 +411,8 @@
if (!Objects.equals(localsAtBlockExit(block0), localsAtBlockExit(block1))) {
return 0;
}
- InstructionListIterator it0 = block0.listIterator(block0.getInstructions().size());
- InstructionListIterator it1 = block1.listIterator(block1.getInstructions().size());
+ InstructionIterator it0 = block0.iterator(block0.getInstructions().size());
+ InstructionIterator it1 = block1.iterator(block1.getInstructions().size());
int suffixSize = 0;
while (it0.hasPrevious() && it1.hasPrevious()) {
Instruction i0 = it0.previous();
@@ -492,11 +492,11 @@
// the same register.
Map<Integer, ConstNumber> registerToNumber = new HashMap<>();
MoveEliminator moveEliminator = new MoveEliminator(allocator);
- ListIterator<Instruction> iterator = block.getInstructions().listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction current = iterator.next();
if (moveEliminator.shouldBeEliminated(current)) {
- iterator.remove();
+ iterator.removeInstructionIgnoreOutValue();
} else if (current.outValue() != null && current.outValue().needsRegister()) {
Value outValue = current.outValue();
int instructionNumber = current.getNumber();
@@ -504,7 +504,7 @@
if (constantSpilledAtDefinition(current.asConstNumber())) {
// Remove constant instructions that are spilled at their definition and are
// therefore unused.
- iterator.remove();
+ iterator.removeInstructionIgnoreOutValue();
continue;
}
int outRegister = allocator.getRegisterForValue(outValue, instructionNumber);
@@ -513,7 +513,7 @@
&& numberInRegister.identicalNonValueNonPositionParts(current)) {
// This instruction is not needed, the same constant is already in this register.
// We don't consider the positions of the two (non-throwing) instructions.
- iterator.remove();
+ iterator.removeInstructionIgnoreOutValue();
} else {
// Insert the current constant in the mapping. Make sure to clobber the second
// register if wide and register-1 if that defines a wide value.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/PhiOptimizations.java b/src/main/java/com/android/tools/r8/ir/optimize/PhiOptimizations.java
index c77171b..9a5e3b9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/PhiOptimizations.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/PhiOptimizations.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.Load;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Store;
@@ -86,7 +86,7 @@
private static int getStackHeightAtInstructionBackwards(Instruction instruction) {
int stackHeight = 0;
BasicBlock block = instruction.getBlock();
- InstructionListIterator it = block.listIterator(block.getInstructions().size() - 1);
+ InstructionIterator it = block.iterator(block.getInstructions().size() - 1);
while (it.hasPrevious()) {
Instruction current = it.previous();
if (current == instruction) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
index 38a1da7..c178221 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/RedundantFieldLoadElimination.java
@@ -115,7 +115,7 @@
activeStaticFieldsAtEntry.containsKey(block)
? activeStaticFieldsAtEntry.get(block)
: new IdentityHashMap<>();
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction instruction = it.next();
if (instruction.isFieldInstruction()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
index 7d655ae..9dc651c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ReflectionOptimizer.java
@@ -14,7 +14,7 @@
import com.android.tools.r8.ir.code.ConstClass;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -24,7 +24,7 @@
// Rewrite getClass() call to const-class if the type of the given instance is effectively final.
public static void rewriteGetClass(AppView<AppInfoWithLiveness> appView, IRCode code) {
- InstructionIterator it = code.instructionIterator();
+ InstructionListIterator it = code.instructionListIterator();
DexItemFactory dexItemFactory = appView.dexItemFactory();
while (it.hasNext()) {
Instruction current = it.next();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
index 6a55792..89e0f2d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
@@ -17,7 +17,7 @@
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeInterface;
import com.android.tools.r8.ir.code.InvokeStatic;
@@ -63,7 +63,7 @@
public static void rewrite(IRCode code, AppView<? extends AppInfoWithLiveness> appView) {
DexItemFactory factory = appView.dexItemFactory();
- InstructionIterator instructionIterator = code.instructionIterator();
+ InstructionListIterator instructionIterator = code.instructionListIterator();
while (instructionIterator.hasNext()) {
Instruction instruction = instructionIterator.next();
@@ -188,7 +188,7 @@
private final IRCode code;
private final InvokeStatic serviceLoaderLoad;
- private InstructionIterator iterator;
+ private InstructionListIterator iterator;
private MemberType memberType;
private Value valueArray;
private int index = 0;
@@ -196,7 +196,7 @@
public Rewriter(
AppView appView,
IRCode code,
- InstructionIterator iterator,
+ InstructionListIterator iterator,
InvokeStatic serviceLoaderLoad) {
this.appView = appView;
this.factory = appView.dexItemFactory();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
index f6293de..8d5bf96 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UninstantiatedTypeOptimization.java
@@ -379,7 +379,7 @@
if (blocksToBeRemoved.contains(block)) {
continue;
}
- InstructionListIterator instructionIterator = block.listIterator();
+ InstructionListIterator instructionIterator = block.listIterator(code);
while (instructionIterator.hasNext()) {
Instruction instruction = instructionIterator.next();
if (instruction.throwsOnNullInput()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/FieldValueHelper.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/FieldValueHelper.java
index 4a5b019..43784de 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/FieldValueHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/FieldValueHelper.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Phi.RegisterReadType;
import com.android.tools.r8.ir.code.Value;
@@ -115,8 +115,8 @@
}
private Value getValueDefinedInTheBlock(BasicBlock block, Instruction stopAt) {
- InstructionListIterator iterator = stopAt == null ?
- block.listIterator(block.getInstructions().size()) : block.listIterator(stopAt);
+ InstructionIterator iterator =
+ stopAt == null ? block.iterator(block.getInstructions().size()) : block.iterator(stopAt);
Instruction valueProducingInsn = null;
while (iterator.hasPrevious()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
index 53e0fc9..8d33db8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
@@ -182,7 +182,7 @@
final void processCode() {
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
- instructions = block.listIterator();
+ instructions = block.listIterator(code);
while (instructions.hasNext()) {
instructions.next().accept(this);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java
index eb2df21..b2db648 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java
@@ -7,7 +7,7 @@
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.LinearFlowInstructionIterator;
+import com.android.tools.r8.ir.code.LinearFlowInstructionListIterator;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.ListIterator;
@@ -39,21 +39,22 @@
while (blocksIterator.hasPrevious()) {
BasicBlock currentBlock = blocksIterator.previous();
InstructionListIterator it =
- new LinearFlowInstructionIterator(currentBlock, currentBlock.getInstructions().size());
+ new LinearFlowInstructionListIterator(
+ code, currentBlock, currentBlock.getInstructions().size());
boolean matched = false;
while (matched || it.hasPrevious()) {
if (!it.hasPrevious()) {
matched = false;
it =
- new LinearFlowInstructionIterator(
- currentBlock, currentBlock.getInstructions().size());
+ new LinearFlowInstructionListIterator(
+ code, currentBlock, currentBlock.getInstructions().size());
}
for (BasicBlockPeephole peepHole : peepholes) {
boolean localMatch = peepHole.match(it);
if (localMatch && peepHole.resetAfterMatch()) {
it =
- new LinearFlowInstructionIterator(
- currentBlock, currentBlock.getInstructions().size());
+ new LinearFlowInstructionListIterator(
+ code, currentBlock, currentBlock.getInstructions().size());
} else {
matched |= localMatch;
}
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 60c34a1..4815c1f 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
@@ -20,7 +20,7 @@
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.Phi;
@@ -278,9 +278,7 @@
assert candidateInfo != null;
// Find and remove instantiation and its users.
- InstructionIterator iterator = code.instructionIterator();
- while (iterator.hasNext()) {
- Instruction instruction = iterator.next();
+ for (Instruction instruction : code.instructions()) {
if (instruction.isNewInstance() &&
instruction.asNewInstance().clazz == candidateInfo.candidate.type) {
// Remove all usages
@@ -293,8 +291,8 @@
Value singletonValue = instruction.outValue();
assert singletonValue != null;
- singletonValue.uniqueUsers().forEach(Instruction::removeOrReplaceByDebugLocalRead);
- instruction.removeOrReplaceByDebugLocalRead();
+ singletonValue.uniqueUsers().forEach(user -> user.removeOrReplaceByDebugLocalRead(code));
+ instruction.removeOrReplaceByDebugLocalRead(code);
return;
}
}
@@ -315,18 +313,19 @@
.filter(get -> singletonFields.containsKey(get.getField()))
.collect(Collectors.toList());
- singletonFieldReads.forEach(read -> {
- DexField field = read.getField();
- CandidateInfo candidateInfo = singletonFields.get(field);
- assert candidateInfo != null;
- Value value = read.dest();
- if (value != null) {
- fixupStaticizedFieldReadUsers(code, value, field);
- }
- if (!candidateInfo.preserveRead.get()) {
- read.removeOrReplaceByDebugLocalRead();
- }
- });
+ singletonFieldReads.forEach(
+ read -> {
+ DexField field = read.getField();
+ CandidateInfo candidateInfo = singletonFields.get(field);
+ assert candidateInfo != null;
+ Value value = read.dest();
+ if (value != null) {
+ fixupStaticizedFieldReadUsers(code, value, field);
+ }
+ if (!candidateInfo.preserveRead.get()) {
+ read.removeOrReplaceByDebugLocalRead(code);
+ }
+ });
if (!candidateToHostMapping.isEmpty()) {
remapMovedCandidates(code);
@@ -490,12 +489,12 @@
List<Value> args = invoke.inValues();
invoke.replace(
new InvokeStatic(invoke.getInvokedMethod(), newValue, args.subList(1, args.size())),
- code.metadata());
+ code);
}
}
private void remapMovedCandidates(IRCode code) {
- InstructionIterator it = code.instructionIterator();
+ InstructionListIterator it = code.instructionListIterator();
while (it.hasNext()) {
Instruction instruction = it.next();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
index 152fcd8..7f2faef 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderOptimizer.java
@@ -21,7 +21,7 @@
import com.android.tools.r8.ir.code.DominatorTree.Assumption;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
@@ -354,10 +354,7 @@
private StringConcatenationAnalysis buildBuilderStateGraph(Set<Value> candidateBuilders) {
DominatorTree dominatorTree = new DominatorTree(code, Assumption.MAY_HAVE_UNREACHABLE_BLOCKS);
for (BasicBlock block : code.topologicallySortedBlocks()) {
- InstructionIterator it = block.listIterator();
- while (it.hasNext()) {
- Instruction instr = it.next();
-
+ for (Instruction instr : block.getInstructions()) {
if (instr.isNewInstance()
&& optimizationConfiguration.isBuilderType(instr.asNewInstance().clazz)) {
Value builder = instr.asNewInstance().dest();
@@ -506,7 +503,7 @@
final Set<Value> simplifiedBuilders = Sets.newIdentityHashSet();
private StringConcatenationAnalysis applyConcatenationResults(Set<Value> candidateBuilders) {
- InstructionIterator it = code.instructionIterator();
+ InstructionListIterator it = code.instructionListIterator();
while (it.hasNext()) {
Instruction instr = it.nextUntil(i -> isToStringOfInterest(candidateBuilders, i));
if (instr == null) {
@@ -634,7 +631,7 @@
}
// All instructions that refer to simplified builders are dead.
// Here, we remove append(...) calls, <init>, and new-instance in order.
- InstructionIterator it = code.instructionIterator();
+ InstructionListIterator it = code.instructionListIterator();
while (it.hasNext()) {
Instruction instr = it.next();
if (instr.isInvokeVirtual()) {
@@ -646,7 +643,7 @@
}
}
}
- it = code.instructionIterator();
+ it = code.instructionListIterator();
while (it.hasNext()) {
Instruction instr = it.next();
if (instr.isInvokeDirect()) {
@@ -658,7 +655,7 @@
}
}
}
- it = code.instructionIterator();
+ it = code.instructionListIterator();
while (it.hasNext()) {
Instruction instr = it.next();
if (instr.isNewInstance()
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
index 3adb9d4..1ccf6df 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
@@ -26,7 +26,7 @@
import com.android.tools.r8.ir.code.DexItemBasedConstString;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.Value;
@@ -66,7 +66,7 @@
if (!code.metadata().mayHaveConstString()) {
return;
}
- InstructionIterator it = code.instructionIterator();
+ InstructionListIterator it = code.instructionListIterator();
while (it.hasNext()) {
Instruction instr = it.next();
if (!instr.isInvokeVirtual()) {
@@ -207,7 +207,7 @@
return;
}
boolean markUseIdentifierNameString = false;
- InstructionIterator it = code.instructionIterator().recordChangesToMetadata(code);
+ InstructionListIterator it = code.instructionListIterator();
while (it.hasNext()) {
Instruction instr = it.next();
if (!instr.isInvokeVirtual()) {
@@ -353,7 +353,7 @@
// String#valueOf(String s) -> s
// str.toString() -> str
public void removeTrivialConversions(IRCode code) {
- InstructionIterator it = code.instructionIterator().recordChangesToMetadata(code);
+ InstructionListIterator it = code.instructionListIterator();
while (it.hasNext()) {
Instruction instr = it.next();
if (instr.isInvokeStatic()) {
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index 1a14543..8456912 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -222,9 +222,9 @@
// locals alive for their entire live range. In release mode the liveness is all that matters
// and we do not actually want locals information in the output.
if (options().debug) {
- computeDebugInfo(blocks, liveIntervals, this, liveAtEntrySets);
+ computeDebugInfo(code, blocks, liveIntervals, this, liveAtEntrySets);
} else if (code.method.getOptimizationInfo().isReachabilitySensitive()) {
- InstructionIterator it = code.instructionIterator();
+ InstructionListIterator it = code.instructionListIterator();
while (it.hasNext()) {
Instruction instruction = it.next();
if (instruction.isDebugLocalRead()) {
@@ -238,6 +238,7 @@
}
public static void computeDebugInfo(
+ IRCode code,
ImmutableList<BasicBlock> blocks,
List<LiveIntervals> liveIntervals,
RegisterAllocator allocator,
@@ -278,7 +279,7 @@
boolean isEntryBlock = true;
for (BasicBlock block : blocks) {
- InstructionListIterator instructionIterator = block.listIterator();
+ InstructionListIterator instructionIterator = block.listIterator(code);
Set<Value> liveLocalValues = new HashSet<>(liveAtEntrySets.get(block).liveLocalValues);
// Skip past arguments and open argument and phi locals.
if (isEntryBlock) {
@@ -746,7 +747,7 @@
private void removeSpillAndPhiMoves() {
for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction instruction = it.next();
if (isSpillInstruction(instruction)) {
@@ -2549,8 +2550,7 @@
}
addLiveRange(value, block, end, liveIntervals, options);
}
- ListIterator<Instruction> iterator =
- block.getInstructions().listIterator(block.getInstructions().size());
+ InstructionIterator iterator = block.iterator(block.getInstructions().size());
while (iterator.hasPrevious()) {
Instruction instruction = iterator.previous();
Value definition = instruction.outValue();
@@ -2663,7 +2663,7 @@
private void transformBridgeMethod() {
assert implementationIsBridge(code);
BasicBlock entry = code.entryBlock();
- InstructionListIterator iterator = entry.listIterator();
+ InstructionIterator iterator = entry.iterator();
// Create a mapping from argument values to their index, while scanning over the arguments.
Reference2IntMap<Value> argumentIndices = new Reference2IntArrayMap<>();
while (iterator.peekNext().isArgument()) {
@@ -2720,7 +2720,7 @@
if (code.blocks.size() > 1) {
return false;
}
- InstructionListIterator iterator = code.entryBlock().listIterator();
+ InstructionIterator iterator = code.entryBlock().iterator();
// Move forward to the first instruction after the definition of the arguments.
while (iterator.hasNext() && iterator.peekNext().isArgument()) {
iterator.next();
@@ -2913,7 +2913,7 @@
private void insertRangeInvokeMoves() {
for (BasicBlock block : code.blocks) {
- InstructionListIterator it = block.listIterator();
+ InstructionListIterator it = block.listIterator(code);
while (it.hasNext()) {
Instruction instruction = it.next();
if (instruction.isInvoke()) {
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
index aae72b4..a5506d9 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/SpillMoveSet.java
@@ -165,7 +165,7 @@
*/
public int scheduleAndInsertMoves(int tempRegister) {
for (BasicBlock block : code.blocks) {
- InstructionListIterator insertAt = block.listIterator();
+ InstructionListIterator insertAt = block.listIterator(code);
if (block == code.entryBlock()) {
// Move insertAt iterator to the first non-argument, such that moves for the arguments will
// be inserted after the last argument.
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
index c007b7b..725c68c 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
@@ -101,7 +101,7 @@
if (blocks != null && !blocks.contains(block)) {
continue;
}
- InstructionListIterator iterator = block.listIterator().recordChangesToMetadata(code);
+ InstructionListIterator iterator = block.listIterator(code);
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
// v_n <- "x.y.z" // in.definition
@@ -168,10 +168,10 @@
block.hasCatchHandlers() ? iterator.split(code, blocks) : block;
if (blockWithFieldInstruction != block) {
// If we split, add const-string at the end of the currently visiting block.
- iterator = block.listIterator(block.getInstructions().size() - 1);
+ iterator = block.listIterator(code, block.getInstructions().size() - 1);
iterator.add(decoupled);
// Restore the cursor and block.
- iterator = blockWithFieldInstruction.listIterator().recordChangesToMetadata(code);
+ iterator = blockWithFieldInstruction.listIterator(code);
assert iterator.peekNext() == fieldPut;
iterator.next();
} else {
@@ -239,7 +239,7 @@
iterator.replaceCurrentInstruction(decoupled);
iterator.nextUntil(instruction -> instruction == invoke);
} else {
- in.definition.replace(decoupled, code.metadata());
+ in.definition.replace(decoupled, code);
}
} else {
decoupled.setPosition(invoke.getPosition());
@@ -255,12 +255,11 @@
block.hasCatchHandlers() ? iterator.split(code, blocks) : block;
if (blockWithInvoke != block) {
// If we split, add const-string at the end of the currently visiting block.
- iterator =
- block.listIterator(block.getInstructions().size()).recordChangesToMetadata(code);
+ iterator = block.listIterator(code, block.getInstructions().size());
iterator.previous();
iterator.add(decoupled);
// Restore the cursor and block.
- iterator = blockWithInvoke.listIterator().recordChangesToMetadata(code);
+ iterator = blockWithInvoke.listIterator(code);
assert iterator.peekNext() == invoke;
iterator.next();
} else {
@@ -304,12 +303,11 @@
block.hasCatchHandlers() ? iterator.split(code, blocks) : block;
if (blockWithInvoke != block) {
// If we split, add const-string at the end of the currently visiting block.
- iterator =
- block.listIterator(block.getInstructions().size()).recordChangesToMetadata(code);
+ iterator = block.listIterator(code, block.getInstructions().size());
iterator.previous();
iterator.add(decoupled);
// Restore the cursor and block.
- iterator = blockWithInvoke.listIterator().recordChangesToMetadata(code);
+ iterator = blockWithInvoke.listIterator(code);
assert iterator.peekNext() == invoke;
iterator.next();
} else {
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
index 4b072806..8cfd094 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
@@ -21,7 +21,7 @@
import com.android.tools.r8.ir.code.ConstantValueUtils;
import com.android.tools.r8.ir.code.DexItemBasedConstString;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.InvokeVirtual;
@@ -401,7 +401,7 @@
// put into the array. Conservatively bail out if the content of the array cannot be statically
// computed.
BasicBlock block = newArray.getBlock();
- InstructionListIterator iterator = block.listIterator();
+ InstructionIterator iterator = block.iterator();
iterator.nextUntil(i -> i == newArray);
do {
while (iterator.hasNext()) {
@@ -453,7 +453,7 @@
if (block.getPredecessors().size() != 1) {
return null;
}
- iterator = block.listIterator();
+ iterator = block.iterator();
} while (iterator != null);
return null;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index e830d62..b7dcd14 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -54,6 +54,7 @@
import com.android.tools.r8.ir.code.ConstantValueUtils;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.Value;
@@ -85,7 +86,6 @@
import java.util.Deque;
import java.util.HashSet;
import java.util.IdentityHashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -2102,7 +2102,7 @@
DexType originHolder = method.method.holder;
Origin origin = appInfo.originFor(originHolder);
IRCode code = method.buildIR(appView, origin);
- Iterator<Instruction> iterator = code.instructionIterator();
+ InstructionIterator iterator = code.instructionIterator();
while (iterator.hasNext()) {
Instruction instruction = iterator.next();
handleReflectiveBehavior(method, instruction);
diff --git a/src/main/java/com/android/tools/r8/utils/IteratorUtils.java b/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
index abffa51..b6cbe41 100644
--- a/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/IteratorUtils.java
@@ -4,6 +4,10 @@
package com.android.tools.r8.utils;
+import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionIterator;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.function.Predicate;
@@ -35,6 +39,16 @@
}
}
+ /** @deprecated Use {@link #removeIf(InstructionListIterator, Predicate)} instead. */
+ @Deprecated
+ public static void removeIf(InstructionIterator iterator, Predicate<Instruction> predicate) {
+ throw new Unimplemented();
+ }
+
+ public static void removeIf(InstructionListIterator iterator, Predicate<Instruction> predicate) {
+ removeIf((Iterator<Instruction>) iterator, predicate);
+ }
+
public static <T> boolean allRemainingMatch(ListIterator<T> iterator, Predicate<T> predicate) {
return !anyRemainingMatch(iterator, remaining -> !predicate.test(remaining));
}
diff --git a/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java b/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java
index f22aa2e..cf8f3f4 100644
--- a/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java
+++ b/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java
@@ -17,11 +17,11 @@
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.List;
-import java.util.ListIterator;
import org.junit.Test;
/**
@@ -91,17 +91,17 @@
BasicBlock entryBlock = code.entryBlock();
BasicBlock tryBlock = code.blocks.get(1);
assertTrue(tryBlock.hasCatchHandlers());
- ListIterator<Instruction> it = entryBlock.getInstructions().listIterator();
+ InstructionListIterator it = entryBlock.listIterator(code);
Instruction constNumber = it.next();
while (!constNumber.isConstNumber()) {
constNumber = it.next();
}
- it.remove();
+ it.removeInstructionIgnoreOutValue();
Instruction add = it.next();
while (!add.isAdd()) {
add = it.next();
}
- it.remove();
+ it.removeInstructionIgnoreOutValue();
constNumber.setBlock(tryBlock);
add.setBlock(tryBlock);
tryBlock.getInstructions().add(0, add);
diff --git a/src/test/java/com/android/tools/r8/ir/BasicBlockIteratorTest.java b/src/test/java/com/android/tools/r8/ir/BasicBlockIteratorTest.java
index 989550b..9394934 100644
--- a/src/test/java/com/android/tools/r8/ir/BasicBlockIteratorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/BasicBlockIteratorTest.java
@@ -61,7 +61,7 @@
MethodSubject methodSubject = getMethodSubject(application, signature);
IRCode code = methodSubject.buildIR();
ListIterator<BasicBlock> blocks = code.listIterator();
- InstructionListIterator iter = blocks.next().listIterator();
+ InstructionListIterator iter = blocks.next().listIterator(code);
iter.nextUntil(i -> !i.isArgument());
iter.previous();
iter.split(code, 1, blocks);
diff --git a/src/test/java/com/android/tools/r8/ir/InlineTest.java b/src/test/java/com/android/tools/r8/ir/InlineTest.java
index 94ff10e..e20e882 100644
--- a/src/test/java/com/android/tools/r8/ir/InlineTest.java
+++ b/src/test/java/com/android/tools/r8/ir/InlineTest.java
@@ -38,7 +38,7 @@
public class InlineTest extends IrInjectionTestBase {
- public TestApplication buildTestApplication(
+ private TestApplication buildTestApplication(
DexApplication application,
InternalOptions options,
MethodSubject method,
@@ -134,7 +134,7 @@
// Run code inlining a.
test = codeForMethodReplaceTest(a, b);
- iterator = test.code.entryBlock().listIterator();
+ iterator = test.code.entryBlock().listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(0));
@@ -143,7 +143,7 @@
// Run code inlining b (where a is actually called).
test = codeForMethodReplaceTest(a, b);
- iterator = test.code.entryBlock().listIterator();
+ iterator = test.code.entryBlock().listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(1));
@@ -213,7 +213,7 @@
// Run code inlining a.
test = codeForMethodReplaceReturnVoidTest(1, 2);
- iterator = test.code.entryBlock().listIterator();
+ iterator = test.code.entryBlock().listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(0));
@@ -305,7 +305,7 @@
Set<BasicBlock> blocksToRemove = Sets.newIdentityHashSet();
while (blocksIterator.hasNext()) {
BasicBlock block = blocksIterator.next();
- iterator = block.listIterator();
+ iterator = block.listIterator(test.code);
Instruction invoke = iterator.nextUntil(Instruction::isInvoke);
if (invoke != null) {
iterator.previous();
@@ -323,7 +323,7 @@
inlinee = test.additionalCode.listIterator(3); // IR code for b's
while (blocksIterator.hasNext()) {
BasicBlock block = blocksIterator.next();
- iterator = block.listIterator();
+ iterator = block.listIterator(test.code);
Instruction invoke = iterator.nextUntil(Instruction::isInvoke);
if (invoke != null) {
iterator.previous();
@@ -427,7 +427,7 @@
// Run code inlining a.
test = codeForMethodReplaceTestWithCatchHandler(a, b, twoGuards);
- iterator = test.code.blocks.get(1).listIterator();
+ iterator = test.code.blocks.get(1).listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(0));
@@ -436,7 +436,7 @@
// Run code inlining b (where a is actually called).
test = codeForMethodReplaceTestWithCatchHandler(a, b, twoGuards);
- iterator = test.code.blocks.get(1).listIterator();
+ iterator = test.code.blocks.get(1).listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(1));
@@ -540,7 +540,7 @@
// Run code inlining a.
test = codeForInlineCanThrow(a, b, twoGuards);
- iterator = test.code.entryBlock().listIterator();
+ iterator = test.code.entryBlock().listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(0));
@@ -549,7 +549,7 @@
// Run code inlining b (where a is actually called).
test = codeForInlineCanThrow(a, b, twoGuards);
- iterator = test.code.entryBlock().listIterator();
+ iterator = test.code.entryBlock().listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(1));
@@ -651,7 +651,7 @@
// Run code inlining a.
test = codeForInlineAlwaysThrows(twoGuards);
- iterator = test.code.entryBlock().listIterator();
+ iterator = test.code.entryBlock().listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(0));
@@ -661,7 +661,7 @@
// Run code inlining b (where a is actually called).
test = codeForInlineAlwaysThrows(twoGuards);
- iterator = test.code.entryBlock().listIterator();
+ iterator = test.code.entryBlock().listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(1));
@@ -780,7 +780,7 @@
if (blocksToRemove.contains(block)) {
continue;
}
- iterator = block.listIterator();
+ iterator = block.listIterator(test.code);
Instruction invoke = iterator.nextUntil(Instruction::isInvoke);
if (invoke != null) {
iterator.previous();
@@ -804,7 +804,7 @@
if (blocksToRemove.contains(block)) {
continue;
}
- iterator = block.listIterator();
+ iterator = block.listIterator(test.code);
Instruction invoke = iterator.nextUntil(Instruction::isInvoke);
if (invoke != null) {
iterator.previous();
@@ -936,7 +936,7 @@
if (blocksToRemove.contains(block)) {
continue;
}
- iterator = block.listIterator();
+ iterator = block.listIterator(test.code);
Instruction invoke = iterator.nextUntil(Instruction::isInvoke);
if (invoke != null) {
iterator.previous();
@@ -960,7 +960,7 @@
if (blocksToRemove.contains(block)) {
continue;
}
- iterator = block.listIterator();
+ iterator = block.listIterator(test.code);
Instruction invoke = iterator.nextUntil(Instruction::isInvoke);
if (invoke != null) {
iterator.previous();
@@ -1169,7 +1169,7 @@
// Run code inlining a.
test = codeForInlineWithHandlersCanThrow(
a, b, c, twoGuards, callerHasCatchAll, inlineeHasCatchAll);
- iterator = test.code.blocks.get(1).listIterator();
+ iterator = test.code.blocks.get(1).listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(0));
@@ -1179,7 +1179,7 @@
// Run code inlining b (where a is actually called).
test = codeForInlineWithHandlersCanThrow(
a, b, c, twoGuards, callerHasCatchAll, inlineeHasCatchAll);
- iterator = test.code.blocks.get(1).listIterator();
+ iterator = test.code.blocks.get(1).listIterator(test.code);
iterator.nextUntil(Instruction::isInvoke);
iterator.previous();
iterator.inlineInvoke(test.appView, test.code, test.additionalCode.get(1));
diff --git a/src/test/java/com/android/tools/r8/ir/InstructionIteratorTest.java b/src/test/java/com/android/tools/r8/ir/InstructionIteratorTest.java
index 5ab4a24..10a30dc 100644
--- a/src/test/java/com/android/tools/r8/ir/InstructionIteratorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/InstructionIteratorTest.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.smali.SmaliBuilder;
import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
@@ -50,7 +49,7 @@
MethodSubject methodSubject = getMethodSubject(application, signature);
IRCode code = methodSubject.buildIR();
ListIterator<BasicBlock> blocks = code.listIterator();
- InstructionListIterator iter = blocks.next().listIterator();
+ InstructionListIterator iter = blocks.next().listIterator(code);
iter.nextUntil(i -> !i.isArgument());
iter.previous();
iter.split(code, 1, blocks);
@@ -62,7 +61,7 @@
IRCode code = simpleCode();
ListIterator<BasicBlock> blocks = code.listIterator();
- ListIterator<Instruction> instructions = blocks.next().listIterator();
+ InstructionListIterator instructions = blocks.next().listIterator(code);
thrown.expect(IllegalStateException.class);
instructions.remove();
}
@@ -73,7 +72,7 @@
ListIterator<BasicBlock> blocks = code.listIterator();
blocks.next();
- ListIterator<Instruction> instructions = blocks.next().listIterator();
+ InstructionListIterator instructions = blocks.next().listIterator(code);
instructions.next();
instructions.remove();
thrown.expect(IllegalStateException.class);
diff --git a/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java b/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
index 77ed1bf..fc61691 100644
--- a/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/IrInjectionTestBase.java
@@ -10,7 +10,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
import com.android.tools.r8.ir.conversion.IRConverter;
@@ -27,7 +27,6 @@
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.io.IOException;
import java.util.List;
-import java.util.ListIterator;
import java.util.concurrent.ExecutionException;
import org.antlr.runtime.RecognitionException;
@@ -98,7 +97,7 @@
public int countArgumentInstructions() {
int count = 0;
- ListIterator<Instruction> iterator = code.entryBlock().listIterator();
+ InstructionIterator iterator = code.entryBlock().iterator();
while (iterator.next().isArgument()) {
count++;
}
@@ -106,7 +105,7 @@
}
public InstructionListIterator listIteratorAt(BasicBlock block, int index) {
- InstructionListIterator iterator = block.listIterator();
+ InstructionListIterator iterator = block.listIterator(code);
for (int i = 0; i < index; i++) {
iterator.next();
}
diff --git a/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java b/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java
index c68810f..88785c4 100644
--- a/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java
+++ b/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.LinearFlowInstructionIterator;
+import com.android.tools.r8.ir.code.LinearFlowInstructionListIterator;
import com.android.tools.r8.jasmin.JasminBuilder;
import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
import com.android.tools.r8.utils.AndroidApp;
@@ -22,7 +22,7 @@
public class LinearFlowIteratorTest extends TestBase {
- IRCode branchingCode() throws Exception {
+ private IRCode branchingCode() throws Exception {
JasminBuilder jasminBuilder = new JasminBuilder();
@@ -58,14 +58,14 @@
IRCode code = methodSubject.buildIR();
ListIterator<BasicBlock> blocks = code.listIterator();
blocks.next();
- InstructionListIterator iter = blocks.next().listIterator();
+ InstructionListIterator iter = blocks.next().listIterator(code);
iter.nextUntil(i -> !i.isConstNumber());
iter.previous();
iter.split(code, blocks);
return code;
}
- IRCode simpleCode() throws Exception {
+ private IRCode simpleCode() throws Exception {
JasminBuilder jasminBuilder = new JasminBuilder();
@@ -92,7 +92,7 @@
MethodSubject method = getMethodSubject(app, "foo", "void", "bar", ImmutableList.of("int"));
IRCode code = method.buildIR();
ListIterator<BasicBlock> blocks = code.listIterator();
- InstructionListIterator iter = blocks.next().listIterator();
+ InstructionListIterator iter = blocks.next().listIterator(code);
iter.nextUntil(i -> !i.isArgument());
iter.split(code, 0, blocks);
return code;
@@ -101,35 +101,33 @@
@Test
public void hasNextWillCheckNextBlock() throws Exception {
IRCode code = simpleCode();
- InstructionListIterator it = new LinearFlowInstructionIterator(code.entryBlock());
- Instruction current = it.next();
- current = it.next();
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.entryBlock());
+ it.next();
+ it.next();
assert it.hasNext();
}
@Test
public void nextWillContinueThroughGotoBlocks() throws Exception {
IRCode code = simpleCode();
- InstructionListIterator it = new LinearFlowInstructionIterator(code.entryBlock());
- Instruction current;
- current = it.next(); // Argument
- current = it.next(); // ConstNumber 0/NULL
- current = it.next(); // ArrayGet
- current = it.next(); // Return;
- assert current.isReturn();
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.entryBlock());
+ it.next(); // Argument
+ it.next(); // ConstNumber 0/NULL
+ it.next(); // ArrayGet
+ assert it.next().isReturn(); // Return
}
@Test
public void hasPreviousWillCheckPreviousBlock() throws Exception {
IRCode code = simpleCode();
- InstructionListIterator it = new LinearFlowInstructionIterator(code.blocks.get(2));
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.blocks.get(2));
assert it.hasPrevious();
}
@Test
public void hasPreviousWillJumpOverGotos() throws Exception {
IRCode code = simpleCode();
- InstructionListIterator it = new LinearFlowInstructionIterator(code.blocks.get(2));
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.blocks.get(2));
assert it.previous().isConstNumber();
}
@@ -137,7 +135,7 @@
public void GoToFrontAndBackIsSameAmountOfInstructions() throws Exception {
IRCode code = simpleCode();
int moves = 0;
- InstructionListIterator it = new LinearFlowInstructionIterator(code.entryBlock());
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.entryBlock());
while (it.hasNext()) {
it.next();
moves++;
@@ -153,7 +151,7 @@
@Test
public void moveFromEmptyBlock() throws Exception {
IRCode code = simpleCode();
- InstructionListIterator it = new LinearFlowInstructionIterator(code.blocks.get(1));
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.blocks.get(1));
Instruction current = it.previous();
assertTrue(current.isConstNumber() && current.outValue().getTypeLattice().isReference());
it.next();
@@ -164,23 +162,23 @@
@Test
public void doNotChangeToNextBlockWhenNotLinearFlow() throws Exception {
IRCode code = branchingCode();
- InstructionListIterator it = new LinearFlowInstructionIterator(code.entryBlock());
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.entryBlock());
it.nextUntil((i) -> !i.isArgument());
- Instruction current = it.next();
+ it.next();
assert !it.hasNext();
}
@Test
public void doNotChangeToPreviousBlockWhenNotLinearFlow() throws Exception {
IRCode code = branchingCode();
- InstructionListIterator it = new LinearFlowInstructionIterator(code.blocks.get(4));
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.blocks.get(4));
assert !it.hasPrevious();
}
@Test
public void followLinearSubPathDown() throws Exception {
IRCode code = branchingCode();
- InstructionListIterator it = new LinearFlowInstructionIterator(code.blocks.get(1));
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.blocks.get(1));
Instruction current = null;
while (it.hasNext()) {
current = it.next();
@@ -191,7 +189,7 @@
@Test
public void followLinearSubPathUp() throws Exception {
IRCode code = branchingCode();
- InstructionListIterator it = new LinearFlowInstructionIterator(code.blocks.get(2));
+ InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.blocks.get(2));
Instruction current = null;
while (it.hasPrevious()) {
current = it.previous();
diff --git a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
index 35e89c1..111e8f1 100644
--- a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
+++ b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
@@ -354,7 +354,7 @@
List<BasicBlock> exitBlocks = new ArrayList<>(code.computeNormalExitBlocks());
for (BasicBlock originalReturnBlock : exitBlocks) {
InstructionListIterator iterator =
- originalReturnBlock.listIterator(originalReturnBlock.getInstructions().size());
+ originalReturnBlock.listIterator(code, originalReturnBlock.getInstructions().size());
Instruction ret = iterator.previous();
assert ret.isReturn();
BasicBlock newReturnBlock = iterator.split(code);
@@ -364,8 +364,8 @@
new Value(test.valueNumberGenerator.next(), TypeLatticeElement.INT, null);
Value newReturnValue =
new Value(test.valueNumberGenerator.next(), TypeLatticeElement.INT, null);
- Value oldReturnValue = newReturnBlock.listIterator().next().asReturn().returnValue();
- newReturnBlock.listIterator().next().asReturn().returnValue().replaceUsers(newReturnValue);
+ Value oldReturnValue = newReturnBlock.iterator().next().asReturn().returnValue();
+ newReturnBlock.iterator().next().asReturn().returnValue().replaceUsers(newReturnValue);
Instruction constInstruction = new ConstNumber(newConstValue, 10);
Instruction addInstruction =
new Add(NumericType.INT, newReturnValue, oldReturnValue, newConstValue);
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 c6c0d73..5782025 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
@@ -19,7 +19,6 @@
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.InstanceGet;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeMethodWithReceiver;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.NewInstance;
@@ -82,10 +81,8 @@
}
private void verifyLastInvoke(IRCode code, boolean npeCaught) {
- InstructionIterator it = code.instructionIterator();
boolean metInvokeVirtual = false;
- while (it.hasNext()) {
- Instruction instruction = it.next();
+ for (Instruction instruction : code.instructions()) {
if (instruction.isInvokeMethodWithReceiver()) {
InvokeMethodWithReceiver invoke = instruction.asInvokeMethodWithReceiver();
if (invoke.getInvokedMethod().name.toString().contains("hash")) {
diff --git a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java
index 803ca02..91fdee5 100644
--- a/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java
+++ b/src/test/java/com/android/tools/r8/ir/analysis/type/TypeAnalysisTest.java
@@ -22,7 +22,6 @@
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.InstanceOf;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeNewArray;
import com.android.tools.r8.ir.code.NewArrayEmpty;
import com.android.tools.r8.ir.code.NewInstance;
@@ -160,11 +159,9 @@
private static void fillArrayData(AppView<?> appView, CodeInspector inspector) {
MethodSubject test1Subject =
inspector.clazz("Test").method(new MethodSignature("test1", "int[]", ImmutableList.of()));
- IRCode irCode = test1Subject.buildIR();
+ IRCode code = test1Subject.buildIR();
Value array = null;
- InstructionIterator iterator = irCode.instructionIterator();
- while (iterator.hasNext()) {
- Instruction instruction = iterator.next();
+ for (Instruction instruction : code.instructions()) {
if (instruction instanceof NewArrayEmpty) {
array = instruction.outValue();
break;
@@ -172,26 +169,26 @@
}
assertNotNull(array);
final Value finalArray = array;
- forEachOutValue(irCode, (v, l) -> {
- if (v == finalArray) {
- assertTrue(l.isArrayType());
- ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
- assertTrue(lattice.getArrayMemberTypeAsMemberType().isPrimitive());
- assertEquals(1, lattice.getNesting());
- assertFalse(lattice.isNullable());
- }
- });
+ forEachOutValue(
+ code,
+ (v, l) -> {
+ if (v == finalArray) {
+ assertTrue(l.isArrayType());
+ ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
+ assertTrue(lattice.getArrayMemberTypeAsMemberType().isPrimitive());
+ assertEquals(1, lattice.getNesting());
+ assertFalse(lattice.isNullable());
+ }
+ });
}
// filled-new-array
private static void filledNewArray(AppView<?> appView, CodeInspector inspector) {
MethodSubject test4Subject =
inspector.clazz("Test").method(new MethodSignature("test4", "int[]", ImmutableList.of()));
- IRCode irCode = test4Subject.buildIR();
+ IRCode code = test4Subject.buildIR();
Value array = null;
- InstructionIterator iterator = irCode.instructionIterator();
- while (iterator.hasNext()) {
- Instruction instruction = iterator.next();
+ for (Instruction instruction : code.instructions()) {
if (instruction instanceof InvokeNewArray) {
array = instruction.outValue();
break;
@@ -199,15 +196,17 @@
}
assertNotNull(array);
final Value finalArray = array;
- forEachOutValue(irCode, (v, l) -> {
- if (v == finalArray) {
- assertTrue(l.isArrayType());
- ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
- assertTrue(lattice.getArrayMemberTypeAsMemberType().isPrimitive());
- assertEquals(1, lattice.getNesting());
- assertFalse(lattice.isNullable());
- }
- });
+ forEachOutValue(
+ code,
+ (v, l) -> {
+ if (v == finalArray) {
+ assertTrue(l.isArrayType());
+ ArrayTypeLatticeElement lattice = l.asArrayTypeLatticeElement();
+ assertTrue(lattice.getArrayMemberTypeAsMemberType().isPrimitive());
+ assertEquals(1, lattice.getNesting());
+ assertFalse(lattice.isNullable());
+ }
+ });
}
// Make sure the analysis does not hang.
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java
index bac6888..deec11f 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTest.java
@@ -35,22 +35,22 @@
AppView<?> appView = build(testClass);
CodeInspector codeInspector = new CodeInspector(appView.appInfo().app());
MethodSubject fooSubject = codeInspector.clazz(testClass.getName()).method(signature);
- IRCode irCode = fooSubject.buildIR();
- checkCountOfNonNull(irCode, 0);
+ IRCode code = fooSubject.buildIR();
+ checkCountOfNonNull(code, 0);
NonNullTracker nonNullTracker = new NonNullTracker(appView);
- nonNullTracker.addNonNull(irCode);
- assertTrue(irCode.isConsistentSSA());
- checkCountOfNonNull(irCode, expectedNumberOfNonNull);
+ nonNullTracker.addNonNull(code);
+ assertTrue(code.isConsistentSSA());
+ checkCountOfNonNull(code, expectedNumberOfNonNull);
if (testAugmentedIRCode != null) {
- testAugmentedIRCode.accept(irCode);
+ testAugmentedIRCode.accept(code);
}
- new CodeRewriter(appView, null).removeAssumeInstructions(irCode);
- assertTrue(irCode.isConsistentSSA());
- checkCountOfNonNull(irCode, 0);
+ new CodeRewriter(appView, null).removeAssumeInstructions(code);
+ assertTrue(code.isConsistentSSA());
+ checkCountOfNonNull(code, 0);
}
private static void checkCountOfNonNull(IRCode code, int expectedOccurrences) {
@@ -75,16 +75,16 @@
assertEquals(expectedOccurrences, count);
}
- private void checkInvokeGetsNonNullReceiver(IRCode irCode) {
- checkInvokeReceiver(irCode, true);
+ private void checkInvokeGetsNonNullReceiver(IRCode code) {
+ checkInvokeReceiver(code, true);
}
- private void checkInvokeGetsNullReceiver(IRCode irCode) {
- checkInvokeReceiver(irCode, false);
+ private void checkInvokeGetsNullReceiver(IRCode code) {
+ checkInvokeReceiver(code, false);
}
- private void checkInvokeReceiver(IRCode irCode, boolean isNotNull) {
- InstructionIterator it = irCode.instructionIterator();
+ private void checkInvokeReceiver(IRCode code, boolean isNotNull) {
+ InstructionIterator it = code.instructionIterator();
boolean metInvokeWithReceiver = false;
while (it.hasNext()) {
Instruction instruction = it.nextUntil(Instruction::isInvokeMethodWithReceiver);
@@ -146,10 +146,10 @@
NonNullAfterFieldAccess.class,
signature,
1,
- ircode -> {
+ code -> {
// There are two InstancePut instructions of interest.
int count = 0;
- InstructionIterator it = ircode.instructionIterator();
+ InstructionIterator it = code.instructionIterator();
while (it.hasNext()) {
Instruction instruction = it.nextUntil(Instruction::isInstancePut);
if (instruction == null) {