Dexlayout cleanup and refactoring.

Created option to output to a mem map in preparation of hooking
dexlayout into dex2oat.

Test: mm test-art-host-gtest-dexlayout_test
Bug: 29921113
Change-Id: Id42ef15cb8f83cc8d05b025b7647a4338e9b96b0
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index 67f3e09..fe2bcce 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -56,6 +56,36 @@
                     entry.end_address_, entry.reg_)));
 }
 
+static uint32_t GetCodeItemSize(const DexFile& dex_file, const DexFile::CodeItem& disk_code_item) {
+  uintptr_t code_item_start = reinterpret_cast<uintptr_t>(&disk_code_item);
+  uint32_t insns_size = disk_code_item.insns_size_in_code_units_;
+  uint32_t tries_size = disk_code_item.tries_size_;
+  if (tries_size == 0) {
+    uintptr_t insns_end = reinterpret_cast<uintptr_t>(&disk_code_item.insns_[insns_size]);
+    return insns_end - code_item_start;
+  } else {
+    uint32_t last_handler_off = 0;
+    for (uint32_t i = 0; i < tries_size; ++i) {
+      // Iterate over the try items to find the last catch handler.
+      const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i);
+      uint16_t handler_off = disk_try_item->handler_off_;
+      if (handler_off > last_handler_off) {
+        last_handler_off = handler_off;
+      }
+    }
+    // Decode the final handler to see where it ends.
+    const uint8_t* handler_data = DexFile::GetCatchHandlerData(disk_code_item, last_handler_off);
+    int32_t uleb128_count = DecodeSignedLeb128(&handler_data) * 2;
+    if (uleb128_count <= 0) {
+      uleb128_count = -uleb128_count + 1;
+    }
+    for (int32_t i = 0; i < uleb128_count; ++i) {
+      DecodeUnsignedLeb128(&handler_data);
+    }
+    return reinterpret_cast<uintptr_t>(handler_data) - code_item_start;
+  }
+}
+
 static uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) {
   const uint8_t* stream = debug_info_stream;
   DecodeUnsignedLeb128(&stream);  // line_start
@@ -384,11 +414,9 @@
   if (dex_type_list == nullptr) {
     return nullptr;
   }
-  // TODO: Create more efficient lookup for existing type lists.
-  for (std::unique_ptr<TypeList>& type_list : TypeLists()) {
-    if (type_list->GetOffset() == offset) {
-      return type_list.get();
-    }
+  auto found_type_list = TypeLists().find(offset);
+  if (found_type_list != TypeLists().end()) {
+    return found_type_list->second.get();
   }
   TypeIdVector* type_vector = new TypeIdVector();
   uint32_t size = dex_type_list->Size();
@@ -404,10 +432,9 @@
   if (static_data == nullptr) {
     return nullptr;
   }
-  for (std::unique_ptr<EncodedArrayItem>& existing_array_item : EncodedArrayItems()) {
-    if (existing_array_item->GetOffset() == offset) {
-      return existing_array_item.get();
-    }
+  auto found_encoded_array_item = EncodedArrayItems().find(offset);
+  if (found_encoded_array_item != EncodedArrayItems().end()) {
+    return found_encoded_array_item->second.get();
   }
   uint32_t size = DecodeUnsignedLeb128(&static_data);
   EncodedValueVector* values = new EncodedValueVector();
@@ -422,10 +449,9 @@
 
 AnnotationItem* Collections::CreateAnnotationItem(const DexFile::AnnotationItem* annotation,
                                                   uint32_t offset) {
-  for (std::unique_ptr<AnnotationItem>& existing_annotation_item : AnnotationItems()) {
-    if (existing_annotation_item->GetOffset() == offset) {
-      return existing_annotation_item.get();
-    }
+  auto found_annotation_item = AnnotationItems().find(offset);
+  if (found_annotation_item != AnnotationItems().end()) {
+    return found_annotation_item->second.get();
   }
   uint8_t visibility = annotation->visibility_;
   const uint8_t* annotation_data = annotation->annotation_;
@@ -444,10 +470,9 @@
   if (disk_annotations_item.size_ == 0 && offset == 0) {
     return nullptr;
   }
-  for (std::unique_ptr<AnnotationSetItem>& existing_anno_set_item : AnnotationSetItems()) {
-    if (existing_anno_set_item->GetOffset() == offset) {
-      return existing_anno_set_item.get();
-    }
+  auto found_anno_set_item = AnnotationSetItems().find(offset);
+  if (found_anno_set_item != AnnotationSetItems().end()) {
+    return found_anno_set_item->second.get();
   }
   std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
   for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) {
@@ -467,10 +492,9 @@
 
 AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
     const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
-  for (std::unique_ptr<AnnotationsDirectoryItem>& anno_dir_item : AnnotationsDirectoryItems()) {
-    if (anno_dir_item->GetOffset() == offset) {
-      return anno_dir_item.get();
-    }
+  auto found_anno_dir_item = AnnotationsDirectoryItems().find(offset);
+  if (found_anno_dir_item != AnnotationsDirectoryItems().end()) {
+    return found_anno_dir_item->second.get();
   }
   const DexFile::AnnotationSetItem* class_set_item =
       dex_file.GetClassAnnotationSet(disk_annotations_item);
@@ -535,11 +559,9 @@
     const DexFile& dex_file, MethodId* method_id,
     const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) {
   AnnotationSetRefList* set_ref_list = nullptr;
-  for (std::unique_ptr<AnnotationSetRefList>& existing_set_ref_list : AnnotationSetRefLists()) {
-    if (existing_set_ref_list->GetOffset() == offset) {
-      set_ref_list = existing_set_ref_list.get();
-      break;
-    }
+  auto found_set_ref_list = AnnotationSetRefLists().find(offset);
+  if (found_set_ref_list != AnnotationSetRefLists().end()) {
+    set_ref_list = found_set_ref_list->second.get();
   }
   if (set_ref_list == nullptr) {
     std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
@@ -610,9 +632,10 @@
       tries->push_back(std::unique_ptr<const TryItem>(try_item));
     }
   }
-  // TODO: Calculate the size of the code item.
+  uint32_t size = GetCodeItemSize(dex_file, disk_code_item);
   CodeItem* code_item = new CodeItem(
       registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries, handler_list);
+  code_item->SetSize(size);
   code_items_.AddItem(code_item, offset);
   // Add "fixup" references to types, strings, methods, and fields.
   // This is temporary, as we will probably want more detailed parsing of the
@@ -690,8 +713,8 @@
       virtual_methods->push_back(
           std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
     }
-    // TODO: Calculate the size of the class data.
     class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
+    class_data->SetSize(cdii.EndDataPointer() - encoded_data);
     class_datas_.AddItem(class_data, offset);
   }
   return class_data;