ART: Add dex::TypeIndex

Add abstraction for uint16_t type index.

Test: m test-art-host
Change-Id: I47708741c7c579cbbe59ab723c1e31c5fe71f83a
diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc
index b7c24ff..dfa1504 100644
--- a/compiler/optimizing/bounds_check_elimination_test.cc
+++ b/compiler/optimizing/bounds_check_elimination_test.cc
@@ -70,9 +70,9 @@
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
   HInstruction* parameter1 = new (&allocator_)
-      HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimNot);  // array
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);  // array
   HInstruction* parameter2 = new (&allocator_)
-      HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimInt);  // i
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);  // i
   entry->AddInstruction(parameter1);
   entry->AddInstruction(parameter2);
 
@@ -167,9 +167,9 @@
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
   HInstruction* parameter1 = new (&allocator_)
-      HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimNot);  // array
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);  // array
   HInstruction* parameter2 = new (&allocator_)
-      HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimInt);  // i
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);  // i
   entry->AddInstruction(parameter1);
   entry->AddInstruction(parameter2);
 
@@ -231,9 +231,9 @@
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
   HInstruction* parameter1 = new (&allocator_)
-      HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimNot);  // array
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);  // array
   HInstruction* parameter2 = new (&allocator_)
-      HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimInt);  // i
+      HParameterValue(graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);  // i
   entry->AddInstruction(parameter1);
   entry->AddInstruction(parameter2);
 
@@ -295,7 +295,7 @@
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
   HInstruction* parameter = new (&allocator_) HParameterValue(
-      graph_->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter);
 
   HInstruction* constant_5 = graph_->GetIntConstant(5);
@@ -364,7 +364,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter);
 
   HInstruction* constant_initial = graph->GetIntConstant(initial);
@@ -479,7 +479,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter);
 
   HInstruction* constant_initial = graph->GetIntConstant(initial);
@@ -600,7 +600,7 @@
       constant_10,
       graph->GetCurrentMethod(),
       0,
-      Primitive::kPrimInt,
+      dex::TypeIndex(static_cast<uint16_t>(Primitive::kPrimInt)),
       graph->GetDexFile(),
       kQuickAllocArray);
   block->AddInstruction(new_array);
@@ -692,7 +692,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter);
 
   HInstruction* constant_initial = graph->GetIntConstant(initial);
@@ -795,7 +795,7 @@
   graph_->AddBlock(entry);
   graph_->SetEntryBlock(entry);
   HInstruction* parameter = new (&allocator_) HParameterValue(
-      graph_->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter);
 
   HInstruction* constant_0 = graph_->GetIntConstant(0);
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index a341086..8a6b94e 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -383,7 +383,7 @@
     SaveLiveRegisters(codegen, locations);
 
     InvokeRuntimeCallingConvention calling_convention;
-    __ LoadImmediate(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex());
+    __ LoadImmediate(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex().index_);
     QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
                                                 : kQuickInitializeType;
     arm_codegen->InvokeRuntime(entrypoint, at_, dex_pc_, this);
@@ -3953,7 +3953,7 @@
 
 void InstructionCodeGeneratorARM::VisitNewArray(HNewArray* instruction) {
   InvokeRuntimeCallingConvention calling_convention;
-  __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex());
+  __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex().index_);
   // Note: if heap poisoning is enabled, the entry point takes cares
   // of poisoning the reference.
   codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
@@ -5743,7 +5743,7 @@
 void InstructionCodeGeneratorARM::VisitLoadClass(HLoadClass* cls) {
   LocationSummary* locations = cls->GetLocations();
   if (cls->NeedsAccessCheck()) {
-    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex());
+    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex().index_);
     codegen_->InvokeRuntime(kQuickInitializeTypeAndVerifyAccess, cls, cls->GetDexPc());
     CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
     return;
@@ -5830,7 +5830,7 @@
                         current_method,
                         ArtMethod::DexCacheResolvedTypesOffset(kArmPointerSize).Int32Value());
       // /* GcRoot<mirror::Class> */ out = out[type_index]
-      size_t offset = CodeGenerator::GetCacheOffset(cls->GetTypeIndex());
+      size_t offset = CodeGenerator::GetCacheOffset(cls->GetTypeIndex().index_);
       GenerateGcRootFieldLoad(cls, out_loc, out, offset, read_barrier_option);
       generate_null_check = !cls->IsInDexCache();
     }
@@ -7324,8 +7324,8 @@
 }
 
 CodeGeneratorARM::PcRelativePatchInfo* CodeGeneratorARM::NewPcRelativeTypePatch(
-    const DexFile& dex_file, uint32_t type_index) {
-  return NewPcRelativePatch(dex_file, type_index, &pc_relative_type_patches_);
+    const DexFile& dex_file, dex::TypeIndex type_index) {
+  return NewPcRelativePatch(dex_file, type_index.index_, &pc_relative_type_patches_);
 }
 
 CodeGeneratorARM::PcRelativePatchInfo* CodeGeneratorARM::NewPcRelativeDexCacheArrayPatch(
@@ -7347,7 +7347,7 @@
 }
 
 Literal* CodeGeneratorARM::DeduplicateBootImageTypeLiteral(const DexFile& dex_file,
-                                                           uint32_t type_index) {
+                                                           dex::TypeIndex type_index) {
   return boot_image_type_patches_.GetOrCreate(
       TypeReference(&dex_file, type_index),
       [this]() { return __ NewLiteral<uint32_t>(/* placeholder */ 0u); });
@@ -7452,7 +7452,7 @@
     uint32_t literal_offset = literal->GetLabel()->Position();
     linker_patches->push_back(LinkerPatch::TypePatch(literal_offset,
                                                      target_type.dex_file,
-                                                     target_type.type_index));
+                                                     target_type.type_index.index_));
   }
   EmitPcRelativeLinkerPatches<LinkerPatch::RelativeTypePatch>(pc_relative_type_patches_,
                                                               linker_patches);
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 8ace3da..a4ccb57 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -19,6 +19,7 @@
 
 #include "base/enums.h"
 #include "code_generator.h"
+#include "dex_file_types.h"
 #include "driver/compiler_options.h"
 #include "nodes.h"
 #include "string_reference.h"
@@ -481,11 +482,11 @@
   };
 
   PcRelativePatchInfo* NewPcRelativeStringPatch(const DexFile& dex_file, uint32_t string_index);
-  PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, uint32_t type_index);
+  PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
   PcRelativePatchInfo* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
                                                        uint32_t element_offset);
   Literal* DeduplicateBootImageStringLiteral(const DexFile& dex_file, uint32_t string_index);
-  Literal* DeduplicateBootImageTypeLiteral(const DexFile& dex_file, uint32_t type_index);
+  Literal* DeduplicateBootImageTypeLiteral(const DexFile& dex_file, dex::TypeIndex type_index);
   Literal* DeduplicateBootImageAddressLiteral(uint32_t address);
   Literal* DeduplicateDexCacheAddressLiteral(uint32_t address);
   Literal* DeduplicateJitStringLiteral(const DexFile& dex_file, uint32_t string_index);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index c9e563b..59e1784 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -288,7 +288,7 @@
     SaveLiveRegisters(codegen, locations);
 
     InvokeRuntimeCallingConvention calling_convention;
-    __ Mov(calling_convention.GetRegisterAt(0).W(), cls_->GetTypeIndex());
+    __ Mov(calling_convention.GetRegisterAt(0).W(), cls_->GetTypeIndex().index_);
     QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
                                                 : kQuickInitializeType;
     arm64_codegen->InvokeRuntime(entrypoint, at_, dex_pc_, this);
@@ -4102,9 +4102,9 @@
 
 vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativeTypePatch(
     const DexFile& dex_file,
-    uint32_t type_index,
+    dex::TypeIndex type_index,
     vixl::aarch64::Label* adrp_label) {
-  return NewPcRelativePatch(dex_file, type_index, adrp_label, &pc_relative_type_patches_);
+  return NewPcRelativePatch(dex_file, type_index.index_, adrp_label, &pc_relative_type_patches_);
 }
 
 vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativeDexCacheArrayPatch(
@@ -4136,7 +4136,7 @@
 }
 
 vixl::aarch64::Literal<uint32_t>* CodeGeneratorARM64::DeduplicateBootImageTypeLiteral(
-    const DexFile& dex_file, uint32_t type_index) {
+    const DexFile& dex_file, dex::TypeIndex type_index) {
   return boot_image_type_patches_.GetOrCreate(
       TypeReference(&dex_file, type_index),
       [this]() { return __ CreateLiteralDestroyedWithPool<uint32_t>(/* placeholder */ 0u); });
@@ -4257,7 +4257,7 @@
     vixl::aarch64::Literal<uint32_t>* literal = entry.second;
     linker_patches->push_back(LinkerPatch::TypePatch(literal->GetOffset(),
                                                      target_type.dex_file,
-                                                     target_type.type_index));
+                                                     target_type.type_index.index_));
   }
   EmitPcRelativeLinkerPatches<LinkerPatch::RelativeTypePatch>(pc_relative_type_patches_,
                                                                 linker_patches);
@@ -4381,7 +4381,7 @@
 
 void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) {
   if (cls->NeedsAccessCheck()) {
-    codegen_->MoveConstant(cls->GetLocations()->GetTemp(0), cls->GetTypeIndex());
+    codegen_->MoveConstant(cls->GetLocations()->GetTemp(0), cls->GetTypeIndex().index_);
     codegen_->InvokeRuntime(kQuickInitializeTypeAndVerifyAccess, cls, cls->GetDexPc());
     CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
     return;
@@ -4417,7 +4417,7 @@
       DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
       // Add ADRP with its PC-relative type patch.
       const DexFile& dex_file = cls->GetDexFile();
-      uint32_t type_index = cls->GetTypeIndex();
+      dex::TypeIndex type_index = cls->GetTypeIndex();
       vixl::aarch64::Label* adrp_label = codegen_->NewPcRelativeTypePatch(dex_file, type_index);
       codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
       // Add ADD with its PC-relative type patch.
@@ -4485,7 +4485,7 @@
       GenerateGcRootFieldLoad(cls,
                               out_loc,
                               out.X(),
-                              CodeGenerator::GetCacheOffset(cls->GetTypeIndex()),
+                              CodeGenerator::GetCacheOffset(cls->GetTypeIndex().index_),
                               /* fixup_label */ nullptr,
                               read_barrier_option);
       generate_null_check = !cls->IsInDexCache();
@@ -4775,7 +4775,7 @@
   InvokeRuntimeCallingConvention calling_convention;
   Register type_index = RegisterFrom(locations->GetTemp(0), Primitive::kPrimInt);
   DCHECK(type_index.Is(w0));
-  __ Mov(type_index, instruction->GetTypeIndex());
+  __ Mov(type_index, instruction->GetTypeIndex().index_);
   // Note: if heap poisoning is enabled, the entry point takes cares
   // of poisoning the reference.
   codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index a2ab607..1545fd3 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -20,6 +20,7 @@
 #include "arch/arm64/quick_method_frame_info_arm64.h"
 #include "code_generator.h"
 #include "common_arm64.h"
+#include "dex_file_types.h"
 #include "driver/compiler_options.h"
 #include "nodes.h"
 #include "parallel_move_resolver.h"
@@ -547,7 +548,7 @@
   // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
   // to the associated ADRP patch label).
   vixl::aarch64::Label* NewPcRelativeTypePatch(const DexFile& dex_file,
-                                               uint32_t type_index,
+                                               dex::TypeIndex type_index,
                                                vixl::aarch64::Label* adrp_label = nullptr);
 
   // Add a new PC-relative dex cache array patch for an instruction and return
@@ -562,7 +563,7 @@
   vixl::aarch64::Literal<uint32_t>* DeduplicateBootImageStringLiteral(const DexFile& dex_file,
                                                                       uint32_t string_index);
   vixl::aarch64::Literal<uint32_t>* DeduplicateBootImageTypeLiteral(const DexFile& dex_file,
-                                                                    uint32_t type_index);
+                                                                    dex::TypeIndex type_index);
   vixl::aarch64::Literal<uint32_t>* DeduplicateBootImageAddressLiteral(uint64_t address);
   vixl::aarch64::Literal<uint64_t>* DeduplicateDexCacheAddressLiteral(uint64_t address);
   vixl::aarch64::Literal<uint32_t>* DeduplicateJitStringLiteral(const DexFile& dex_file,
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 61e6b4b..b8d9a91 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -398,7 +398,7 @@
     SaveLiveRegisters(codegen, locations);
 
     InvokeRuntimeCallingConventionARMVIXL calling_convention;
-    __ Mov(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex());
+    __ Mov(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex().index_);
     QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
                                                 : kQuickInitializeType;
     arm_codegen->InvokeRuntime(entrypoint, at_, dex_pc_, this);
@@ -3217,7 +3217,7 @@
 
 void InstructionCodeGeneratorARMVIXL::VisitNewArray(HNewArray* instruction) {
   InvokeRuntimeCallingConventionARMVIXL calling_convention;
-  __ Mov(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex());
+  __ Mov(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex().index_);
   // Note: if heap poisoning is enabled, the entry point takes cares
   // of poisoning the reference.
   codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
@@ -4968,7 +4968,7 @@
 void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) {
   LocationSummary* locations = cls->GetLocations();
   if (cls->NeedsAccessCheck()) {
-    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex());
+    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex().index_);
     codegen_->InvokeRuntime(kQuickInitializeTypeAndVerifyAccess, cls, cls->GetDexPc());
     CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
     return;
@@ -5000,7 +5000,7 @@
           ArtMethod::DexCacheResolvedTypesOffset(kArmPointerSize).Int32Value();
       GetAssembler()->LoadFromOffset(kLoadWord, out, current_method, resolved_types_offset);
       // /* GcRoot<mirror::Class> */ out = out[type_index]
-      size_t offset = CodeGenerator::GetCacheOffset(cls->GetTypeIndex());
+      size_t offset = CodeGenerator::GetCacheOffset(cls->GetTypeIndex().index_);
       GenerateGcRootFieldLoad(cls, out_loc, out, offset, kEmitCompilerReadBarrier);
       generate_null_check = !cls->IsInDexCache();
       break;
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index fcbb8f0..8f94834 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -224,7 +224,7 @@
     SaveLiveRegisters(codegen, locations);
 
     InvokeRuntimeCallingConvention calling_convention;
-    __ LoadConst32(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex());
+    __ LoadConst32(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex().index_);
 
     QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
                                                 : kQuickInitializeType;
@@ -1056,7 +1056,7 @@
     uint32_t literal_offset = __ GetLabelLocation(literal->GetLabel());
     linker_patches->push_back(LinkerPatch::TypePatch(literal_offset,
                                                      target_type.dex_file,
-                                                     target_type.type_index));
+                                                     target_type.type_index.index_));
   }
   for (const auto& entry : boot_image_address_patches_) {
     DCHECK(GetCompilerOptions().GetIncludePatchInformation());
@@ -1073,8 +1073,8 @@
 }
 
 CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativeTypePatch(
-    const DexFile& dex_file, uint32_t type_index) {
-  return NewPcRelativePatch(dex_file, type_index, &pc_relative_type_patches_);
+    const DexFile& dex_file, dex::TypeIndex type_index) {
+  return NewPcRelativePatch(dex_file, type_index.index_, &pc_relative_type_patches_);
 }
 
 CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativeDexCacheArrayPatch(
@@ -1117,7 +1117,7 @@
 }
 
 Literal* CodeGeneratorMIPS::DeduplicateBootImageTypeLiteral(const DexFile& dex_file,
-                                                            uint32_t type_index) {
+                                                            dex::TypeIndex type_index) {
   return boot_image_type_patches_.GetOrCreate(
       TypeReference(&dex_file, type_index),
       [this]() { return __ NewLiteral<uint32_t>(/* placeholder */ 0u); });
@@ -5539,7 +5539,7 @@
 void InstructionCodeGeneratorMIPS::VisitLoadClass(HLoadClass* cls) {
   LocationSummary* locations = cls->GetLocations();
   if (cls->NeedsAccessCheck()) {
-    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex());
+    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex().index_);
     codegen_->InvokeRuntime(kQuickInitializeTypeAndVerifyAccess, cls, cls->GetDexPc());
     CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
     return;
@@ -5633,7 +5633,7 @@
                         base_or_current_method_reg,
                         ArtMethod::DexCacheResolvedTypesOffset(kArmPointerSize).Int32Value());
       // /* GcRoot<mirror::Class> */ out = out[type_index]
-      size_t offset = CodeGenerator::GetCacheOffset(cls->GetTypeIndex());
+      size_t offset = CodeGenerator::GetCacheOffset(cls->GetTypeIndex().index_);
       GenerateGcRootFieldLoad(cls, out_loc, out, offset);
       generate_null_check = !cls->IsInDexCache();
     }
@@ -5975,7 +5975,7 @@
   Register current_method_register = calling_convention.GetRegisterAt(2);
   __ Lw(current_method_register, SP, kCurrentMethodStackOffset);
   // Move an uint16_t value to a register.
-  __ LoadConst32(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex());
+  __ LoadConst32(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex().index_);
   codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck,
                        void*, uint32_t, int32_t, ArtMethod*>();
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index e132819..e225d20 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -449,11 +449,11 @@
   };
 
   PcRelativePatchInfo* NewPcRelativeStringPatch(const DexFile& dex_file, uint32_t string_index);
-  PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, uint32_t type_index);
+  PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
   PcRelativePatchInfo* NewPcRelativeDexCacheArrayPatch(const DexFile& dex_file,
                                                        uint32_t element_offset);
   Literal* DeduplicateBootImageStringLiteral(const DexFile& dex_file, uint32_t string_index);
-  Literal* DeduplicateBootImageTypeLiteral(const DexFile& dex_file, uint32_t type_index);
+  Literal* DeduplicateBootImageTypeLiteral(const DexFile& dex_file, dex::TypeIndex type_index);
   Literal* DeduplicateBootImageAddressLiteral(uint32_t address);
 
   void EmitPcRelativeAddressPlaceholder(PcRelativePatchInfo* info, Register out, Register base);
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 1a54935..02b01c8 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -180,7 +180,7 @@
     SaveLiveRegisters(codegen, locations);
 
     InvokeRuntimeCallingConvention calling_convention;
-    __ LoadConst32(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex());
+    __ LoadConst32(calling_convention.GetRegisterAt(0), cls_->GetTypeIndex().index_);
     QuickEntrypointEnum entrypoint = do_clinit_ ? kQuickInitializeStaticStorage
                                                 : kQuickInitializeType;
     mips64_codegen->InvokeRuntime(entrypoint, at_, dex_pc_, this);
@@ -3157,7 +3157,7 @@
 void InstructionCodeGeneratorMIPS64::VisitLoadClass(HLoadClass* cls) {
   LocationSummary* locations = cls->GetLocations();
   if (cls->NeedsAccessCheck()) {
-    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex());
+    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex().index_);
     codegen_->InvokeRuntime(kQuickInitializeTypeAndVerifyAccess, cls, cls->GetDexPc());
     CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
     return;
@@ -3174,7 +3174,7 @@
     __ LoadFromOffset(kLoadDoubleword, out, current_method,
                       ArtMethod::DexCacheResolvedTypesOffset(kMips64PointerSize).Int32Value());
     __ LoadFromOffset(
-        kLoadUnsignedWord, out, out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex()));
+        kLoadUnsignedWord, out, out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex().index_));
     // TODO: We will need a read barrier here.
     if (!cls->IsInDexCache() || cls->MustGenerateClinitCheck()) {
       DCHECK(cls->CanCallRuntime());
@@ -3382,7 +3382,8 @@
 void InstructionCodeGeneratorMIPS64::VisitNewArray(HNewArray* instruction) {
   LocationSummary* locations = instruction->GetLocations();
   // Move an uint16_t value to a register.
-  __ LoadConst32(locations->GetTemp(0).AsRegister<GpuRegister>(), instruction->GetTypeIndex());
+  __ LoadConst32(locations->GetTemp(0).AsRegister<GpuRegister>(),
+                 instruction->GetTypeIndex().index_);
   codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*>();
 }
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 3849437..51e902a 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -265,7 +265,7 @@
     SaveLiveRegisters(codegen, locations);
 
     InvokeRuntimeCallingConvention calling_convention;
-    __ movl(calling_convention.GetRegisterAt(0), Immediate(cls_->GetTypeIndex()));
+    __ movl(calling_convention.GetRegisterAt(0), Immediate(cls_->GetTypeIndex().index_));
     x86_codegen->InvokeRuntime(do_clinit_ ? kQuickInitializeStaticStorage
                                           : kQuickInitializeType,
                                at_, dex_pc_, this);
@@ -4168,7 +4168,7 @@
 
 void InstructionCodeGeneratorX86::VisitNewArray(HNewArray* instruction) {
   InvokeRuntimeCallingConvention calling_convention;
-  __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex()));
+  __ movl(calling_convention.GetRegisterAt(0), Immediate(instruction->GetTypeIndex().index_));
   // Note: if heap poisoning is enabled, the entry point takes cares
   // of poisoning the reference.
   codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
@@ -4612,7 +4612,7 @@
 }
 
 void CodeGeneratorX86::RecordTypePatch(HLoadClass* load_class) {
-  type_patches_.emplace_back(load_class->GetDexFile(), load_class->GetTypeIndex());
+  type_patches_.emplace_back(load_class->GetDexFile(), load_class->GetTypeIndex().index_);
   __ Bind(&type_patches_.back().label);
 }
 
@@ -6060,7 +6060,7 @@
 void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) {
   LocationSummary* locations = cls->GetLocations();
   if (cls->NeedsAccessCheck()) {
-    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex());
+    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex().index_);
     codegen_->InvokeRuntime(kQuickInitializeTypeAndVerifyAccess, cls, cls->GetDexPc());
     CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
     return;
@@ -6142,7 +6142,8 @@
       // /* GcRoot<mirror::Class> */ out = out[type_index]
       GenerateGcRootFieldLoad(cls,
                               out_loc,
-                              Address(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())),
+                              Address(out,
+                                      CodeGenerator::GetCacheOffset(cls->GetTypeIndex().index_)),
                               /* fixup_label */ nullptr,
                               read_barrier_option);
       generate_null_check = !cls->IsInDexCache();
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 02f5491..3467313 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -246,7 +246,8 @@
     SaveLiveRegisters(codegen, locations);
 
     InvokeRuntimeCallingConvention calling_convention;
-    __ movl(CpuRegister(calling_convention.GetRegisterAt(0)), Immediate(cls_->GetTypeIndex()));
+    __ movl(CpuRegister(calling_convention.GetRegisterAt(0)),
+            Immediate(cls_->GetTypeIndex().index_));
     x86_64_codegen->InvokeRuntime(do_clinit_ ? kQuickInitializeStaticStorage : kQuickInitializeType,
                                   at_,
                                   dex_pc_,
@@ -1110,7 +1111,7 @@
 }
 
 void CodeGeneratorX86_64::RecordTypePatch(HLoadClass* load_class) {
-  type_patches_.emplace_back(load_class->GetDexFile(), load_class->GetTypeIndex());
+  type_patches_.emplace_back(load_class->GetDexFile(), load_class->GetTypeIndex().index_);
   __ Bind(&type_patches_.back().label);
 }
 
@@ -4098,7 +4099,7 @@
 void InstructionCodeGeneratorX86_64::VisitNewArray(HNewArray* instruction) {
   InvokeRuntimeCallingConvention calling_convention;
   codegen_->Load64BitValue(CpuRegister(calling_convention.GetRegisterAt(0)),
-                           instruction->GetTypeIndex());
+                           instruction->GetTypeIndex().index_);
   // Note: if heap poisoning is enabled, the entry point takes cares
   // of poisoning the reference.
   codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc());
@@ -5485,7 +5486,7 @@
 void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) {
   LocationSummary* locations = cls->GetLocations();
   if (cls->NeedsAccessCheck()) {
-    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex());
+    codegen_->MoveConstant(locations->GetTemp(0), cls->GetTypeIndex().index_);
     codegen_->InvokeRuntime(kQuickInitializeTypeAndVerifyAccess, cls, cls->GetDexPc());
     CheckEntrypointTypes<kQuickInitializeTypeAndVerifyAccess, void*, uint32_t>();
     return;
@@ -5568,7 +5569,7 @@
       GenerateGcRootFieldLoad(
           cls,
           out_loc,
-          Address(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())),
+          Address(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex().index_)),
           /* fixup_label */ nullptr,
           read_barrier_option);
       generate_null_check = !cls->IsInDexCache();
diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc
index 5fac3ac..7ef28ed 100644
--- a/compiler/optimizing/constant_folding_test.cc
+++ b/compiler/optimizing/constant_folding_test.cc
@@ -756,7 +756,7 @@
 
   // Make various unsigned comparisons with zero against a parameter.
   HInstruction* parameter = new (&allocator_) HParameterValue(
-      graph_->GetDexFile(), 0, 0, Primitive::kPrimInt, true);
+      graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt, true);
   entry_block->AddInstruction(parameter);
   entry_block->AddInstruction(new (&allocator_) HGoto());
 
diff --git a/compiler/optimizing/gvn_test.cc b/compiler/optimizing/gvn_test.cc
index 6abf00e..437d35c 100644
--- a/compiler/optimizing/gvn_test.cc
+++ b/compiler/optimizing/gvn_test.cc
@@ -35,7 +35,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
-                                                             0,
+                                                             dex::TypeIndex(0),
                                                              0,
                                                              Primitive::kPrimNot);
   entry->AddInstruction(parameter);
@@ -120,7 +120,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
-                                                             0,
+                                                             dex::TypeIndex(0),
                                                              0,
                                                              Primitive::kPrimNot);
   entry->AddInstruction(parameter);
@@ -204,7 +204,7 @@
   graph->SetEntryBlock(entry);
 
   HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
-                                                             0,
+                                                             dex::TypeIndex(0),
                                                              0,
                                                              Primitive::kPrimNot);
   entry->AddInstruction(parameter);
@@ -352,7 +352,7 @@
   inner_loop_exit->AddSuccessor(outer_loop_header);
 
   HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
-                                                             0,
+                                                             dex::TypeIndex(0),
                                                              0,
                                                              Primitive::kPrimBoolean);
   entry->AddInstruction(parameter);
diff --git a/compiler/optimizing/induction_var_analysis_test.cc b/compiler/optimizing/induction_var_analysis_test.cc
index 031f1d7..3425b88 100644
--- a/compiler/optimizing/induction_var_analysis_test.cc
+++ b/compiler/optimizing/induction_var_analysis_test.cc
@@ -80,7 +80,7 @@
 
     // Provide entry and exit instructions.
     parameter_ = new (&allocator_) HParameterValue(
-        graph_->GetDexFile(), 0, 0, Primitive::kPrimNot, true);
+        graph_->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot, true);
     entry_->AddInstruction(parameter_);
     constant0_ = graph_->GetIntConstant(0);
     constant1_ = graph_->GetIntConstant(1);
diff --git a/compiler/optimizing/induction_var_range_test.cc b/compiler/optimizing/induction_var_range_test.cc
index 8bbdd4a..4c99e3c 100644
--- a/compiler/optimizing/induction_var_range_test.cc
+++ b/compiler/optimizing/induction_var_range_test.cc
@@ -62,9 +62,15 @@
     graph_->SetEntryBlock(entry_block_);
     graph_->SetExitBlock(exit_block_);
     // Two parameters.
-    x_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimInt);
+    x_ = new (&allocator_) HParameterValue(graph_->GetDexFile(),
+                                           dex::TypeIndex(0),
+                                           0,
+                                           Primitive::kPrimInt);
     entry_block_->AddInstruction(x_);
-    y_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimInt);
+    y_ = new (&allocator_) HParameterValue(graph_->GetDexFile(),
+                                           dex::TypeIndex(0),
+                                           0,
+                                           Primitive::kPrimInt);
     entry_block_->AddInstruction(y_);
     // Set arbitrary range analysis hint while testing private methods.
     SetHint(x_);
@@ -572,7 +578,8 @@
   HInstruction* new_array = new (&allocator_)
       HNewArray(x_,
                 graph_->GetCurrentMethod(),
-                0, Primitive::kPrimInt,
+                0,
+                dex::TypeIndex(Primitive::kPrimInt),
                 graph_->GetDexFile(),
                 kQuickAllocArray);
   entry_block_->AddInstruction(new_array);
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 7fe54b9..16a465a 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -197,15 +197,15 @@
   }
 }
 
-static uint32_t FindClassIndexIn(mirror::Class* cls,
-                                 const DexFile& dex_file,
-                                 Handle<mirror::DexCache> dex_cache)
+static dex::TypeIndex FindClassIndexIn(mirror::Class* cls,
+                                       const DexFile& dex_file,
+                                       Handle<mirror::DexCache> dex_cache)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  uint32_t index = DexFile::kDexNoIndex;
+  dex::TypeIndex index;
   if (cls->GetDexCache() == nullptr) {
     DCHECK(cls->IsArrayClass()) << cls->PrettyClass();
     index = cls->FindTypeIndexInOtherDexFile(dex_file);
-  } else if (cls->GetDexTypeIndex() == DexFile::kDexNoIndex16) {
+  } else if (!cls->GetDexTypeIndex().IsValid()) {
     DCHECK(cls->IsProxyClass()) << cls->PrettyClass();
     // TODO: deal with proxy classes.
   } else if (IsSameDexFile(cls->GetDexFile(), dex_file)) {
@@ -223,8 +223,8 @@
     // We cannot guarantee the entry in the dex cache will resolve to the same class,
     // as there may be different class loaders. So only return the index if it's
     // the right class in the dex cache already.
-    if (index != DexFile::kDexNoIndex && dex_cache->GetResolvedType(index) != cls) {
-      index = DexFile::kDexNoIndex;
+    if (index.IsValid() && dex_cache->GetResolvedType(index) != cls) {
+      index = dex::TypeIndex::Invalid();
     }
   }
 
@@ -363,9 +363,9 @@
       << invoke_instruction->DebugName();
 
   const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
-  uint32_t class_index = FindClassIndexIn(
+  dex::TypeIndex class_index = FindClassIndexIn(
       ic.GetMonomorphicType(), caller_dex_file, caller_compilation_unit_.GetDexCache());
-  if (class_index == DexFile::kDexNoIndex) {
+  if (!class_index.IsValid()) {
     VLOG(compiler) << "Call to " << ArtMethod::PrettyMethod(resolved_method)
                    << " from inline cache is not inlined because its class is not"
                    << " accessible to the caller";
@@ -417,7 +417,7 @@
 HInstruction* HInliner::AddTypeGuard(HInstruction* receiver,
                                      HInstruction* cursor,
                                      HBasicBlock* bb_cursor,
-                                     uint32_t class_index,
+                                     dex::TypeIndex class_index,
                                      bool is_referrer,
                                      HInstruction* invoke_instruction,
                                      bool with_deoptimization) {
@@ -489,10 +489,10 @@
     HInstruction* cursor = invoke_instruction->GetPrevious();
     HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
 
-    uint32_t class_index = FindClassIndexIn(
+    dex::TypeIndex class_index = FindClassIndexIn(
         ic.GetTypeAt(i), caller_dex_file, caller_compilation_unit_.GetDexCache());
     HInstruction* return_replacement = nullptr;
-    if (class_index == DexFile::kDexNoIndex ||
+    if (!class_index.IsValid() ||
         !TryBuildAndInline(invoke_instruction, method, &return_replacement)) {
       all_targets_inlined = false;
     } else {
diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h
index a1dcd58..682393e 100644
--- a/compiler/optimizing/inliner.h
+++ b/compiler/optimizing/inliner.h
@@ -17,6 +17,7 @@
 #ifndef ART_COMPILER_OPTIMIZING_INLINER_H_
 #define ART_COMPILER_OPTIMIZING_INLINER_H_
 
+#include "dex_file_types.h"
 #include "invoke_type.h"
 #include "optimization.h"
 
@@ -150,7 +151,7 @@
   HInstruction* AddTypeGuard(HInstruction* receiver,
                              HInstruction* cursor,
                              HBasicBlock* bb_cursor,
-                             uint32_t class_index,
+                             dex::TypeIndex class_index,
                              bool is_referrer,
                              HInstruction* invoke_instruction,
                              bool with_deoptimization)
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index b44137d..40de5ce 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -908,7 +908,7 @@
                       false /* is_unresolved */);
 }
 
-bool HInstructionBuilder::BuildNewInstance(uint16_t type_index, uint32_t dex_pc) {
+bool HInstructionBuilder::BuildNewInstance(dex::TypeIndex type_index, uint32_t dex_pc) {
   ScopedObjectAccess soa(Thread::Current());
   StackHandleScope<1> hs(soa.Self());
   Handle<mirror::DexCache> dex_cache = dex_compilation_unit_->GetDexCache();
@@ -1004,7 +1004,7 @@
   Handle<mirror::Class> resolved_method_class(hs.NewHandle(resolved_method->GetDeclaringClass()));
 
   // The index at which the method's class is stored in the DexCache's type array.
-  uint32_t storage_index = DexFile::kDexNoIndex;
+  dex::TypeIndex storage_index;
   bool is_outer_class = (resolved_method->GetDeclaringClass() == outer_class.Get());
   if (is_outer_class) {
     storage_index = outer_class->GetDexTypeIndex();
@@ -1021,7 +1021,7 @@
 
   if (IsInitialized(resolved_method_class)) {
     *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
-  } else if (storage_index != DexFile::kDexNoIndex) {
+  } else if (storage_index.IsValid()) {
     *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
     HLoadClass* load_class = new (arena_) HLoadClass(
         graph_->GetCurrentMethod(),
@@ -1297,7 +1297,7 @@
   return GetClassFrom(compiler_driver_, *dex_compilation_unit_);
 }
 
-bool HInstructionBuilder::IsOutermostCompilingClass(uint16_t type_index) const {
+bool HInstructionBuilder::IsOutermostCompilingClass(dex::TypeIndex type_index) const {
   ScopedObjectAccess soa(Thread::Current());
   StackHandleScope<3> hs(soa.Self());
   Handle<mirror::DexCache> dex_cache = dex_compilation_unit_->GetDexCache();
@@ -1360,7 +1360,7 @@
   Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
 
   // The index at which the field's class is stored in the DexCache's type array.
-  uint32_t storage_index;
+  dex::TypeIndex storage_index;
   bool is_outer_class = (outer_class.Get() == resolved_field->GetDeclaringClass());
   if (is_outer_class) {
     storage_index = outer_class->GetDexTypeIndex();
@@ -1497,7 +1497,7 @@
 }
 
 void HInstructionBuilder::BuildFilledNewArray(uint32_t dex_pc,
-                                              uint32_t type_index,
+                                              dex::TypeIndex type_index,
                                               uint32_t number_of_vreg_arguments,
                                               bool is_range,
                                               uint32_t* args,
@@ -1644,7 +1644,7 @@
 void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction,
                                          uint8_t destination,
                                          uint8_t reference,
-                                         uint16_t type_index,
+                                         dex::TypeIndex type_index,
                                          uint32_t dex_pc) {
   ScopedObjectAccess soa(Thread::Current());
   StackHandleScope<1> hs(soa.Self());
@@ -1684,14 +1684,14 @@
   }
 }
 
-bool HInstructionBuilder::NeedsAccessCheck(uint32_t type_index,
+bool HInstructionBuilder::NeedsAccessCheck(dex::TypeIndex type_index,
                                            Handle<mirror::DexCache> dex_cache,
                                            bool* finalizable) const {
   return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks(
       dex_compilation_unit_->GetDexMethodIndex(), dex_cache, type_index, finalizable);
 }
 
-bool HInstructionBuilder::NeedsAccessCheck(uint32_t type_index, bool* finalizable) const {
+bool HInstructionBuilder::NeedsAccessCheck(dex::TypeIndex type_index, bool* finalizable) const {
   ScopedObjectAccess soa(Thread::Current());
   Handle<mirror::DexCache> dex_cache = dex_compilation_unit_->GetDexCache();
   return NeedsAccessCheck(type_index, dex_cache, finalizable);
@@ -2449,7 +2449,7 @@
     }
 
     case Instruction::NEW_INSTANCE: {
-      if (!BuildNewInstance(instruction.VRegB_21c(), dex_pc)) {
+      if (!BuildNewInstance(dex::TypeIndex(instruction.VRegB_21c()), dex_pc)) {
         return false;
       }
       UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
@@ -2457,7 +2457,7 @@
     }
 
     case Instruction::NEW_ARRAY: {
-      uint16_t type_index = instruction.VRegC_22c();
+      dex::TypeIndex type_index(instruction.VRegC_22c());
       HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt);
       bool finalizable;
       QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index, &finalizable)
@@ -2475,7 +2475,7 @@
 
     case Instruction::FILLED_NEW_ARRAY: {
       uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
-      uint32_t type_index = instruction.VRegB_35c();
+      dex::TypeIndex type_index(instruction.VRegB_35c());
       uint32_t args[5];
       instruction.GetVarArgs(args);
       BuildFilledNewArray(dex_pc, type_index, number_of_vreg_arguments, false, args, 0);
@@ -2484,7 +2484,7 @@
 
     case Instruction::FILLED_NEW_ARRAY_RANGE: {
       uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
-      uint32_t type_index = instruction.VRegB_3rc();
+      dex::TypeIndex type_index(instruction.VRegB_3rc());
       uint32_t register_index = instruction.VRegC_3rc();
       BuildFilledNewArray(
           dex_pc, type_index, number_of_vreg_arguments, true, nullptr, register_index);
@@ -2641,7 +2641,7 @@
     }
 
     case Instruction::CONST_CLASS: {
-      uint16_t type_index = instruction.VRegB_21c();
+      dex::TypeIndex type_index(instruction.VRegB_21c());
       // `CanAccessTypeWithoutChecks` will tell whether the method being
       // built is trying to access its own class, so that the generated
       // code can optimize for this case. However, the optimization does not
@@ -2682,14 +2682,14 @@
     case Instruction::INSTANCE_OF: {
       uint8_t destination = instruction.VRegA_22c();
       uint8_t reference = instruction.VRegB_22c();
-      uint16_t type_index = instruction.VRegC_22c();
+      dex::TypeIndex type_index(instruction.VRegC_22c());
       BuildTypeCheck(instruction, destination, reference, type_index, dex_pc);
       break;
     }
 
     case Instruction::CHECK_CAST: {
       uint8_t reference = instruction.VRegA_21c();
-      uint16_t type_index = instruction.VRegB_21c();
+      dex::TypeIndex type_index(instruction.VRegB_21c());
       BuildTypeCheck(instruction, -1, reference, type_index, dex_pc);
       break;
     }
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index aa34ddd..f29e522 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -20,6 +20,7 @@
 #include "base/arena_containers.h"
 #include "base/arena_object.h"
 #include "block_builder.h"
+#include "dex_file_types.h"
 #include "driver/compiler_driver.h"
 #include "driver/compiler_driver-inl.h"
 #include "driver/dex_compilation_unit.h"
@@ -100,11 +101,11 @@
 
   // Returns whether the current method needs access check for the type.
   // Output parameter finalizable is set to whether the type is finalizable.
-  bool NeedsAccessCheck(uint32_t type_index,
+  bool NeedsAccessCheck(dex::TypeIndex type_index,
                         Handle<mirror::DexCache> dex_cache,
                         /*out*/bool* finalizable) const
       REQUIRES_SHARED(Locks::mutator_lock_);
-  bool NeedsAccessCheck(uint32_t type_index, /*out*/bool* finalizable) const;
+  bool NeedsAccessCheck(dex::TypeIndex type_index, /*out*/bool* finalizable) const;
 
   template<typename T>
   void Unop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
@@ -176,7 +177,7 @@
 
   // Builds a new array node and the instructions that fill it.
   void BuildFilledNewArray(uint32_t dex_pc,
-                           uint32_t type_index,
+                           dex::TypeIndex type_index,
                            uint32_t number_of_vreg_arguments,
                            bool is_range,
                            uint32_t* args,
@@ -205,7 +206,7 @@
   void BuildTypeCheck(const Instruction& instruction,
                       uint8_t destination,
                       uint8_t reference,
-                      uint16_t type_index,
+                      dex::TypeIndex type_index,
                       uint32_t dex_pc);
 
   // Builds an instruction sequence for a switch statement.
@@ -218,7 +219,7 @@
   mirror::Class* GetCompilingClass() const;
 
   // Returns whether `type_index` points to the outer-most compiling method's class.
-  bool IsOutermostCompilingClass(uint16_t type_index) const;
+  bool IsOutermostCompilingClass(dex::TypeIndex type_index) const;
 
   void PotentiallySimplifyFakeString(uint16_t original_dex_register,
                                      uint32_t dex_pc,
@@ -258,7 +259,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Build a HNewInstance instruction.
-  bool BuildNewInstance(uint16_t type_index, uint32_t dex_pc);
+  bool BuildNewInstance(dex::TypeIndex type_index, uint32_t dex_pc);
 
   // Return whether the compiler can assume `cls` is initialized.
   bool IsInitialized(Handle<mirror::Class> cls) const
diff --git a/compiler/optimizing/licm_test.cc b/compiler/optimizing/licm_test.cc
index 2a62643..8c34dc6 100644
--- a/compiler/optimizing/licm_test.cc
+++ b/compiler/optimizing/licm_test.cc
@@ -63,7 +63,10 @@
     return_->AddSuccessor(exit_);
 
     // Provide boiler-plate instructions.
-    parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimNot);
+    parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(),
+                                                   dex::TypeIndex(0),
+                                                   0,
+                                                   Primitive::kPrimNot);
     entry_->AddInstruction(parameter_);
     int_constant_ = graph_->GetIntConstant(42);
     float_constant_ = graph_->GetFloatConstant(42.0f);
diff --git a/compiler/optimizing/loop_optimization_test.cc b/compiler/optimizing/loop_optimization_test.cc
index 7805a69..9a6b493 100644
--- a/compiler/optimizing/loop_optimization_test.cc
+++ b/compiler/optimizing/loop_optimization_test.cc
@@ -48,7 +48,10 @@
     graph_->AddBlock(exit_block_);
     graph_->SetEntryBlock(entry_block_);
     graph_->SetExitBlock(exit_block_);
-    parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(), 0, 0, Primitive::kPrimInt);
+    parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(),
+                                                   dex::TypeIndex(0),
+                                                   0,
+                                                   Primitive::kPrimInt);
     entry_block_->AddInstruction(parameter_);
     return_block_->AddInstruction(new (&allocator_) HReturnVoid());
     exit_block_->AddInstruction(new (&allocator_) HExit());
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 215ed54..eebc49c 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -29,6 +29,7 @@
 #include "base/stl_util.h"
 #include "base/transform_array_ref.h"
 #include "dex_file.h"
+#include "dex_file_types.h"
 #include "entrypoints/quick/quick_entrypoints_enum.h"
 #include "handle.h"
 #include "handle_scope.h"
@@ -800,7 +801,7 @@
   }
 
   // Catch block information constructor.
-  TryCatchInformation(uint16_t catch_type_index, const DexFile& dex_file)
+  TryCatchInformation(dex::TypeIndex catch_type_index, const DexFile& dex_file)
       : try_entry_(nullptr),
         catch_dex_file_(&dex_file),
         catch_type_index_(catch_type_index) {}
@@ -816,10 +817,10 @@
 
   bool IsCatchAllTypeIndex() const {
     DCHECK(IsCatchBlock());
-    return catch_type_index_ == DexFile::kDexNoIndex16;
+    return !catch_type_index_.IsValid();
   }
 
-  uint16_t GetCatchTypeIndex() const {
+  dex::TypeIndex GetCatchTypeIndex() const {
     DCHECK(IsCatchBlock());
     return catch_type_index_;
   }
@@ -836,7 +837,7 @@
 
   // Exception type information. Only set for catch blocks.
   const DexFile* catch_dex_file_;
-  const uint16_t catch_type_index_;
+  const dex::TypeIndex catch_type_index_;
 };
 
 static constexpr size_t kNoLifetime = -1;
@@ -3671,7 +3672,7 @@
   HNewInstance(HInstruction* cls,
                HCurrentMethod* current_method,
                uint32_t dex_pc,
-               uint16_t type_index,
+               dex::TypeIndex type_index,
                const DexFile& dex_file,
                bool needs_access_check,
                bool finalizable,
@@ -3686,7 +3687,7 @@
     SetRawInputAt(1, current_method);
   }
 
-  uint16_t GetTypeIndex() const { return type_index_; }
+  dex::TypeIndex GetTypeIndex() const { return type_index_; }
   const DexFile& GetDexFile() const { return dex_file_; }
 
   // Calls runtime so needs an environment.
@@ -3719,7 +3720,7 @@
   static_assert(kNumberOfNewInstancePackedBits <= kMaxNumberOfPackedBits,
                 "Too many packed fields.");
 
-  const uint16_t type_index_;
+  const dex::TypeIndex type_index_;
   const DexFile& dex_file_;
   QuickEntrypointEnum entrypoint_;
 
@@ -4265,7 +4266,7 @@
   HNewArray(HInstruction* length,
             HCurrentMethod* current_method,
             uint32_t dex_pc,
-            uint16_t type_index,
+            dex::TypeIndex type_index,
             const DexFile& dex_file,
             QuickEntrypointEnum entrypoint)
       : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc),
@@ -4276,7 +4277,7 @@
     SetRawInputAt(1, current_method);
   }
 
-  uint16_t GetTypeIndex() const { return type_index_; }
+  dex::TypeIndex GetTypeIndex() const { return type_index_; }
   const DexFile& GetDexFile() const { return dex_file_; }
 
   // Calls runtime so needs an environment.
@@ -4292,7 +4293,7 @@
   DECLARE_INSTRUCTION(NewArray);
 
  private:
-  const uint16_t type_index_;
+  const dex::TypeIndex type_index_;
   const DexFile& dex_file_;
   const QuickEntrypointEnum entrypoint_;
 
@@ -4829,7 +4830,7 @@
 class HParameterValue FINAL : public HExpression<0> {
  public:
   HParameterValue(const DexFile& dex_file,
-                  uint16_t type_index,
+                  dex::TypeIndex type_index,
                   uint8_t index,
                   Primitive::Type parameter_type,
                   bool is_this = false)
@@ -4842,7 +4843,7 @@
   }
 
   const DexFile& GetDexFile() const { return dex_file_; }
-  uint16_t GetTypeIndex() const { return type_index_; }
+  dex::TypeIndex GetTypeIndex() const { return type_index_; }
   uint8_t GetIndex() const { return index_; }
   bool IsThis() const { return GetPackedFlag<kFlagIsThis>(); }
 
@@ -4860,7 +4861,7 @@
                 "Too many packed fields.");
 
   const DexFile& dex_file_;
-  const uint16_t type_index_;
+  const dex::TypeIndex type_index_;
   // The index of this parameter in the parameters list. Must be less
   // than HGraph::number_of_in_vregs_.
   const uint8_t index_;
@@ -5455,7 +5456,7 @@
   };
 
   HLoadClass(HCurrentMethod* current_method,
-             uint16_t type_index,
+             dex::TypeIndex type_index,
              const DexFile& dex_file,
              bool is_referrers_class,
              uint32_t dex_pc,
@@ -5487,7 +5488,7 @@
 
   void SetLoadKindWithTypeReference(LoadKind load_kind,
                                     const DexFile& dex_file,
-                                    uint32_t type_index) {
+                                    dex::TypeIndex type_index) {
     DCHECK(HasTypeReference(load_kind));
     DCHECK(IsSameDexFile(dex_file_, dex_file));
     DCHECK_EQ(type_index_, type_index);
@@ -5511,7 +5512,7 @@
 
   bool InstructionDataEquals(const HInstruction* other) const;
 
-  size_t ComputeHashCode() const OVERRIDE { return type_index_; }
+  size_t ComputeHashCode() const OVERRIDE { return type_index_.index_; }
 
   bool CanBeNull() const OVERRIDE { return false; }
 
@@ -5547,7 +5548,7 @@
     loaded_class_rti_ = rti;
   }
 
-  uint32_t GetTypeIndex() const { return type_index_; }
+  dex::TypeIndex GetTypeIndex() const { return type_index_; }
   const DexFile& GetDexFile() const { return dex_file_; }
 
   uint32_t GetDexCacheElementOffset() const;
@@ -5630,7 +5631,7 @@
   // for PC-relative loads, i.e. kDexCachePcRelative or kBootImageLinkTimePcRelative.
   HUserRecord<HInstruction*> special_input_;
 
-  const uint16_t type_index_;
+  const dex::TypeIndex type_index_;
   const DexFile& dex_file_;
 
   union {
diff --git a/compiler/optimizing/nodes_test.cc b/compiler/optimizing/nodes_test.cc
index d4e2a58..5d9a652 100644
--- a/compiler/optimizing/nodes_test.cc
+++ b/compiler/optimizing/nodes_test.cc
@@ -35,7 +35,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (&allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter);
   entry->AddInstruction(new (&allocator) HGoto());
 
@@ -78,9 +78,9 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter1 = new (&allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   HInstruction* parameter2 = new (&allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter1);
   entry->AddInstruction(parameter2);
   entry->AddInstruction(new (&allocator) HExit());
@@ -106,7 +106,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (&allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter);
 
   ASSERT_FALSE(parameter->HasUses());
@@ -127,7 +127,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter1 = new (&allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   HInstruction* with_environment = new (&allocator) HNullCheck(parameter1, 0);
   entry->AddInstruction(parameter1);
   entry->AddInstruction(with_environment);
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 85519c9..604d99c 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -61,6 +61,7 @@
 #include "debug/method_debug_info.h"
 #include "dex/verification_results.h"
 #include "dex/verified_method.h"
+#include "dex_file_types.h"
 #include "driver/compiler_driver-inl.h"
 #include "driver/compiler_options.h"
 #include "driver/dex_compilation_unit.h"
@@ -948,7 +949,7 @@
     graph->SetArtMethod(method);
     ScopedObjectAccess soa(Thread::Current());
     interpreter_metadata = method->GetQuickenedInfo(class_linker->GetImagePointerSize());
-    uint16_t type_index = method->GetDeclaringClass()->GetDexTypeIndex();
+    dex::TypeIndex type_index = method->GetDeclaringClass()->GetDexTypeIndex();
 
     // Update the dex cache if the type is not in it yet. Note that under AOT,
     // the verifier must have set it, but under JIT, there's no guarantee, as we
diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc
index 0db6088..f9ac3a0 100644
--- a/compiler/optimizing/prepare_for_register_allocation.cc
+++ b/compiler/optimizing/prepare_for_register_allocation.cc
@@ -143,7 +143,7 @@
   // - or the load class has only one use.
   if (instruction->IsFinalizable() || has_only_one_use || load_class->NeedsAccessCheck()) {
     instruction->SetEntrypoint(kQuickAllocObject);
-    instruction->ReplaceInput(GetGraph()->GetIntConstant(load_class->GetTypeIndex()), 0);
+    instruction->ReplaceInput(GetGraph()->GetIntConstant(load_class->GetTypeIndex().index_), 0);
     if (has_only_one_use) {
       // We've just removed the only use of the HLoadClass. Since we don't run DCE after this pass,
       // do it manually if possible.
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index d588dea..c191c66 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -96,7 +96,7 @@
   void VisitBoundType(HBoundType* instr) OVERRIDE;
   void VisitNullCheck(HNullCheck* instr) OVERRIDE;
   void UpdateReferenceTypeInfo(HInstruction* instr,
-                               uint16_t type_idx,
+                               dex::TypeIndex type_idx,
                                const DexFile& dex_file,
                                bool is_exact);
 
@@ -463,7 +463,7 @@
 }
 
 void ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* instr,
-                                                                   uint16_t type_idx,
+                                                                   dex::TypeIndex type_idx,
                                                                    const DexFile& dex_file,
                                                                    bool is_exact) {
   DCHECK_EQ(instr->GetType(), Primitive::kPrimNot);
@@ -484,7 +484,7 @@
 
 static mirror::Class* GetClassFromDexCache(Thread* self,
                                            const DexFile& dex_file,
-                                           uint16_t type_idx,
+                                           dex::TypeIndex type_idx,
                                            Handle<mirror::DexCache> hint_dex_cache)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   mirror::DexCache* dex_cache = FindDexCacheWithHint(self, dex_file, hint_dex_cache);
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index 55ea99e..559f409 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -20,6 +20,7 @@
 #include "code_generator.h"
 #include "code_generator_x86.h"
 #include "dex_file.h"
+#include "dex_file_types.h"
 #include "dex_instruction.h"
 #include "driver/compiler_options.h"
 #include "nodes.h"
@@ -495,7 +496,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter);
 
   HBasicBlock* block = new (allocator) HBasicBlock(graph);
@@ -658,7 +659,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimNot);
   entry->AddInstruction(parameter);
 
   HBasicBlock* block = new (allocator) HBasicBlock(graph);
@@ -742,7 +743,7 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* parameter = new (allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);
   entry->AddInstruction(parameter);
 
   HInstruction* constant1 = graph->GetIntConstant(1);
@@ -821,9 +822,9 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* first = new (allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);
   HInstruction* second = new (allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);
   entry->AddInstruction(first);
   entry->AddInstruction(second);
 
@@ -883,13 +884,13 @@
   graph->AddBlock(entry);
   graph->SetEntryBlock(entry);
   HInstruction* one = new (&allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);
   HInstruction* two = new (&allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);
   HInstruction* three = new (&allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);
   HInstruction* four = new (&allocator) HParameterValue(
-      graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
+      graph->GetDexFile(), dex::TypeIndex(0), 0, Primitive::kPrimInt);
   entry->AddInstruction(one);
   entry->AddInstruction(two);
   entry->AddInstruction(three);
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 15254ed..a127708 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -147,7 +147,7 @@
   DCHECK(!load_class->IsInBootImage()) << "HLoadClass should not be optimized before sharpening.";
 
   const DexFile& dex_file = load_class->GetDexFile();
-  uint32_t type_index = load_class->GetTypeIndex();
+  dex::TypeIndex type_index = load_class->GetTypeIndex();
 
   bool is_in_dex_cache = false;
   bool is_in_boot_image = false;
@@ -197,7 +197,7 @@
           // inlined frames are used correctly for OOM stack trace.
           // TODO: Write a test for this. Bug: 29416588
           desired_load_kind = HLoadClass::LoadKind::kDexCacheAddress;
-          void* dex_cache_element_address = &dex_cache->GetResolvedTypes()[type_index];
+          void* dex_cache_element_address = &dex_cache->GetResolvedTypes()[type_index.index_];
           address = reinterpret_cast64<uint64_t>(dex_cache_element_address);
         }
         // AOT app compilation. Check if the class is in the boot image.