Implement chaining up to the first 64 cases in a switch statement.
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 28d4d9f..1cd821f 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -506,8 +506,48 @@
cUnit.hasLoop = true;
}
+ if (lastInsn->dalvikInsn.opCode == OP_PACKED_SWITCH ||
+ lastInsn->dalvikInsn.opCode == OP_SPARSE_SWITCH) {
+ int i;
+ const u2 *switchData = desc->method->insns + lastInsn->offset +
+ lastInsn->dalvikInsn.vB;
+ int size = switchData[1];
+ int maxChains = MIN(size, MAX_CHAINED_SWITCH_CASES);
+
+ /*
+ * Generate the landing pad for cases whose ranks are higher than
+ * MAX_CHAINED_SWITCH_CASES. The code will re-enter the interpreter
+ * through the NoChain point.
+ */
+ if (maxChains != size) {
+ cUnit.switchOverflowPad =
+ desc->method->insns + lastInsn->offset;
+ }
+
+ s4 *targets = (s4 *) (switchData + 2 +
+ (lastInsn->dalvikInsn.opCode == OP_PACKED_SWITCH ?
+ 2 : size * 2));
+
+ /* One chaining cell for the first MAX_CHAINED_SWITCH_CASES cases */
+ for (i = 0; i < maxChains; i++) {
+ BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal);
+ lastBB->next = caseChain;
+ lastBB = caseChain;
+
+ caseChain->startOffset = lastInsn->offset + targets[i];
+ caseChain->id = numBlocks++;
+ }
+
+ /* One more chaining cell for the default case */
+ BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal);
+ lastBB->next = caseChain;
+ lastBB = caseChain;
+
+ caseChain->startOffset = lastInsn->offset + lastInsn->width;
+ caseChain->id = numBlocks++;
/* Fallthrough block not included in the trace */
- if (!isUnconditionalBranch(lastInsn) && curBB->fallThrough == NULL) {
+ } else if (!isUnconditionalBranch(lastInsn) &&
+ curBB->fallThrough == NULL) {
/*
* If the chaining cell is after an invoke or
* instruction that cannot change the control flow, request a hot