diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc
index 9468f76..a04a234 100644
--- a/dexlayout/dex_ir_builder.cc
+++ b/dexlayout/dex_ir_builder.cc
@@ -20,14 +20,226 @@
 #include <vector>
 
 #include "dex_ir_builder.h"
+
+#include "dex/code_item_accessors-inl.h"
+#include "dex/dex_file_exception_helpers.h"
 #include "dexlayout.h"
 
 namespace art {
 namespace dex_ir {
 
-static void CheckAndSetRemainingOffsets(const DexFile& dex_file,
-                                        Collections* collections,
-                                        const Options& options);
+static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
+  uint64_t value = 0;
+  for (uint32_t i = 0; i <= length; i++) {
+    value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
+  }
+  if (sign_extend) {
+    int shift = (7 - length) * 8;
+    return (static_cast<int64_t>(value) << shift) >> shift;
+  }
+  return value;
+}
+
+static uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) {
+  const uint8_t* stream = debug_info_stream;
+  DecodeUnsignedLeb128(&stream);  // line_start
+  uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
+  for (uint32_t i = 0; i < parameters_size; ++i) {
+    DecodeUnsignedLeb128P1(&stream);  // Parameter name.
+  }
+
+  for (;;)  {
+    uint8_t opcode = *stream++;
+    switch (opcode) {
+      case DexFile::DBG_END_SEQUENCE:
+        return stream - debug_info_stream;  // end of stream.
+      case DexFile::DBG_ADVANCE_PC:
+        DecodeUnsignedLeb128(&stream);  // addr_diff
+        break;
+      case DexFile::DBG_ADVANCE_LINE:
+        DecodeSignedLeb128(&stream);  // line_diff
+        break;
+      case DexFile::DBG_START_LOCAL:
+        DecodeUnsignedLeb128(&stream);  // register_num
+        DecodeUnsignedLeb128P1(&stream);  // name_idx
+        DecodeUnsignedLeb128P1(&stream);  // type_idx
+        break;
+      case DexFile::DBG_START_LOCAL_EXTENDED:
+        DecodeUnsignedLeb128(&stream);  // register_num
+        DecodeUnsignedLeb128P1(&stream);  // name_idx
+        DecodeUnsignedLeb128P1(&stream);  // type_idx
+        DecodeUnsignedLeb128P1(&stream);  // sig_idx
+        break;
+      case DexFile::DBG_END_LOCAL:
+      case DexFile::DBG_RESTART_LOCAL:
+        DecodeUnsignedLeb128(&stream);  // register_num
+        break;
+      case DexFile::DBG_SET_PROLOGUE_END:
+      case DexFile::DBG_SET_EPILOGUE_BEGIN:
+        break;
+      case DexFile::DBG_SET_FILE: {
+        DecodeUnsignedLeb128P1(&stream);  // name_idx
+        break;
+      }
+      default: {
+        break;
+      }
+    }
+  }
+}
+
+template<class T> class CollectionMap : public CollectionBase {
+ public:
+  CollectionMap() = default;
+  virtual ~CollectionMap() OVERRIDE { }
+
+  template <class... Args>
+  T* CreateAndAddItem(CollectionVector<T>& vector,
+                      bool eagerly_assign_offsets,
+                      uint32_t offset,
+                      Args&&... args) {
+    T* item = vector.CreateAndAddItem(std::forward<Args>(args)...);
+    DCHECK(!GetExistingObject(offset));
+    DCHECK(!item->OffsetAssigned());
+    if (eagerly_assign_offsets) {
+      item->SetOffset(offset);
+    }
+    AddItem(item, offset);
+    return item;
+  }
+
+  // Returns the existing item if it is already inserted, null otherwise.
+  T* GetExistingObject(uint32_t offset) {
+    auto it = collection_.find(offset);
+    return it != collection_.end() ? it->second : nullptr;
+  }
+
+  // Lower case for template interop with std::map.
+  uint32_t size() const { return collection_.size(); }
+  std::map<uint32_t, T*>& Collection() { return collection_; }
+
+ private:
+  std::map<uint32_t, T*> collection_;
+
+  // CollectionMaps do not own the objects they contain, therefore AddItem is supported
+  // rather than CreateAndAddItem.
+  void AddItem(T* object, uint32_t offset) {
+    auto it = collection_.emplace(offset, object);
+    CHECK(it.second) << "CollectionMap already has an object with offset " << offset << " "
+                     << " and address " << it.first->second;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(CollectionMap);
+};
+
+class BuilderMaps {
+ public:
+  BuilderMaps(Header* header, bool eagerly_assign_offsets)
+      : header_(header), eagerly_assign_offsets_(eagerly_assign_offsets) { }
+
+  void CreateStringId(const DexFile& dex_file, uint32_t i);
+  void CreateTypeId(const DexFile& dex_file, uint32_t i);
+  void CreateProtoId(const DexFile& dex_file, uint32_t i);
+  void CreateFieldId(const DexFile& dex_file, uint32_t i);
+  void CreateMethodId(const DexFile& dex_file, uint32_t i);
+  void CreateClassDef(const DexFile& dex_file, uint32_t i);
+  void CreateCallSiteId(const DexFile& dex_file, uint32_t i);
+  void CreateMethodHandleItem(const DexFile& dex_file, uint32_t i);
+
+  void CreateCallSitesAndMethodHandles(const DexFile& dex_file);
+
+  TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset);
+  EncodedArrayItem* CreateEncodedArrayItem(const DexFile& dex_file,
+                                           const uint8_t* static_data,
+                                           uint32_t offset);
+  AnnotationItem* CreateAnnotationItem(const DexFile& dex_file,
+                                       const DexFile::AnnotationItem* annotation);
+  AnnotationSetItem* CreateAnnotationSetItem(const DexFile& dex_file,
+      const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset);
+  AnnotationsDirectoryItem* CreateAnnotationsDirectoryItem(const DexFile& dex_file,
+      const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset);
+  CodeItem* DedupeOrCreateCodeItem(const DexFile& dex_file,
+                                   const DexFile::CodeItem* disk_code_item,
+                                   uint32_t offset,
+                                   uint32_t dex_method_index);
+  ClassData* CreateClassData(const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset);
+
+  void AddAnnotationsFromMapListSection(const DexFile& dex_file,
+                                        uint32_t start_offset,
+                                        uint32_t count);
+
+  void CheckAndSetRemainingOffsets(const DexFile& dex_file, const Options& options);
+
+  // Sort the vectors buy map order (same order that was used in the input file).
+  void SortVectorsByMapOrder();
+
+ private:
+  bool GetIdsFromByteCode(const CodeItem* code,
+                          std::vector<TypeId*>* type_ids,
+                          std::vector<StringId*>* string_ids,
+                          std::vector<MethodId*>* method_ids,
+                          std::vector<FieldId*>* field_ids);
+
+  bool GetIdFromInstruction(const Instruction* dec_insn,
+                            std::vector<TypeId*>* type_ids,
+                            std::vector<StringId*>* string_ids,
+                            std::vector<MethodId*>* method_ids,
+                            std::vector<FieldId*>* field_ids);
+
+  EncodedValue* ReadEncodedValue(const DexFile& dex_file, const uint8_t** data);
+  EncodedValue* ReadEncodedValue(const DexFile& dex_file,
+                                 const uint8_t** data,
+                                 uint8_t type,
+                                 uint8_t length);
+  void ReadEncodedValue(const DexFile& dex_file,
+                        const uint8_t** data,
+                        uint8_t type,
+                        uint8_t length,
+                        EncodedValue* item);
+
+  MethodItem GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii);
+
+  ParameterAnnotation* GenerateParameterAnnotation(
+      const DexFile& dex_file,
+      MethodId* method_id,
+      const DexFile::AnnotationSetRefList* annotation_set_ref_list,
+      uint32_t offset);
+
+  template <typename Type, class... Args>
+  Type* CreateAndAddIndexedItem(IndexedCollectionVector<Type>& vector,
+                                uint32_t offset,
+                                uint32_t index,
+                                Args&&... args) {
+    Type* item = vector.CreateAndAddIndexedItem(index, std::forward<Args>(args)...);
+    DCHECK(!item->OffsetAssigned());
+    if (eagerly_assign_offsets_) {
+      item->SetOffset(offset);
+    }
+    return item;
+  }
+
+  Header* header_;
+  // If we eagerly assign offsets during IR building or later after layout. Must be false if
+  // changing the layout is enabled.
+  bool eagerly_assign_offsets_;
+
+  // Note: maps do not have ownership.
+  CollectionMap<StringData> string_datas_map_;
+  CollectionMap<TypeList> type_lists_map_;
+  CollectionMap<EncodedArrayItem> encoded_array_items_map_;
+  CollectionMap<AnnotationItem> annotation_items_map_;
+  CollectionMap<AnnotationSetItem> annotation_set_items_map_;
+  CollectionMap<AnnotationSetRefList> annotation_set_ref_lists_map_;
+  CollectionMap<AnnotationsDirectoryItem> annotations_directory_items_map_;
+  CollectionMap<DebugInfoItem> debug_info_items_map_;
+  // Code item maps need to check both the debug info offset and debug info offset, do not use
+  // CollectionMap.
+  // First offset is the code item offset, second is the debug info offset.
+  std::map<std::pair<uint32_t, uint32_t>, CodeItem*> code_items_map_;
+  CollectionMap<ClassData> class_datas_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(BuilderMaps);
+};
 
 Header* DexIrBuilder(const DexFile& dex_file,
                      bool eagerly_assign_offsets,
@@ -50,36 +262,35 @@
                               dex_file.NumFieldIds(),
                               dex_file.NumMethodIds(),
                               dex_file.NumClassDefs());
-  Collections& collections = header->GetCollections();
-  collections.SetEagerlyAssignOffsets(eagerly_assign_offsets);
+  BuilderMaps builder_maps(header, eagerly_assign_offsets);
   // Walk the rest of the header fields.
   // StringId table.
-  collections.SetStringIdsOffset(disk_header.string_ids_off_);
+  header->StringIds().SetOffset(disk_header.string_ids_off_);
   for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
-    collections.CreateStringId(dex_file, i);
+    builder_maps.CreateStringId(dex_file, i);
   }
   // TypeId table.
-  collections.SetTypeIdsOffset(disk_header.type_ids_off_);
+  header->TypeIds().SetOffset(disk_header.type_ids_off_);
   for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
-    collections.CreateTypeId(dex_file, i);
+    builder_maps.CreateTypeId(dex_file, i);
   }
   // ProtoId table.
-  collections.SetProtoIdsOffset(disk_header.proto_ids_off_);
+  header->ProtoIds().SetOffset(disk_header.proto_ids_off_);
   for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
-    collections.CreateProtoId(dex_file, i);
+    builder_maps.CreateProtoId(dex_file, i);
   }
   // FieldId table.
-  collections.SetFieldIdsOffset(disk_header.field_ids_off_);
+  header->FieldIds().SetOffset(disk_header.field_ids_off_);
   for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
-    collections.CreateFieldId(dex_file, i);
+    builder_maps.CreateFieldId(dex_file, i);
   }
   // MethodId table.
-  collections.SetMethodIdsOffset(disk_header.method_ids_off_);
+  header->MethodIds().SetOffset(disk_header.method_ids_off_);
   for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
-    collections.CreateMethodId(dex_file, i);
+    builder_maps.CreateMethodId(dex_file, i);
   }
   // ClassDef table.
-  collections.SetClassDefsOffset(disk_header.class_defs_off_);
+  header->ClassDefs().SetOffset(disk_header.class_defs_off_);
   for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
     if (!options.class_filter_.empty()) {
       // If the filter is enabled (not empty), filter out classes that don't have a matching
@@ -90,29 +301,29 @@
         continue;
       }
     }
-    collections.CreateClassDef(dex_file, i);
+    builder_maps.CreateClassDef(dex_file, i);
   }
   // MapItem.
-  collections.SetMapListOffset(disk_header.map_off_);
+  header->SetMapListOffset(disk_header.map_off_);
   // CallSiteIds and MethodHandleItems.
-  collections.CreateCallSitesAndMethodHandles(dex_file);
-  CheckAndSetRemainingOffsets(dex_file, &collections, options);
+  builder_maps.CreateCallSitesAndMethodHandles(dex_file);
+  builder_maps.CheckAndSetRemainingOffsets(dex_file, options);
 
   // Sort the vectors by the map order (same order as the file).
-  collections.SortVectorsByMapOrder();
-  collections.ClearMaps();
+  builder_maps.SortVectorsByMapOrder();
 
   // Load the link data if it exists.
-  collections.SetLinkData(std::vector<uint8_t>(
+  header->SetLinkData(std::vector<uint8_t>(
       dex_file.DataBegin() + dex_file.GetHeader().link_off_,
       dex_file.DataBegin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_));
 
   return header;
 }
 
-static void CheckAndSetRemainingOffsets(const DexFile& dex_file,
-                                        Collections* collections,
-                                        const Options& options) {
+/*
+ * Get all the types, strings, methods, and fields referred to from bytecode.
+ */
+void BuilderMaps::CheckAndSetRemainingOffsets(const DexFile& dex_file, const Options& options) {
   const DexFile::Header& disk_header = dex_file.GetHeader();
   // Read MapItems and validate/set remaining offsets.
   const DexFile::MapList* map = dex_file.GetMapList();
@@ -125,74 +336,74 @@
         CHECK_EQ(item->offset_, 0u);
         break;
       case DexFile::kDexTypeStringIdItem:
-        CHECK_EQ(item->size_, collections->StringIdsSize());
-        CHECK_EQ(item->offset_, collections->StringIdsOffset());
+        CHECK_EQ(item->size_, header_->StringIds().Size());
+        CHECK_EQ(item->offset_, header_->StringIds().GetOffset());
         break;
       case DexFile::kDexTypeTypeIdItem:
-        CHECK_EQ(item->size_, collections->TypeIdsSize());
-        CHECK_EQ(item->offset_, collections->TypeIdsOffset());
+        CHECK_EQ(item->size_, header_->TypeIds().Size());
+        CHECK_EQ(item->offset_, header_->TypeIds().GetOffset());
         break;
       case DexFile::kDexTypeProtoIdItem:
-        CHECK_EQ(item->size_, collections->ProtoIdsSize());
-        CHECK_EQ(item->offset_, collections->ProtoIdsOffset());
+        CHECK_EQ(item->size_, header_->ProtoIds().Size());
+        CHECK_EQ(item->offset_, header_->ProtoIds().GetOffset());
         break;
       case DexFile::kDexTypeFieldIdItem:
-        CHECK_EQ(item->size_, collections->FieldIdsSize());
-        CHECK_EQ(item->offset_, collections->FieldIdsOffset());
+        CHECK_EQ(item->size_, header_->FieldIds().Size());
+        CHECK_EQ(item->offset_, header_->FieldIds().GetOffset());
         break;
       case DexFile::kDexTypeMethodIdItem:
-        CHECK_EQ(item->size_, collections->MethodIdsSize());
-        CHECK_EQ(item->offset_, collections->MethodIdsOffset());
+        CHECK_EQ(item->size_, header_->MethodIds().Size());
+        CHECK_EQ(item->offset_, header_->MethodIds().GetOffset());
         break;
       case DexFile::kDexTypeClassDefItem:
         if (options.class_filter_.empty()) {
           // The filter may have removed some classes, this will get fixed up during writing.
-          CHECK_EQ(item->size_, collections->ClassDefsSize());
+          CHECK_EQ(item->size_, header_->ClassDefs().Size());
         }
-        CHECK_EQ(item->offset_, collections->ClassDefsOffset());
+        CHECK_EQ(item->offset_, header_->ClassDefs().GetOffset());
         break;
       case DexFile::kDexTypeCallSiteIdItem:
-        CHECK_EQ(item->size_, collections->CallSiteIdsSize());
-        CHECK_EQ(item->offset_, collections->CallSiteIdsOffset());
+        CHECK_EQ(item->size_, header_->CallSiteIds().Size());
+        CHECK_EQ(item->offset_, header_->CallSiteIds().GetOffset());
         break;
       case DexFile::kDexTypeMethodHandleItem:
-        CHECK_EQ(item->size_, collections->MethodHandleItemsSize());
-        CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset());
+        CHECK_EQ(item->size_, header_->MethodHandleItems().Size());
+        CHECK_EQ(item->offset_, header_->MethodHandleItems().GetOffset());
         break;
       case DexFile::kDexTypeMapList:
         CHECK_EQ(item->size_, 1u);
         CHECK_EQ(item->offset_, disk_header.map_off_);
         break;
       case DexFile::kDexTypeTypeList:
-        collections->SetTypeListsOffset(item->offset_);
+        header_->TypeLists().SetOffset(item->offset_);
         break;
       case DexFile::kDexTypeAnnotationSetRefList:
-        collections->SetAnnotationSetRefListsOffset(item->offset_);
+        header_->AnnotationSetRefLists().SetOffset(item->offset_);
         break;
       case DexFile::kDexTypeAnnotationSetItem:
-        collections->SetAnnotationSetItemsOffset(item->offset_);
+        header_->AnnotationSetItems().SetOffset(item->offset_);
         break;
       case DexFile::kDexTypeClassDataItem:
-        collections->SetClassDatasOffset(item->offset_);
+        header_->ClassDatas().SetOffset(item->offset_);
         break;
       case DexFile::kDexTypeCodeItem:
-        collections->SetCodeItemsOffset(item->offset_);
+        header_->CodeItems().SetOffset(item->offset_);
         break;
       case DexFile::kDexTypeStringDataItem:
-        collections->SetStringDatasOffset(item->offset_);
+        header_->StringDatas().SetOffset(item->offset_);
         break;
       case DexFile::kDexTypeDebugInfoItem:
-        collections->SetDebugInfoItemsOffset(item->offset_);
+        header_->DebugInfoItems().SetOffset(item->offset_);
         break;
       case DexFile::kDexTypeAnnotationItem:
-        collections->SetAnnotationItemsOffset(item->offset_);
-        collections->AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_);
+        header_->AnnotationItems().SetOffset(item->offset_);
+        AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_);
         break;
       case DexFile::kDexTypeEncodedArrayItem:
-        collections->SetEncodedArrayItemsOffset(item->offset_);
+        header_->EncodedArrayItems().SetOffset(item->offset_);
         break;
       case DexFile::kDexTypeAnnotationsDirectoryItem:
-        collections->SetAnnotationsDirectoryItemsOffset(item->offset_);
+        header_->AnnotationsDirectoryItems().SetOffset(item->offset_);
         break;
       default:
         LOG(ERROR) << "Unknown map list item type.";
@@ -200,5 +411,798 @@
   }
 }
 
+void BuilderMaps::CreateStringId(const DexFile& dex_file, uint32_t i) {
+  const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i));
+  StringData* string_data =
+      string_datas_map_.CreateAndAddItem(header_->StringDatas(),
+                                         eagerly_assign_offsets_,
+                                         disk_string_id.string_data_off_,
+                                         dex_file.GetStringData(disk_string_id));
+  CreateAndAddIndexedItem(header_->StringIds(),
+                          header_->StringIds().GetOffset() + i * StringId::ItemSize(),
+                          i,
+                          string_data);
+}
+
+void BuilderMaps::CreateTypeId(const DexFile& dex_file, uint32_t i) {
+  const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i));
+  CreateAndAddIndexedItem(header_->TypeIds(),
+                          header_->TypeIds().GetOffset() + i * TypeId::ItemSize(),
+                          i,
+                          header_->StringIds()[disk_type_id.descriptor_idx_.index_]);
+}
+
+void BuilderMaps::CreateProtoId(const DexFile& dex_file, uint32_t i) {
+  const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(dex::ProtoIndex(i));
+  const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
+  TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_);
+
+  CreateAndAddIndexedItem(header_->ProtoIds(),
+                          header_->ProtoIds().GetOffset() + i * ProtoId::ItemSize(),
+                          i,
+                          header_->StringIds()[disk_proto_id.shorty_idx_.index_],
+                          header_->TypeIds()[disk_proto_id.return_type_idx_.index_],
+                          parameter_type_list);
+}
+
+void BuilderMaps::CreateFieldId(const DexFile& dex_file, uint32_t i) {
+  const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
+  CreateAndAddIndexedItem(header_->FieldIds(),
+                          header_->FieldIds().GetOffset() + i * FieldId::ItemSize(),
+                          i,
+                          header_->TypeIds()[disk_field_id.class_idx_.index_],
+                          header_->TypeIds()[disk_field_id.type_idx_.index_],
+                          header_->StringIds()[disk_field_id.name_idx_.index_]);
+}
+
+void BuilderMaps::CreateMethodId(const DexFile& dex_file, uint32_t i) {
+  const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
+  CreateAndAddIndexedItem(header_->MethodIds(),
+                          header_->MethodIds().GetOffset() + i * MethodId::ItemSize(),
+                          i,
+                          header_->TypeIds()[disk_method_id.class_idx_.index_],
+                          header_->ProtoIds()[disk_method_id.proto_idx_.index_],
+                          header_->StringIds()[disk_method_id.name_idx_.index_]);
+}
+
+void BuilderMaps::CreateClassDef(const DexFile& dex_file, uint32_t i) {
+  const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
+  const TypeId* class_type = header_->TypeIds()[disk_class_def.class_idx_.index_];
+  uint32_t access_flags = disk_class_def.access_flags_;
+  const TypeId* superclass = header_->GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_);
+
+  const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
+  TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_);
+
+  const StringId* source_file =
+      header_->GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_);
+  // Annotations.
+  AnnotationsDirectoryItem* annotations = nullptr;
+  const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
+      dex_file.GetAnnotationsDirectory(disk_class_def);
+  if (disk_annotations_directory_item != nullptr) {
+    annotations = CreateAnnotationsDirectoryItem(
+        dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
+  }
+  // Static field initializers.
+  const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
+  EncodedArrayItem* static_values =
+      CreateEncodedArrayItem(dex_file, static_data, disk_class_def.static_values_off_);
+  ClassData* class_data = CreateClassData(
+      dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
+  CreateAndAddIndexedItem(header_->ClassDefs(),
+                          header_->ClassDefs().GetOffset() + i * ClassDef::ItemSize(),
+                          i,
+                          class_type,
+                          access_flags,
+                          superclass,
+                          interfaces_type_list,
+                          source_file,
+                          annotations,
+                          static_values,
+                          class_data);
+}
+
+void BuilderMaps::CreateCallSiteId(const DexFile& dex_file, uint32_t i) {
+  const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i);
+  const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_;
+  EncodedArrayItem* call_site_item =
+      CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_);
+
+  CreateAndAddIndexedItem(header_->CallSiteIds(),
+                          header_->CallSiteIds().GetOffset() + i * CallSiteId::ItemSize(),
+                          i,
+                          call_site_item);
+}
+
+void BuilderMaps::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) {
+  const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i);
+  uint16_t index = disk_method_handle.field_or_method_idx_;
+  DexFile::MethodHandleType type =
+      static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_);
+  bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic ||
+                   type == DexFile::MethodHandleType::kInvokeInstance ||
+                   type == DexFile::MethodHandleType::kInvokeConstructor ||
+                   type == DexFile::MethodHandleType::kInvokeDirect ||
+                   type == DexFile::MethodHandleType::kInvokeInterface;
+  static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface,
+                "Unexpected method handle types.");
+  IndexedItem* field_or_method_id;
+  if (is_invoke) {
+    field_or_method_id = header_->MethodIds()[index];
+  } else {
+    field_or_method_id = header_->FieldIds()[index];
+  }
+  CreateAndAddIndexedItem(header_->MethodHandleItems(),
+                          header_->MethodHandleItems().GetOffset() +
+                              i * MethodHandleItem::ItemSize(),
+                          i,
+                          type,
+                          field_or_method_id);
+}
+
+void BuilderMaps::CreateCallSitesAndMethodHandles(const DexFile& dex_file) {
+  // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems.
+  const DexFile::MapList* map = dex_file.GetMapList();
+  for (uint32_t i = 0; i < map->size_; ++i) {
+    const DexFile::MapItem* item = map->list_ + i;
+    switch (item->type_) {
+      case DexFile::kDexTypeCallSiteIdItem:
+        header_->CallSiteIds().SetOffset(item->offset_);
+        break;
+      case DexFile::kDexTypeMethodHandleItem:
+        header_->MethodHandleItems().SetOffset(item->offset_);
+        break;
+      default:
+        break;
+    }
+  }
+  // Populate MethodHandleItems first (CallSiteIds may depend on them).
+  for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) {
+    CreateMethodHandleItem(dex_file, i);
+  }
+  // Populate CallSiteIds.
+  for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) {
+    CreateCallSiteId(dex_file, i);
+  }
+}
+
+TypeList* BuilderMaps::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) {
+  if (dex_type_list == nullptr) {
+    return nullptr;
+  }
+  TypeList* type_list = type_lists_map_.GetExistingObject(offset);
+  if (type_list == nullptr) {
+    TypeIdVector* type_vector = new TypeIdVector();
+    uint32_t size = dex_type_list->Size();
+    for (uint32_t index = 0; index < size; ++index) {
+      type_vector->push_back(header_->TypeIds()[
+                             dex_type_list->GetTypeItem(index).type_idx_.index_]);
+    }
+    type_list = type_lists_map_.CreateAndAddItem(header_->TypeLists(),
+                                                 eagerly_assign_offsets_,
+                                                 offset,
+                                                 type_vector);
+  }
+  return type_list;
+}
+
+EncodedArrayItem* BuilderMaps::CreateEncodedArrayItem(const DexFile& dex_file,
+                                                      const uint8_t* static_data,
+                                                      uint32_t offset) {
+  if (static_data == nullptr) {
+    return nullptr;
+  }
+  EncodedArrayItem* encoded_array_item = encoded_array_items_map_.GetExistingObject(offset);
+  if (encoded_array_item == nullptr) {
+    uint32_t size = DecodeUnsignedLeb128(&static_data);
+    EncodedValueVector* values = new EncodedValueVector();
+    for (uint32_t i = 0; i < size; ++i) {
+      values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, &static_data)));
+    }
+    // TODO: Calculate the size of the encoded array.
+    encoded_array_item = encoded_array_items_map_.CreateAndAddItem(header_->EncodedArrayItems(),
+                                                                   eagerly_assign_offsets_,
+                                                                   offset,
+                                                                   values);
+  }
+  return encoded_array_item;
+}
+
+void BuilderMaps::AddAnnotationsFromMapListSection(const DexFile& dex_file,
+                                                   uint32_t start_offset,
+                                                   uint32_t count) {
+  uint32_t current_offset = start_offset;
+  for (size_t i = 0; i < count; ++i) {
+    // Annotation that we didn't process already, add it to the set.
+    const DexFile::AnnotationItem* annotation = dex_file.GetAnnotationItemAtOffset(current_offset);
+    AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
+    DCHECK(annotation_item != nullptr);
+    current_offset += annotation_item->GetSize();
+  }
+}
+
+AnnotationItem* BuilderMaps::CreateAnnotationItem(const DexFile& dex_file,
+                                                  const DexFile::AnnotationItem* annotation) {
+  const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation);
+  const uint32_t offset = start_data - dex_file.DataBegin();
+  AnnotationItem* annotation_item = annotation_items_map_.GetExistingObject(offset);
+  if (annotation_item == nullptr) {
+    uint8_t visibility = annotation->visibility_;
+    const uint8_t* annotation_data = annotation->annotation_;
+    std::unique_ptr<EncodedValue> encoded_value(
+        ReadEncodedValue(dex_file, &annotation_data, DexFile::kDexAnnotationAnnotation, 0));
+    annotation_item =
+        annotation_items_map_.CreateAndAddItem(header_->AnnotationItems(),
+                                               eagerly_assign_offsets_,
+                                               offset,
+                                               visibility,
+                                               encoded_value->ReleaseEncodedAnnotation());
+    annotation_item->SetSize(annotation_data - start_data);
+  }
+  return annotation_item;
+}
+
+
+AnnotationSetItem* BuilderMaps::CreateAnnotationSetItem(const DexFile& dex_file,
+    const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) {
+  if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) {
+    return nullptr;
+  }
+  AnnotationSetItem* annotation_set_item = annotation_set_items_map_.GetExistingObject(offset);
+  if (annotation_set_item == nullptr) {
+    std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
+    for (uint32_t i = 0; i < disk_annotations_item->size_; ++i) {
+      const DexFile::AnnotationItem* annotation =
+          dex_file.GetAnnotationItem(disk_annotations_item, i);
+      if (annotation == nullptr) {
+        continue;
+      }
+      AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation);
+      items->push_back(annotation_item);
+    }
+    annotation_set_item =
+        annotation_set_items_map_.CreateAndAddItem(header_->AnnotationSetItems(),
+                                                   eagerly_assign_offsets_,
+                                                   offset,
+                                                   items);
+  }
+  return annotation_set_item;
+}
+
+AnnotationsDirectoryItem* BuilderMaps::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
+    const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
+  AnnotationsDirectoryItem* annotations_directory_item =
+      annotations_directory_items_map_.GetExistingObject(offset);
+  if (annotations_directory_item != nullptr) {
+    return annotations_directory_item;
+  }
+  const DexFile::AnnotationSetItem* class_set_item =
+      dex_file.GetClassAnnotationSet(disk_annotations_item);
+  AnnotationSetItem* class_annotation = nullptr;
+  if (class_set_item != nullptr) {
+    uint32_t item_offset = disk_annotations_item->class_annotations_off_;
+    class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, item_offset);
+  }
+  const DexFile::FieldAnnotationsItem* fields =
+      dex_file.GetFieldAnnotations(disk_annotations_item);
+  FieldAnnotationVector* field_annotations = nullptr;
+  if (fields != nullptr) {
+    field_annotations = new FieldAnnotationVector();
+    for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
+      FieldId* field_id = header_->FieldIds()[fields[i].field_idx_];
+      const DexFile::AnnotationSetItem* field_set_item =
+          dex_file.GetFieldAnnotationSetItem(fields[i]);
+      uint32_t annotation_set_offset = fields[i].annotations_off_;
+      AnnotationSetItem* annotation_set_item =
+          CreateAnnotationSetItem(dex_file, field_set_item, annotation_set_offset);
+      field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
+          new FieldAnnotation(field_id, annotation_set_item)));
+    }
+  }
+  const DexFile::MethodAnnotationsItem* methods =
+      dex_file.GetMethodAnnotations(disk_annotations_item);
+  MethodAnnotationVector* method_annotations = nullptr;
+  if (methods != nullptr) {
+    method_annotations = new MethodAnnotationVector();
+    for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
+      MethodId* method_id = header_->MethodIds()[methods[i].method_idx_];
+      const DexFile::AnnotationSetItem* method_set_item =
+          dex_file.GetMethodAnnotationSetItem(methods[i]);
+      uint32_t annotation_set_offset = methods[i].annotations_off_;
+      AnnotationSetItem* annotation_set_item =
+          CreateAnnotationSetItem(dex_file, method_set_item, annotation_set_offset);
+      method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
+          new MethodAnnotation(method_id, annotation_set_item)));
+    }
+  }
+  const DexFile::ParameterAnnotationsItem* parameters =
+      dex_file.GetParameterAnnotations(disk_annotations_item);
+  ParameterAnnotationVector* parameter_annotations = nullptr;
+  if (parameters != nullptr) {
+    parameter_annotations = new ParameterAnnotationVector();
+    for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
+      MethodId* method_id = header_->MethodIds()[parameters[i].method_idx_];
+      const DexFile::AnnotationSetRefList* list =
+          dex_file.GetParameterAnnotationSetRefList(&parameters[i]);
+      parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
+          GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
+    }
+  }
+  // TODO: Calculate the size of the annotations directory.
+  return annotations_directory_items_map_.CreateAndAddItem(header_->AnnotationsDirectoryItems(),
+                                                           eagerly_assign_offsets_,
+                                                           offset,
+                                                           class_annotation,
+                                                           field_annotations,
+                                                           method_annotations,
+                                                           parameter_annotations);
+}
+
+CodeItem* BuilderMaps::DedupeOrCreateCodeItem(const DexFile& dex_file,
+                                              const DexFile::CodeItem* disk_code_item,
+                                              uint32_t offset,
+                                              uint32_t dex_method_index) {
+  if (disk_code_item == nullptr) {
+    return nullptr;
+  }
+  CodeItemDebugInfoAccessor accessor(dex_file, disk_code_item, dex_method_index);
+  const uint32_t debug_info_offset = accessor.DebugInfoOffset();
+
+  // Create the offsets pair and dedupe based on it.
+  std::pair<uint32_t, uint32_t> offsets_pair(offset, debug_info_offset);
+  auto existing = code_items_map_.find(offsets_pair);
+  if (existing != code_items_map_.end()) {
+    return existing->second;
+  }
+
+  const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset);
+  DebugInfoItem* debug_info = nullptr;
+  if (debug_info_stream != nullptr) {
+    debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset);
+    if (debug_info == nullptr) {
+      uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream);
+      uint8_t* debug_info_buffer = new uint8_t[debug_info_size];
+      memcpy(debug_info_buffer, debug_info_stream, debug_info_size);
+      debug_info = debug_info_items_map_.CreateAndAddItem(header_->DebugInfoItems(),
+                                                          eagerly_assign_offsets_,
+                                                          debug_info_offset,
+                                                          debug_info_size,
+                                                          debug_info_buffer);
+    }
+  }
+
+  uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
+  uint16_t* insns = new uint16_t[insns_size];
+  memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t));
+
+  TryItemVector* tries = nullptr;
+  CatchHandlerVector* handler_list = nullptr;
+  if (accessor.TriesSize() > 0) {
+    tries = new TryItemVector();
+    handler_list = new CatchHandlerVector();
+    for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) {
+      uint32_t start_addr = disk_try_item.start_addr_;
+      uint16_t insn_count = disk_try_item.insn_count_;
+      uint16_t handler_off = disk_try_item.handler_off_;
+      const CatchHandler* handlers = nullptr;
+      for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
+        if (handler_off == existing_handlers->GetListOffset()) {
+          handlers = existing_handlers.get();
+          break;
+        }
+      }
+      if (handlers == nullptr) {
+        bool catch_all = false;
+        TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
+        for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) {
+          const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
+          const TypeId* type_id = header_->GetTypeIdOrNullPtr(type_index.index_);
+          catch_all |= type_id == nullptr;
+          addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>(
+              new TypeAddrPair(type_id, it.GetHandlerAddress())));
+        }
+        handlers = new CatchHandler(catch_all, handler_off, addr_pairs);
+        handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers));
+      }
+      TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
+      tries->push_back(std::unique_ptr<const TryItem>(try_item));
+    }
+    // Manually walk catch handlers list and add any missing handlers unreferenced by try items.
+    const uint8_t* handlers_base = accessor.GetCatchHandlerData();
+    const uint8_t* handlers_data = handlers_base;
+    uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
+    while (handlers_size > handler_list->size()) {
+      bool already_added = false;
+      uint16_t handler_off = handlers_data - handlers_base;
+      for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
+        if (handler_off == existing_handlers->GetListOffset()) {
+          already_added = true;
+          break;
+        }
+      }
+      int32_t size = DecodeSignedLeb128(&handlers_data);
+      bool has_catch_all = size <= 0;
+      if (has_catch_all) {
+        size = -size;
+      }
+      if (already_added) {
+        for (int32_t i = 0; i < size; i++) {
+          DecodeUnsignedLeb128(&handlers_data);
+          DecodeUnsignedLeb128(&handlers_data);
+        }
+        if (has_catch_all) {
+          DecodeUnsignedLeb128(&handlers_data);
+        }
+        continue;
+      }
+      TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
+      for (int32_t i = 0; i < size; i++) {
+        const TypeId* type_id =
+            header_->GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data));
+        uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
+        addr_pairs->push_back(
+            std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr)));
+      }
+      if (has_catch_all) {
+        uint32_t addr = DecodeUnsignedLeb128(&handlers_data);
+        addr_pairs->push_back(
+            std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr)));
+      }
+      const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs);
+      handler_list->push_back(std::unique_ptr<const CatchHandler>(handler));
+    }
+  }
+
+  uint32_t size = dex_file.GetCodeItemSize(*disk_code_item);
+  CodeItem* code_item = header_->CodeItems().CreateAndAddItem(accessor.RegistersSize(),
+                                                                  accessor.InsSize(),
+                                                                  accessor.OutsSize(),
+                                                                  debug_info,
+                                                                  insns_size,
+                                                                  insns,
+                                                                  tries,
+                                                                  handler_list);
+  code_item->SetSize(size);
+
+  // Add the code item to the map.
+  DCHECK(!code_item->OffsetAssigned());
+  if (eagerly_assign_offsets_) {
+    code_item->SetOffset(offset);
+  }
+  code_items_map_.emplace(offsets_pair, code_item);
+
+  // Add "fixup" references to types, strings, methods, and fields.
+  // This is temporary, as we will probably want more detailed parsing of the
+  // instructions here.
+  std::vector<TypeId*> type_ids;
+  std::vector<StringId*> string_ids;
+  std::vector<MethodId*> method_ids;
+  std::vector<FieldId*> field_ids;
+  if (GetIdsFromByteCode(code_item,
+                         /*out*/ &type_ids,
+                         /*out*/ &string_ids,
+                         /*out*/ &method_ids,
+                         /*out*/ &field_ids)) {
+    CodeFixups* fixups = new CodeFixups(std::move(type_ids),
+                                        std::move(string_ids),
+                                        std::move(method_ids),
+                                        std::move(field_ids));
+    code_item->SetCodeFixups(fixups);
+  }
+
+  return code_item;
+}
+
+ClassData* BuilderMaps::CreateClassData(
+    const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
+  // Read the fields and methods defined by the class, resolving the circular reference from those
+  // to classes by setting class at the same time.
+  ClassData* class_data = class_datas_map_.GetExistingObject(offset);
+  if (class_data == nullptr && encoded_data != nullptr) {
+    ClassDataItemIterator cdii(dex_file, encoded_data);
+    // Static fields.
+    FieldItemVector* static_fields = new FieldItemVector();
+    for (; cdii.HasNextStaticField(); cdii.Next()) {
+      FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()];
+      uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+      static_fields->emplace_back(access_flags, field_item);
+    }
+    // Instance fields.
+    FieldItemVector* instance_fields = new FieldItemVector();
+    for (; cdii.HasNextInstanceField(); cdii.Next()) {
+      FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()];
+      uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+      instance_fields->emplace_back(access_flags, field_item);
+    }
+    // Direct methods.
+    MethodItemVector* direct_methods = new MethodItemVector();
+    for (; cdii.HasNextDirectMethod(); cdii.Next()) {
+      direct_methods->push_back(GenerateMethodItem(dex_file, cdii));
+    }
+    // Virtual methods.
+    MethodItemVector* virtual_methods = new MethodItemVector();
+    for (; cdii.HasNextVirtualMethod(); cdii.Next()) {
+      virtual_methods->push_back(GenerateMethodItem(dex_file, cdii));
+    }
+    class_data = class_datas_map_.CreateAndAddItem(header_->ClassDatas(),
+                                                   eagerly_assign_offsets_,
+                                                   offset,
+                                                   static_fields,
+                                                   instance_fields,
+                                                   direct_methods,
+                                                   virtual_methods);
+    class_data->SetSize(cdii.EndDataPointer() - encoded_data);
+  }
+  return class_data;
+}
+
+void BuilderMaps::SortVectorsByMapOrder() {
+  header_->StringDatas().SortByMapOrder(string_datas_map_.Collection());
+  header_->TypeLists().SortByMapOrder(type_lists_map_.Collection());
+  header_->EncodedArrayItems().SortByMapOrder(encoded_array_items_map_.Collection());
+  header_->AnnotationItems().SortByMapOrder(annotation_items_map_.Collection());
+  header_->AnnotationSetItems().SortByMapOrder(annotation_set_items_map_.Collection());
+  header_->AnnotationSetRefLists().SortByMapOrder(annotation_set_ref_lists_map_.Collection());
+  header_->AnnotationsDirectoryItems().SortByMapOrder(
+      annotations_directory_items_map_.Collection());
+  header_->DebugInfoItems().SortByMapOrder(debug_info_items_map_.Collection());
+  header_->CodeItems().SortByMapOrder(code_items_map_);
+  header_->ClassDatas().SortByMapOrder(class_datas_map_.Collection());
+}
+
+bool BuilderMaps::GetIdsFromByteCode(const CodeItem* code,
+                                     std::vector<TypeId*>* type_ids,
+                                     std::vector<StringId*>* string_ids,
+                                     std::vector<MethodId*>* method_ids,
+                                     std::vector<FieldId*>* field_ids) {
+  bool has_id = false;
+  IterationRange<DexInstructionIterator> instructions = code->Instructions();
+  SafeDexInstructionIterator it(instructions.begin(), instructions.end());
+  for (; !it.IsErrorState() && it < instructions.end(); ++it) {
+    // In case the instruction goes past the end of the code item, make sure to not process it.
+    SafeDexInstructionIterator next = it;
+    ++next;
+    if (next.IsErrorState()) {
+      break;
+    }
+    has_id |= GetIdFromInstruction(&it.Inst(), type_ids, string_ids, method_ids, field_ids);
+  }  // for
+  return has_id;
+}
+
+bool BuilderMaps::GetIdFromInstruction(const Instruction* dec_insn,
+                                       std::vector<TypeId*>* type_ids,
+                                       std::vector<StringId*>* string_ids,
+                                       std::vector<MethodId*>* method_ids,
+                                       std::vector<FieldId*>* field_ids) {
+  // Determine index and width of the string.
+  uint32_t index = 0;
+  switch (Instruction::FormatOf(dec_insn->Opcode())) {
+    // SOME NOT SUPPORTED:
+    // case Instruction::k20bc:
+    case Instruction::k21c:
+    case Instruction::k35c:
+    // case Instruction::k35ms:
+    case Instruction::k3rc:
+    // case Instruction::k3rms:
+    // case Instruction::k35mi:
+    // case Instruction::k3rmi:
+    case Instruction::k45cc:
+    case Instruction::k4rcc:
+      index = dec_insn->VRegB();
+      break;
+    case Instruction::k31c:
+      index = dec_insn->VRegB();
+      break;
+    case Instruction::k22c:
+    // case Instruction::k22cs:
+      index = dec_insn->VRegC();
+      break;
+    default:
+      break;
+  }  // switch
+
+  // Determine index type, and add reference to the appropriate collection.
+  switch (Instruction::IndexTypeOf(dec_insn->Opcode())) {
+    case Instruction::kIndexTypeRef:
+      if (index < header_->TypeIds().Size()) {
+        type_ids->push_back(header_->TypeIds()[index]);
+        return true;
+      }
+      break;
+    case Instruction::kIndexStringRef:
+      if (index < header_->StringIds().Size()) {
+        string_ids->push_back(header_->StringIds()[index]);
+        return true;
+      }
+      break;
+    case Instruction::kIndexMethodRef:
+    case Instruction::kIndexMethodAndProtoRef:
+      if (index < header_->MethodIds().Size()) {
+        method_ids->push_back(header_->MethodIds()[index]);
+        return true;
+      }
+      break;
+    case Instruction::kIndexFieldRef:
+      if (index < header_->FieldIds().Size()) {
+        field_ids->push_back(header_->FieldIds()[index]);
+        return true;
+      }
+      break;
+    case Instruction::kIndexUnknown:
+    case Instruction::kIndexNone:
+    case Instruction::kIndexVtableOffset:
+    case Instruction::kIndexFieldOffset:
+    default:
+      break;
+  }  // switch
+  return false;
+}
+
+EncodedValue* BuilderMaps::ReadEncodedValue(const DexFile& dex_file, const uint8_t** data) {
+  const uint8_t encoded_value = *(*data)++;
+  const uint8_t type = encoded_value & 0x1f;
+  EncodedValue* item = new EncodedValue(type);
+  ReadEncodedValue(dex_file, data, type, encoded_value >> 5, item);
+  return item;
+}
+
+EncodedValue* BuilderMaps::ReadEncodedValue(const DexFile& dex_file,
+                                            const uint8_t** data,
+                                            uint8_t type,
+                                            uint8_t length) {
+  EncodedValue* item = new EncodedValue(type);
+  ReadEncodedValue(dex_file, data, type, length, item);
+  return item;
+}
+
+void BuilderMaps::ReadEncodedValue(const DexFile& dex_file,
+                                   const uint8_t** data,
+                                   uint8_t type,
+                                   uint8_t length,
+                                   EncodedValue* item) {
+  switch (type) {
+    case DexFile::kDexAnnotationByte:
+      item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
+      break;
+    case DexFile::kDexAnnotationShort:
+      item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
+      break;
+    case DexFile::kDexAnnotationChar:
+      item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
+      break;
+    case DexFile::kDexAnnotationInt:
+      item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
+      break;
+    case DexFile::kDexAnnotationLong:
+      item->SetLong(static_cast<int64_t>(ReadVarWidth(data, length, true)));
+      break;
+    case DexFile::kDexAnnotationFloat: {
+      // Fill on right.
+      union {
+        float f;
+        uint32_t data;
+      } conv;
+      conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
+      item->SetFloat(conv.f);
+      break;
+    }
+    case DexFile::kDexAnnotationDouble: {
+      // Fill on right.
+      union {
+        double d;
+        uint64_t data;
+      } conv;
+      conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
+      item->SetDouble(conv.d);
+      break;
+    }
+    case DexFile::kDexAnnotationMethodType: {
+      const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->SetProtoId(header_->ProtoIds()[proto_index]);
+      break;
+    }
+    case DexFile::kDexAnnotationMethodHandle: {
+      const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->SetMethodHandle(header_->MethodHandleItems()[method_handle_index]);
+      break;
+    }
+    case DexFile::kDexAnnotationString: {
+      const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->SetStringId(header_->StringIds()[string_index]);
+      break;
+    }
+    case DexFile::kDexAnnotationType: {
+      const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->SetTypeId(header_->TypeIds()[string_index]);
+      break;
+    }
+    case DexFile::kDexAnnotationField:
+    case DexFile::kDexAnnotationEnum: {
+      const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->SetFieldId(header_->FieldIds()[field_index]);
+      break;
+    }
+    case DexFile::kDexAnnotationMethod: {
+      const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+      item->SetMethodId(header_->MethodIds()[method_index]);
+      break;
+    }
+    case DexFile::kDexAnnotationArray: {
+      EncodedValueVector* values = new EncodedValueVector();
+      const uint32_t offset = *data - dex_file.DataBegin();
+      const uint32_t size = DecodeUnsignedLeb128(data);
+      // Decode all elements.
+      for (uint32_t i = 0; i < size; i++) {
+        values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(dex_file, data)));
+      }
+      EncodedArrayItem* array_item = new EncodedArrayItem(values);
+      if (eagerly_assign_offsets_) {
+        array_item->SetOffset(offset);
+      }
+      item->SetEncodedArray(array_item);
+      break;
+    }
+    case DexFile::kDexAnnotationAnnotation: {
+      AnnotationElementVector* elements = new AnnotationElementVector();
+      const uint32_t type_idx = DecodeUnsignedLeb128(data);
+      const uint32_t size = DecodeUnsignedLeb128(data);
+      // Decode all name=value pairs.
+      for (uint32_t i = 0; i < size; i++) {
+        const uint32_t name_index = DecodeUnsignedLeb128(data);
+        elements->push_back(std::unique_ptr<AnnotationElement>(
+            new AnnotationElement(header_->StringIds()[name_index],
+                                  ReadEncodedValue(dex_file, data))));
+      }
+      item->SetEncodedAnnotation(new EncodedAnnotation(header_->TypeIds()[type_idx], elements));
+      break;
+    }
+    case DexFile::kDexAnnotationNull:
+      break;
+    case DexFile::kDexAnnotationBoolean:
+      item->SetBoolean(length != 0);
+      break;
+    default:
+      break;
+  }
+}
+
+MethodItem BuilderMaps::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
+  MethodId* method_id = header_->MethodIds()[cdii.GetMemberIndex()];
+  uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+  const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
+  // Temporary hack to prevent incorrectly deduping code items if they have the same offset since
+  // they may have different debug info streams.
+  CodeItem* code_item = DedupeOrCreateCodeItem(dex_file,
+                                               disk_code_item,
+                                               cdii.GetMethodCodeItemOffset(),
+                                               cdii.GetMemberIndex());
+  return MethodItem(access_flags, method_id, code_item);
+}
+
+ParameterAnnotation* BuilderMaps::GenerateParameterAnnotation(
+    const DexFile& dex_file,
+    MethodId* method_id,
+    const DexFile::AnnotationSetRefList* annotation_set_ref_list,
+    uint32_t offset) {
+  AnnotationSetRefList* set_ref_list = annotation_set_ref_lists_map_.GetExistingObject(offset);
+  if (set_ref_list == nullptr) {
+    std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
+    for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
+      const DexFile::AnnotationSetItem* annotation_set_item =
+          dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
+      uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
+      annotations->push_back(CreateAnnotationSetItem(dex_file, annotation_set_item, set_offset));
+    }
+    set_ref_list =
+        annotation_set_ref_lists_map_.CreateAndAddItem(header_->AnnotationSetRefLists(),
+                                                       eagerly_assign_offsets_,
+                                                       offset,
+                                                       annotations);
+  }
+  return new ParameterAnnotation(method_id, set_ref_list);
+}
+
 }  // namespace dex_ir
 }  // namespace art
