Update stack map verifier to check exception edges for all instructions
Bug: b/238047037
Change-Id: I1865be4ae18f8f14936e83dcc744e73e8abf6d97
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrameVerifier.java b/src/main/java/com/android/tools/r8/cf/code/CfFrameVerifier.java
index bdd6512..09cabd8 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrameVerifier.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrameVerifier.java
@@ -107,15 +107,17 @@
for (int i = 0; i < code.getInstructions().size(); i++) {
CfInstruction instruction = code.getInstruction(i);
assert !state.isError();
- // Check the exceptional edge prior to evaluating the instruction. The local state is stable
- // at this point as store operations are not throwing and the current stack does not
- // affect the exceptional transfer (the exception edge is always a singleton stack).
- if (instruction.canThrow()) {
- assert !instruction.isStore();
- state = checkExceptionEdges(state, labelToFrameMap);
- }
if (instruction.isLabel()) {
updateActiveCatchHandlers(instruction.asLabel());
+ } else {
+ // The ExceptionStackFrame is defined as the current frame having an empty operand stack.
+ // All instructions, not only throwing instructions, check the exception frame to be
+ // assignable to all exception edges.
+ // https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.10.1.9
+ if (appView.options().enableCheckAllInstructionsDuringStackMapVerification
+ || instruction.canThrow()) {
+ state = checkExceptionEdges(state, labelToFrameMap);
+ }
}
eventConsumer.acceptInstructionState(instruction, state);
state = instruction.evaluate(state, appView, config);
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 1ffb413..0c68c28 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -375,6 +375,9 @@
public boolean enableRedundantConstNumberOptimization = false;
public boolean enableLoopUnrolling = true;
+ // TODO(b/237567012): Remove when resolved.
+ public boolean enableCheckAllInstructionsDuringStackMapVerification = false;
+
public String synthesizedClassPrefix = "";
// Number of threads to use while processing the dex files.