Fix HNewArray with unresolved primitive array type.

And enable test 920-objects that was crashing because
of this bug.

Test: testrunner.py --host --jit-on-first-use -t 920
Test: testrunner.py --host --optimizing
Test: m test-art-host-gtest
Bug: 117638896
Change-Id: I47dc893b121c82de537b3147c86d37a6eecf2d62
diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc
index 7c29df8..e15161e 100644
--- a/compiler/optimizing/bounds_check_elimination_test.cc
+++ b/compiler/optimizing/bounds_check_elimination_test.cc
@@ -598,9 +598,10 @@
   entry->AddSuccessor(block);
   // We pass a bogus constant for the class to avoid mocking one.
   HInstruction* new_array = new (allocator) HNewArray(
-      constant_10,
-      constant_10,
-      0);
+      /* cls= */ constant_10,
+      /* length= */ constant_10,
+      /* dex_pc= */ 0,
+      /* component_size_shift= */ 0);
   block->AddInstruction(new_array);
   block->AddInstruction(new (allocator) HGoto());
 
@@ -977,7 +978,11 @@
   graph_->AddBlock(block);
   entry->AddSuccessor(block);
   // We pass a bogus constant for the class to avoid mocking one.
-  HInstruction* new_array = new (GetAllocator()) HNewArray(constant_10, constant_10, 0);
+  HInstruction* new_array = new (GetAllocator()) HNewArray(
+      /* cls= */ constant_10,
+      /* length= */ constant_10,
+      /* dex_pc= */ 0,
+      /* component_size_shift= */ 0);
   block->AddInstruction(new_array);
   block->AddInstruction(new (GetAllocator()) HGoto());
 
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index d440cf3..d8e442c 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -1653,19 +1653,12 @@
   EmitJitRootPatches(code, roots_data);
 }
 
-QuickEntrypointEnum CodeGenerator::GetArrayAllocationEntrypoint(Handle<mirror::Class> array_klass) {
-  ScopedObjectAccess soa(Thread::Current());
-  if (array_klass == nullptr) {
-    // This can only happen for non-primitive arrays, as primitive arrays can always
-    // be resolved.
-    return kQuickAllocArrayResolved32;
-  }
-
-  switch (array_klass->GetComponentSize()) {
-    case 1: return kQuickAllocArrayResolved8;
-    case 2: return kQuickAllocArrayResolved16;
-    case 4: return kQuickAllocArrayResolved32;
-    case 8: return kQuickAllocArrayResolved64;
+QuickEntrypointEnum CodeGenerator::GetArrayAllocationEntrypoint(HNewArray* new_array) {
+  switch (new_array->GetComponentSizeShift()) {
+    case 0: return kQuickAllocArrayResolved8;
+    case 1: return kQuickAllocArrayResolved16;
+    case 2: return kQuickAllocArrayResolved32;
+    case 3: return kQuickAllocArrayResolved64;
   }
   LOG(FATAL) << "Unreachable";
   return kQuickAllocArrayResolved;
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 4e73e0b..3f56078 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -636,7 +636,7 @@
 
   virtual void GenerateNop() = 0;
 
-  static QuickEntrypointEnum GetArrayAllocationEntrypoint(Handle<mirror::Class> array_klass);
+  static QuickEntrypointEnum GetArrayAllocationEntrypoint(HNewArray* new_array);
 
  protected:
   // Patch info used for recording locations of required linker patches and their targets,
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 0a28f65..3f4fb15 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -5004,10 +5004,8 @@
 }
 
 void InstructionCodeGeneratorARM64::VisitNewArray(HNewArray* instruction) {
-  // Note: if heap poisoning is enabled, the entry point takes cares
-  // of poisoning the reference.
-  QuickEntrypointEnum entrypoint =
-      CodeGenerator::GetArrayAllocationEntrypoint(instruction->GetLoadClass()->GetClass());
+  // Note: if heap poisoning is enabled, the entry point takes care of poisoning the reference.
+  QuickEntrypointEnum entrypoint = CodeGenerator::GetArrayAllocationEntrypoint(instruction);
   codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>();
   codegen_->MaybeGenerateMarkingRegisterCheck(/* code */ __LINE__);
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 8bd4af5..d5b734d 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -5043,10 +5043,8 @@
 }
 
 void InstructionCodeGeneratorARMVIXL::VisitNewArray(HNewArray* instruction) {
-  // Note: if heap poisoning is enabled, the entry point takes cares
-  // of poisoning the reference.
-  QuickEntrypointEnum entrypoint =
-      CodeGenerator::GetArrayAllocationEntrypoint(instruction->GetLoadClass()->GetClass());
+  // Note: if heap poisoning is enabled, the entry point takes care of poisoning the reference.
+  QuickEntrypointEnum entrypoint = CodeGenerator::GetArrayAllocationEntrypoint(instruction);
   codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>();
   DCHECK(!codegen_->IsLeafMethod());
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 1f0e200..c6d0f3f 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -8702,10 +8702,8 @@
 }
 
 void InstructionCodeGeneratorMIPS::VisitNewArray(HNewArray* instruction) {
-  // Note: if heap poisoning is enabled, the entry point takes care
-  // of poisoning the reference.
-  QuickEntrypointEnum entrypoint =
-      CodeGenerator::GetArrayAllocationEntrypoint(instruction->GetLoadClass()->GetClass());
+  // Note: if heap poisoning is enabled, the entry point takes care of poisoning the reference.
+  QuickEntrypointEnum entrypoint = CodeGenerator::GetArrayAllocationEntrypoint(instruction);
   codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>();
   DCHECK(!codegen_->IsLeafMethod());
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 0005d8f..039b3ca 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -6633,10 +6633,8 @@
 }
 
 void InstructionCodeGeneratorMIPS64::VisitNewArray(HNewArray* instruction) {
-  // Note: if heap poisoning is enabled, the entry point takes care
-  // of poisoning the reference.
-  QuickEntrypointEnum entrypoint =
-      CodeGenerator::GetArrayAllocationEntrypoint(instruction->GetLoadClass()->GetClass());
+  // Note: if heap poisoning is enabled, the entry point takes care of poisoning the reference.
+  QuickEntrypointEnum entrypoint = CodeGenerator::GetArrayAllocationEntrypoint(instruction);
   codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>();
   DCHECK(!codegen_->IsLeafMethod());
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index ca1e93b..9f34a51 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -4525,10 +4525,8 @@
 }
 
 void InstructionCodeGeneratorX86::VisitNewArray(HNewArray* instruction) {
-  // Note: if heap poisoning is enabled, the entry point takes cares
-  // of poisoning the reference.
-  QuickEntrypointEnum entrypoint =
-      CodeGenerator::GetArrayAllocationEntrypoint(instruction->GetLoadClass()->GetClass());
+  // Note: if heap poisoning is enabled, the entry point takes care of poisoning the reference.
+  QuickEntrypointEnum entrypoint = CodeGenerator::GetArrayAllocationEntrypoint(instruction);
   codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>();
   DCHECK(!codegen_->IsLeafMethod());
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index e6643fb..dac2dba 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -4371,10 +4371,8 @@
 }
 
 void InstructionCodeGeneratorX86_64::VisitNewArray(HNewArray* instruction) {
-  // Note: if heap poisoning is enabled, the entry point takes cares
-  // of poisoning the reference.
-  QuickEntrypointEnum entrypoint =
-      CodeGenerator::GetArrayAllocationEntrypoint(instruction->GetLoadClass()->GetClass());
+  // Note: if heap poisoning is enabled, the entry point takes care of poisoning the reference.
+  QuickEntrypointEnum entrypoint = CodeGenerator::GetArrayAllocationEntrypoint(instruction);
   codegen_->InvokeRuntime(entrypoint, instruction, instruction->GetDexPc());
   CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>();
   DCHECK(!codegen_->IsLeafMethod());
diff --git a/compiler/optimizing/induction_var_range_test.cc b/compiler/optimizing/induction_var_range_test.cc
index e5bc6ef..223e08e 100644
--- a/compiler/optimizing/induction_var_range_test.cc
+++ b/compiler/optimizing/induction_var_range_test.cc
@@ -701,7 +701,11 @@
 
 TEST_F(InductionVarRangeTest, ArrayLengthAndHints) {
   // We pass a bogus constant for the class to avoid mocking one.
-  HInstruction* new_array = new (GetAllocator()) HNewArray(x_, x_, 0);
+  HInstruction* new_array = new (GetAllocator()) HNewArray(
+      /* cls= */ x_,
+      /* length= */ x_,
+      /* dex_pc= */ 0,
+      /* component_size_shift= */ 0);
   entry_block_->AddInstruction(new_array);
   HInstruction* array_length = new (GetAllocator()) HArrayLength(new_array, 0);
   entry_block_->AddInstruction(array_length);
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index b576f83..bd94789 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1842,15 +1842,27 @@
   graph_->SetHasBoundsChecks(true);
 }
 
+HNewArray* HInstructionBuilder::BuildNewArray(uint32_t dex_pc,
+                                              dex::TypeIndex type_index,
+                                              HInstruction* length) {
+  HLoadClass* cls = BuildLoadClass(type_index, dex_pc);
+
+  const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(type_index));
+  DCHECK_EQ(descriptor[0], '[');
+  size_t component_type_shift = Primitive::ComponentSizeShift(Primitive::GetType(descriptor[1]));
+
+  HNewArray* new_array = new (allocator_) HNewArray(cls, length, dex_pc, component_type_shift);
+  AppendInstruction(new_array);
+  return new_array;
+}
+
 HNewArray* HInstructionBuilder::BuildFilledNewArray(uint32_t dex_pc,
                                                     dex::TypeIndex type_index,
                                                     const InstructionOperands& operands) {
   const size_t number_of_operands = operands.GetNumberOfOperands();
   HInstruction* length = graph_->GetIntConstant(number_of_operands, dex_pc);
-  HLoadClass* cls = BuildLoadClass(type_index, dex_pc);
-  HNewArray* const object = new (allocator_) HNewArray(cls, length, dex_pc);
-  AppendInstruction(object);
 
+  HNewArray* new_array = BuildNewArray(dex_pc, type_index, length);
   const char* descriptor = dex_file_->StringByTypeIdx(type_index);
   DCHECK_EQ(descriptor[0], '[') << descriptor;
   char primitive = descriptor[1];
@@ -1863,13 +1875,13 @@
   for (size_t i = 0; i < number_of_operands; ++i) {
     HInstruction* value = LoadLocal(operands.GetOperand(i), type);
     HInstruction* index = graph_->GetIntConstant(i, dex_pc);
-    HArraySet* aset = new (allocator_) HArraySet(object, index, value, type, dex_pc);
+    HArraySet* aset = new (allocator_) HArraySet(new_array, index, value, type, dex_pc);
     ssa_builder_->MaybeAddAmbiguousArraySet(aset);
     AppendInstruction(aset);
   }
-  latest_result_ = object;
+  latest_result_ = new_array;
 
-  return object;
+  return new_array;
 }
 
 template <typename T>
@@ -2892,10 +2904,8 @@
     case Instruction::NEW_ARRAY: {
       dex::TypeIndex type_index(instruction.VRegC_22c());
       HInstruction* length = LoadLocal(instruction.VRegB_22c(), DataType::Type::kInt32);
-      HLoadClass* cls = BuildLoadClass(type_index, dex_pc);
+      HNewArray* new_array = BuildNewArray(dex_pc, type_index, length);
 
-      HNewArray* new_array = new (allocator_) HNewArray(cls, length, dex_pc);
-      AppendInstruction(new_array);
       UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
       BuildConstructorFenceForAllocation(new_array);
       break;
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index af1b86c..2ab2139 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -179,6 +179,9 @@
                          uint32_t call_site_idx,
                          const InstructionOperands& operands);
 
+  // Builds a new array node.
+  HNewArray* BuildNewArray(uint32_t dex_pc, dex::TypeIndex type_index, HInstruction* length);
+
   // Builds a new array node and the instructions that fill it.
   HNewArray* BuildFilledNewArray(uint32_t dex_pc,
                                  dex::TypeIndex type_index,
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 97b50d3..6ebe89e 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4849,10 +4849,11 @@
 
 class HNewArray final : public HExpression<2> {
  public:
-  HNewArray(HInstruction* cls, HInstruction* length, uint32_t dex_pc)
+  HNewArray(HInstruction* cls, HInstruction* length, uint32_t dex_pc, size_t component_size_shift)
       : HExpression(kNewArray, DataType::Type::kReference, SideEffects::CanTriggerGC(), dex_pc) {
     SetRawInputAt(0, cls);
     SetRawInputAt(1, length);
+    SetPackedField<ComponentSizeShiftField>(component_size_shift);
   }
 
   bool IsClonable() const override { return true; }
@@ -4874,10 +4875,23 @@
     return InputAt(1);
   }
 
+  size_t GetComponentSizeShift() {
+    return GetPackedField<ComponentSizeShiftField>();
+  }
+
   DECLARE_INSTRUCTION(NewArray);
 
  protected:
   DEFAULT_COPY_CONSTRUCTOR(NewArray);
+
+ private:
+  static constexpr size_t kFieldComponentSizeShift = kNumberOfGenericPackedBits;
+  static constexpr size_t kFieldComponentSizeShiftSize = MinimumBitsToStore(3u);
+  static constexpr size_t kNumberOfNewArrayPackedBits =
+      kFieldComponentSizeShift + kFieldComponentSizeShiftSize;
+  static_assert(kNumberOfNewArrayPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
+  using ComponentSizeShiftField =
+      BitField<size_t, kFieldComponentSizeShift, kFieldComponentSizeShift>;
 };
 
 class HAdd final : public HBinaryOperation {
diff --git a/test/knownfailures.json b/test/knownfailures.json
index d769b48..f4f45ce 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -1114,11 +1114,5 @@
         "variant": "target & gcstress & debug",
         "bug": "b/117597114",
         "description": ["Looks timing dependent"]
-    },
-    {
-        "tests": ["920-objects"],
-        "variant": "jit-on-first-use",
-        "bug": "b/117638896",
-        "description": ["SIGSEGVs on jit-on-first-use configuration."]
     }
 ]