diff options
| -rw-r--r-- | dexlayout/dexlayout.cc | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index 6b0b0f8623..ffd11369cd 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -1794,6 +1794,10 @@ int32_t DexLayout::LayoutCodeItems(const DexFile* dex_file, } } + // Removing duplicate CodeItems may expose other issues with downstream + // optimizations such as quickening. But we need to ensure at least the weak + // forms of it currently in use do not break layout optimizations. + std::map<dex_ir::CodeItem*, uint32_t> original_code_item_offset; // Total_diff includes diffs generated by clinits, executed, and non-executed methods. int32_t total_diff = 0; // The relative placement has no effect on correctness; it is used to ensure @@ -1812,11 +1816,22 @@ int32_t DexLayout::LayoutCodeItems(const DexFile* dex_file, dex_ir::CodeItem* code_item = method->GetCodeItem(); if (code_item != nullptr && code_items_set.find(code_item) != code_items_set.end()) { - diff += UnsignedLeb128Size(code_item_offset) - - UnsignedLeb128Size(code_item->GetOffset()); - code_item->SetOffset(code_item_offset); - code_item_offset += - RoundUp(code_item->GetSize(), kDexCodeItemAlignment); + // Compute where the CodeItem was originally laid out. + uint32_t original_offset = code_item->GetOffset(); + auto it = original_code_item_offset.find(code_item); + if (it != original_code_item_offset.end()) { + original_offset = it->second; + } else { + original_code_item_offset[code_item] = code_item->GetOffset(); + // Assign the new offset and move the pointer to allocate space. + code_item->SetOffset(code_item_offset); + code_item_offset += + RoundUp(code_item->GetSize(), kDexCodeItemAlignment); + } + // Update the size of the encoded methods to reflect that the offset difference + // may have changed the ULEB128 length. + diff += + UnsignedLeb128Size(code_item->GetOffset()) - UnsignedLeb128Size(original_offset); } } } |