Fix chaining offset mis-calculation for translations w/ large switch statements.
Bug: 2369821
There are 12 bytes of additional code after the 65th chaining cell. So if a
switch statement with more than that many cases is translated by the JIT, it
will run fine until the next unchaining event, which will patch the wrong code
and lead to all kinds of unexpected crashes.
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index d6cb5d6..f92e347 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -3703,13 +3703,13 @@
/* Used to hold the labels of each block */
ArmLIR *labelList =
dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
- GrowableList chainingListByType[kChainingCellLast];
+ GrowableList chainingListByType[kChainingCellGap];
int i;
/*
* Initialize various types chaining lists.
*/
- for (i = 0; i < kChainingCellLast; i++) {
+ for (i = 0; i < kChainingCellGap; i++) {
dvmInitGrowableList(&chainingListByType[i], 2);
}
@@ -3756,7 +3756,7 @@
labelList[i].operands[0] = blockList[i]->startOffset;
- if (blockList[i]->blockType >= kChainingCellLast) {
+ if (blockList[i]->blockType >= kChainingCellGap) {
/*
* Append the label pseudo LIR first. Chaining cells will be handled
* separately afterwards.
@@ -4023,7 +4023,7 @@
}
/* Handle the chaining cells in predefined order */
- for (i = 0; i < kChainingCellLast; i++) {
+ for (i = 0; i < kChainingCellGap; i++) {
size_t j;
int *blockIdList = (int *) chainingListByType[i].elemList;
@@ -4076,6 +4076,9 @@
}
}
+ /* Mark the bottom of chaining cells */
+ cUnit->chainingCellBottom = (LIR *) newLIR0(cUnit, kArmChainingCellBottom);
+
/*
* Generate the branch to the dvmJitToInterpNoChain entry point at the end
* of all chaining cells for the overflow cases.