diff options
author | buzbee <buzbee@google.com> | 2013-07-26 16:26:08 -0700 |
---|---|---|
committer | buzbee <buzbee@google.com> | 2013-07-26 16:46:14 -0700 |
commit | 728328a441c6d3172283f3e44d120550997b5887 (patch) | |
tree | 886013afb34df67fa7d5feae0d007a508ec950d1 /compiler/dex | |
parent | 23d5cffcb8e32aaa6ce0895ade28849f72d90463 (diff) | |
download | art-728328a441c6d3172283f3e44d120550997b5887.zip art-728328a441c6d3172283f3e44d120550997b5887.tar.gz art-728328a441c6d3172283f3e44d120550997b5887.tar.bz2 |
Support inline dex data
Dx always places switch table and array data following executable
code. However, embedding data inline appears to be legal - and
the Garmin Connect app does this. Unknown is what tool generated
the odd dex code. This CL reworks dex parsing to support inline data.
Further, a verification check to require a move-exception at
the beginning of catch regions is disabled. Dalvik's verifier appears
to only require that if a move-exception exists, it must be at
the beginning of the catch. If there is value to the check
requiring a move-exception, we'll need to enable it based on a
future dex version.
Change-Id: I80c78544993acb999f7c62d32479c3c8455b56cb
Diffstat (limited to 'compiler/dex')
-rw-r--r-- | compiler/dex/mir_graph.cc | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc index 264604c..76317aa 100644 --- a/compiler/dex/mir_graph.cc +++ b/compiler/dex/mir_graph.cc @@ -605,9 +605,6 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_ 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 +623,6 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_ 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 +631,50 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_ def_count_ += (df_flags & DF_A_WIDE) ? 2 : 1; } + // Check for inline data block signatures + if (opcode == Instruction::NOP) { + const uint16_t* tmp_code_ptr = code_ptr; + int tmp_width = 0; + uint16_t raw_instruction = *tmp_code_ptr; + bool embedded_data_block = true; + if (raw_instruction == 0x0000) { + // Could be an aligning nop - see if an embedded data block follows. + tmp_code_ptr++; + tmp_width++; + raw_instruction = *tmp_code_ptr; + } + if (raw_instruction == Instruction::kSparseSwitchSignature) { + tmp_width += (tmp_code_ptr[1] * 4) + 2; + } else if (raw_instruction == Instruction::kPackedSwitchSignature) { + tmp_width += (tmp_code_ptr[1] * 2) + 4; + } else if (raw_instruction == Instruction::kArrayDataSignature) { + int element_width = tmp_code_ptr[1]; + int num_elements = tmp_code_ptr[2] + (tmp_code_ptr[3] << 16); + tmp_width += (((num_elements * element_width) + 1) / 2) + 4; + } else { + // Just a normal nop - process as usual. + embedded_data_block = false; + AppendMIR(cur_block, insn); + } + if (embedded_data_block) { + width = tmp_width; + DCHECK(cur_block->fall_through == NULL); + DCHECK(cur_block->taken == NULL); + // No fallthrough for this block + flags = 0; + df_flags = 0; + // If there's more code following, make sure there's a basic block to attach it to. + if ((code_ptr + width) < code_end) { + FindBlock(current_offset_ + width, /* split */ false, /* create */ true, + /* immed_pred_block_p */ NULL); + } + } + } 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); |