summaryrefslogtreecommitdiffstats
path: root/compiler/dex
diff options
context:
space:
mode:
authorbuzbee <buzbee@google.com>2013-07-26 16:26:08 -0700
committerbuzbee <buzbee@google.com>2013-07-26 16:46:14 -0700
commit728328a441c6d3172283f3e44d120550997b5887 (patch)
tree886013afb34df67fa7d5feae0d007a508ec950d1 /compiler/dex
parent23d5cffcb8e32aaa6ce0895ade28849f72d90463 (diff)
downloadart-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.cc50
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);