Support inline dex data, take 2
Allow switch and array data blocks to appear interspersed
with Dex code (rather than just at the end).
Bug 10040419
Change-Id: Ia2850070f0e702381eb402f604d675e5a0b101de
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 6b010ed..86f6ee5 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -116,25 +116,10 @@
STLDeleteElements(&m_units_);
}
-bool MIRGraph::ContentIsInsn(const uint16_t* code_ptr) {
- uint16_t instr = *code_ptr;
- Instruction::Code opcode = static_cast<Instruction::Code>(instr & 0xff);
- /*
- * Since the low 8-bit in metadata may look like NOP, we need to check
- * both the low and whole sub-word to determine whether it is code or data.
- */
- return (opcode != Instruction::NOP || instr == 0);
-}
-
/*
* Parse an instruction, return the length of the instruction
*/
int MIRGraph::ParseInsn(const uint16_t* code_ptr, DecodedInstruction* decoded_instruction) {
- // Don't parse instruction data
- if (!ContentIsInsn(code_ptr)) {
- return 0;
- }
-
const Instruction* instruction = Instruction::At(code_ptr);
*decoded_instruction = DecodedInstruction(instruction);
@@ -349,11 +334,8 @@
cur_block->fall_through = fallthrough_block;
fallthrough_block->predecessors->Insert(cur_block);
} else if (code_ptr < code_end) {
- /* Create a fallthrough block for real instructions (incl. NOP) */
- if (ContentIsInsn(code_ptr)) {
- FindBlock(cur_offset + width, /* split */ false, /* create */ true,
+ FindBlock(cur_offset + width, /* split */ false, /* create */ true,
/* immed_pred_block_p */ NULL);
- }
}
return cur_block;
}
@@ -478,7 +460,7 @@
if (insn->dalvikInsn.opcode == Instruction::THROW) {
cur_block->explicit_throw = true;
- if ((code_ptr < code_end) && ContentIsInsn(code_ptr)) {
+ if (code_ptr < code_end) {
// Force creation of new block following THROW via side-effect
FindBlock(cur_offset + width, /* split */ false, /* create */ true,
/* immed_pred_block_p */ NULL);
@@ -605,9 +587,6 @@
opcode_count_[static_cast<int>(opcode)]++;
}
- /* Terminate when the data section is seen */
- if (width == 0)
- break;
/* Possible simple method? */
if (live_pattern) {
@@ -626,9 +605,6 @@
pattern_pos++;
}
- AppendMIR(cur_block, insn);
-
- code_ptr += width;
int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode);
int df_flags = oat_data_flow_attributes_[insn->dalvikInsn.opcode];
@@ -637,6 +613,33 @@
def_count_ += (df_flags & DF_A_WIDE) ? 2 : 1;
}
+ // Check for inline data block signatures
+ if (opcode == Instruction::NOP) {
+ // A simple NOP will have a width of 1 at this point, embedded data NOP > 1.
+ if ((width == 1) && ((current_offset_ & 0x1) == 0x1) && ((code_end - code_ptr) > 1)) {
+ // Could be an aligning nop. If an embedded data NOP follows, treat pair as single unit.
+ uint16_t following_raw_instruction = code_ptr[1];
+ if ((following_raw_instruction == Instruction::kSparseSwitchSignature) ||
+ (following_raw_instruction == Instruction::kPackedSwitchSignature) ||
+ (following_raw_instruction == Instruction::kArrayDataSignature)) {
+ width += Instruction::At(code_ptr + 1)->SizeInCodeUnits();
+ }
+ }
+ if (width == 1) {
+ // It is a simple nop - treat normally.
+ AppendMIR(cur_block, insn);
+ } else {
+ DCHECK(cur_block->fall_through == NULL);
+ DCHECK(cur_block->taken == NULL);
+ // Unreachable instruction, mark for no continuation.
+ flags &= ~Instruction::kContinue;
+ }
+ } else {
+ AppendMIR(cur_block, insn);
+ }
+
+ code_ptr += width;
+
if (flags & Instruction::kBranch) {
cur_block = ProcessCanBranch(cur_block, insn, current_offset_,
width, flags, code_ptr, code_end);
@@ -653,10 +656,8 @@
* Create a fallthrough block for real instructions
* (incl. NOP).
*/
- if (ContentIsInsn(code_ptr)) {
- FindBlock(current_offset_ + width, /* split */ false, /* create */ true,
- /* immed_pred_block_p */ NULL);
- }
+ FindBlock(current_offset_ + width, /* split */ false, /* create */ true,
+ /* immed_pred_block_p */ NULL);
}
} else if (flags & Instruction::kThrow) {
cur_block = ProcessCanThrow(cur_block, insn, current_offset_, width, flags, try_block_addr_,
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index aa6b29c..acb6557 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -526,12 +526,6 @@
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "exception handler starts at bad address (" << dex_pc << ")";
return false;
}
- const Instruction* inst = Instruction::At(code_item_->insns_ + dex_pc);
- if (inst->Opcode() != Instruction::MOVE_EXCEPTION) {
- Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "exception handler doesn't start with move-exception ("
- << dex_pc << ")";
- return false;
- }
insn_flags_[dex_pc].SetBranchTarget();
// Ensure exception types are resolved so that they don't need resolution to be delivered,
// unresolved exception types will be ignored by exception delivery