diff options
author | 2017-01-19 08:59:37 +0000 | |
---|---|---|
committer | 2017-01-19 09:32:17 +0000 | |
commit | e761bccf9f0d884cc4d4ec104568cef968296492 (patch) | |
tree | 05a2d20d61c0e91270df2747f0c242433b5ce62b | |
parent | b0355130e38034db6b904783a00f74a3524e1881 (diff) |
Revert "Revert "Load the array class in the compiler for allocations.""
This reverts commit fee255039e30c1c3dfc70c426c3d176221c3cdf9.
Change-Id: I02b45f9a659d872feeb35df40b42c1be9878413a
28 files changed, 133 insertions, 295 deletions
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc index 7dc094b25f..2ee4db923a 100644 --- a/compiler/optimizing/bounds_check_elimination.cc +++ b/compiler/optimizing/bounds_check_elimination.cc @@ -153,21 +153,6 @@ class ValueBound : public ValueObject { return instruction_ == bound.instruction_ && constant_ == bound.constant_; } - /* - * Hunt "under the hood" of array lengths (leading to array references), - * null checks (also leading to array references), and new arrays - * (leading to the actual length). This makes it more likely related - * instructions become actually comparable. - */ - static HInstruction* HuntForDeclaration(HInstruction* instruction) { - while (instruction->IsArrayLength() || - instruction->IsNullCheck() || - instruction->IsNewArray()) { - instruction = instruction->InputAt(0); - } - return instruction; - } - static bool Equal(HInstruction* instruction1, HInstruction* instruction2) { if (instruction1 == instruction2) { return true; @@ -1136,7 +1121,7 @@ class BCEVisitor : public HGraphVisitor { } void VisitNewArray(HNewArray* new_array) OVERRIDE { - HInstruction* len = new_array->InputAt(0); + HInstruction* len = new_array->GetLength(); if (!len->IsIntConstant()) { HInstruction *left; int32_t right_const; @@ -1324,7 +1309,7 @@ class BCEVisitor : public HGraphVisitor { InductionVarRange::Value v2; bool needs_finite_test = false; HInstruction* index = context->InputAt(0); - HInstruction* hint = ValueBound::HuntForDeclaration(context->InputAt(1)); + HInstruction* hint = HuntForDeclaration(context->InputAt(1)); if (induction_range_.GetInductionRange(context, index, hint, &v1, &v2, &needs_finite_test)) { if (v1.is_known && (v1.a_constant == 0 || v1.a_constant == 1) && v2.is_known && (v2.a_constant == 0 || v2.a_constant == 1)) { diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc index dfa150406d..5d58207511 100644 --- a/compiler/optimizing/bounds_check_elimination_test.cc +++ b/compiler/optimizing/bounds_check_elimination_test.cc @@ -596,13 +596,11 @@ static HInstruction* BuildSSAGraph3(HGraph* graph, HBasicBlock* block = new (allocator) HBasicBlock(graph); graph->AddBlock(block); entry->AddSuccessor(block); + // We pass a bogus constant for the class to avoid mocking one. HInstruction* new_array = new (allocator) HNewArray( constant_10, - graph->GetCurrentMethod(), - 0, - dex::TypeIndex(static_cast<uint16_t>(Primitive::kPrimInt)), - graph->GetDexFile(), - kQuickAllocArray); + constant_10, + 0); block->AddInstruction(new_array); block->AddInstruction(new (allocator) HGoto()); diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 07b174698a..9c9c604dca 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -3984,19 +3984,16 @@ void LocationsBuilderARM::VisitNewArray(HNewArray* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly); InvokeRuntimeCallingConvention calling_convention; - locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetOut(Location::RegisterLocation(R0)); - locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); - locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); + locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); + locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); } void InstructionCodeGeneratorARM::VisitNewArray(HNewArray* instruction) { - InvokeRuntimeCallingConvention calling_convention; - __ 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()); - CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*>(); + codegen_->InvokeRuntime(kQuickAllocArrayResolved, instruction, instruction->GetDexPc()); + CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>(); } void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) { diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index b094e54f8a..68d0b869e7 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -4747,22 +4747,16 @@ void LocationsBuilderARM64::VisitNewArray(HNewArray* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly); InvokeRuntimeCallingConvention calling_convention; - locations->AddTemp(LocationFrom(calling_convention.GetRegisterAt(0))); locations->SetOut(LocationFrom(x0)); - locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(1))); - locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(2))); + locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); + locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(1))); } void InstructionCodeGeneratorARM64::VisitNewArray(HNewArray* instruction) { - LocationSummary* locations = instruction->GetLocations(); - InvokeRuntimeCallingConvention calling_convention; - Register type_index = RegisterFrom(locations->GetTemp(0), Primitive::kPrimInt); - DCHECK(type_index.Is(w0)); - __ 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()); - CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*>(); + codegen_->InvokeRuntime(kQuickAllocArrayResolved, instruction, instruction->GetDexPc()); + CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>(); } void LocationsBuilderARM64::VisitNewInstance(HNewInstance* instruction) { diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index ecabc58c4d..592ee5aba6 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -3997,19 +3997,16 @@ void LocationsBuilderARMVIXL::VisitNewArray(HNewArray* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly); InvokeRuntimeCallingConventionARMVIXL calling_convention; - locations->AddTemp(LocationFrom(calling_convention.GetRegisterAt(0))); locations->SetOut(LocationFrom(r0)); locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(1))); locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(2))); } void InstructionCodeGeneratorARMVIXL::VisitNewArray(HNewArray* instruction) { - InvokeRuntimeCallingConventionARMVIXL calling_convention; - __ 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()); - CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*>(); + codegen_->InvokeRuntime(kQuickAllocArrayResolved, instruction, instruction->GetDexPc()); + CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>(); } void LocationsBuilderARMVIXL::VisitParameterValue(HParameterValue* instruction) { diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index 24234e18c1..a0383826d3 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -5897,21 +5897,14 @@ void LocationsBuilderMIPS::VisitNewArray(HNewArray* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly); InvokeRuntimeCallingConvention calling_convention; - locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0))); - locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2))); locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); - locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); + locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); + locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); } void InstructionCodeGeneratorMIPS::VisitNewArray(HNewArray* instruction) { - InvokeRuntimeCallingConvention calling_convention; - 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().index_); - codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc()); - CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, - void*, uint32_t, int32_t, ArtMethod*>(); + codegen_->InvokeRuntime(kQuickAllocArrayResolved, instruction, instruction->GetDexPc()); + CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>(); } void LocationsBuilderMIPS::VisitNewInstance(HNewInstance* instruction) { diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index fc8fb7acb2..446dea659e 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -3841,19 +3841,14 @@ void LocationsBuilderMIPS64::VisitNewArray(HNewArray* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly); InvokeRuntimeCallingConvention calling_convention; - locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot)); - locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); - locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); + locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); + locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); } 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().index_); - codegen_->InvokeRuntime(instruction->GetEntrypoint(), instruction, instruction->GetDexPc()); - CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*>(); + codegen_->InvokeRuntime(kQuickAllocArrayResolved, instruction, instruction->GetDexPc()); + CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>(); } void LocationsBuilderMIPS64::VisitNewInstance(HNewInstance* instruction) { diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index cc727d2068..853c91fac8 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -4192,18 +4192,15 @@ void LocationsBuilderX86::VisitNewArray(HNewArray* instruction) { new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly); locations->SetOut(Location::RegisterLocation(EAX)); InvokeRuntimeCallingConvention calling_convention; - locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0))); - locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); - locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); + locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); + locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); } void InstructionCodeGeneratorX86::VisitNewArray(HNewArray* instruction) { - InvokeRuntimeCallingConvention calling_convention; - __ 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()); - CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*>(); + codegen_->InvokeRuntime(kQuickAllocArrayResolved, 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 9adedab130..74c71cce1f 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -4088,21 +4088,16 @@ void LocationsBuilderX86_64::VisitNewArray(HNewArray* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnMainOnly); InvokeRuntimeCallingConvention calling_convention; - locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(0))); locations->SetOut(Location::RegisterLocation(RAX)); - locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); - locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(2))); + locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); + locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); } void InstructionCodeGeneratorX86_64::VisitNewArray(HNewArray* instruction) { - InvokeRuntimeCallingConvention calling_convention; - codegen_->Load64BitValue(CpuRegister(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()); - CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*>(); - + codegen_->InvokeRuntime(kQuickAllocArrayResolved, instruction, instruction->GetDexPc()); + CheckEntrypointTypes<kQuickAllocArrayResolved, void*, mirror::Class*, int32_t>(); DCHECK(!codegen_->IsLeafMethod()); } diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc index 6d8ae75460..3973985338 100644 --- a/compiler/optimizing/induction_var_range.cc +++ b/compiler/optimizing/induction_var_range.cc @@ -114,12 +114,7 @@ static bool IsMaxAtHint( } } else { *suitable = instruction; - while (instruction->IsArrayLength() || - instruction->IsNullCheck() || - instruction->IsNewArray()) { - instruction = instruction->InputAt(0); - } - return instruction == hint; + return HuntForDeclaration(instruction) == hint; } return false; } @@ -629,7 +624,7 @@ InductionVarRange::Value InductionVarRange::GetFetch(HInstruction* instruction, if (chase_hint_ == nullptr) { return is_min ? Value(0) : Value(std::numeric_limits<int32_t>::max()); } else if (instruction->InputAt(0)->IsNewArray()) { - return GetFetch(instruction->InputAt(0)->InputAt(0), trip, in_body, is_min); + return GetFetch(instruction->InputAt(0)->AsNewArray()->GetLength(), trip, in_body, is_min); } } else if (instruction->IsTypeConversion()) { // Since analysis is 32-bit (or narrower), chase beyond widening along the path. diff --git a/compiler/optimizing/induction_var_range_test.cc b/compiler/optimizing/induction_var_range_test.cc index aa3e1aab4f..d81817fb09 100644 --- a/compiler/optimizing/induction_var_range_test.cc +++ b/compiler/optimizing/induction_var_range_test.cc @@ -697,13 +697,8 @@ TEST_F(InductionVarRangeTest, MaxValue) { } TEST_F(InductionVarRangeTest, ArrayLengthAndHints) { - HInstruction* new_array = new (&allocator_) - HNewArray(x_, - graph_->GetCurrentMethod(), - 0, - dex::TypeIndex(Primitive::kPrimInt), - graph_->GetDexFile(), - kQuickAllocArray); + // We pass a bogus constant for the class to avoid mocking one. + HInstruction* new_array = new (&allocator_) HNewArray(x_, x_, 0); entry_block_->AddInstruction(new_array); HInstruction* array_length = new (&allocator_) HArrayLength(new_array, 0); entry_block_->AddInstruction(array_length); diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 78a4251e3a..5d40f75618 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -1429,15 +1429,6 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, return false; } - if (current->IsNewArray() && - (current->AsNewArray()->GetEntrypoint() == kQuickAllocArrayWithAccessCheck)) { - VLOG(compiler) << "Method " << callee_dex_file.PrettyMethod(method_index) - << " could not be inlined because it is using an entrypoint" - << " with access checks"; - // Allocation entrypoint does not handle inlined frames. - return false; - } - if (current->IsUnresolvedStaticFieldGet() || current->IsUnresolvedInstanceFieldGet() || current->IsUnresolvedStaticFieldSet() || diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 8ed0e7fa06..ef8d74dce0 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -1498,16 +1498,8 @@ void HInstructionBuilder::BuildFilledNewArray(uint32_t dex_pc, uint32_t* args, uint32_t register_index) { HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments, dex_pc); - bool finalizable; - QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index, &finalizable) - ? kQuickAllocArrayWithAccessCheck - : kQuickAllocArray; - HInstruction* object = new (arena_) HNewArray(length, - graph_->GetCurrentMethod(), - dex_pc, - type_index, - *dex_compilation_unit_->GetDexFile(), - entrypoint); + HLoadClass* cls = BuildLoadClass(type_index, dex_pc, /* check_access */ true); + HInstruction* object = new (arena_) HNewArray(cls, length, dex_pc); AppendInstruction(object); const char* descriptor = dex_file_->StringByTypeIdx(type_index); @@ -1644,9 +1636,13 @@ HLoadClass* HInstructionBuilder::BuildLoadClass(dex::TypeIndex type_index, const DexCompilationUnit* compilation_unit = outer ? outer_compilation_unit_ : dex_compilation_unit_; const DexFile& dex_file = *compilation_unit->GetDexFile(); - Handle<mirror::DexCache> dex_cache = compilation_unit->GetDexCache(); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle( + soa.Decode<mirror::ClassLoader>(dex_compilation_unit_->GetClassLoader()))); + Handle<mirror::Class> klass = handles_->NewHandle(compiler_driver_->ResolveClass( + soa, compilation_unit->GetDexCache(), class_loader, type_index, compilation_unit)); + bool is_accessible = false; - Handle<mirror::Class> klass = handles_->NewHandle(dex_cache->GetResolvedType(type_index)); if (!check_access) { is_accessible = true; } else if (klass.Get() != nullptr) { @@ -2503,16 +2499,8 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, case Instruction::NEW_ARRAY: { dex::TypeIndex type_index(instruction.VRegC_22c()); HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt); - bool finalizable; - QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index, &finalizable) - ? kQuickAllocArrayWithAccessCheck - : kQuickAllocArray; - AppendInstruction(new (arena_) HNewArray(length, - graph_->GetCurrentMethod(), - dex_pc, - type_index, - *dex_compilation_unit_->GetDexFile(), - entrypoint)); + HLoadClass* cls = BuildLoadClass(type_index, dex_pc, /* check_access */ true); + AppendInstruction(new (arena_) HNewArray(cls, length, dex_pc)); UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction()); break; } diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 911bfb9cc6..35f59cb4a4 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -777,7 +777,7 @@ void InstructionSimplifierVisitor::VisitArrayLength(HArrayLength* instruction) { // If the array is a NewArray with constant size, replace the array length // with the constant instruction. This helps the bounds check elimination phase. if (input->IsNewArray()) { - input = input->InputAt(0); + input = input->AsNewArray()->GetLength(); if (input->IsIntConstant()) { instruction->ReplaceWith(input); } @@ -1774,7 +1774,7 @@ static bool IsArrayLengthOf(HInstruction* potential_length, HInstruction* potent } if (potential_array->IsNewArray()) { - return potential_array->InputAt(0) == potential_length; + return potential_array->AsNewArray()->GetLength() == potential_length; } return false; diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 53b0fdde75..a2980dca20 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -3801,6 +3801,15 @@ class HNewInstance FINAL : public HExpression<1> { entrypoint_ = entrypoint; } + HLoadClass* GetLoadClass() const { + HInstruction* input = InputAt(0); + if (input->IsClinitCheck()) { + input = input->InputAt(0); + } + DCHECK(input->IsLoadClass()); + return input->AsLoadClass(); + } + bool IsStringAlloc() const; DECLARE_INSTRUCTION(NewInstance); @@ -4355,23 +4364,12 @@ class HNeg FINAL : public HUnaryOperation { class HNewArray FINAL : public HExpression<2> { public: - HNewArray(HInstruction* length, - HCurrentMethod* current_method, - uint32_t dex_pc, - dex::TypeIndex type_index, - const DexFile& dex_file, - QuickEntrypointEnum entrypoint) - : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc), - type_index_(type_index), - dex_file_(dex_file), - entrypoint_(entrypoint) { - SetRawInputAt(0, length); - SetRawInputAt(1, current_method); + HNewArray(HInstruction* cls, HInstruction* length, uint32_t dex_pc) + : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc) { + SetRawInputAt(0, cls); + SetRawInputAt(1, length); } - dex::TypeIndex GetTypeIndex() const { return type_index_; } - const DexFile& GetDexFile() const { return dex_file_; } - // Calls runtime so needs an environment. bool NeedsEnvironment() const OVERRIDE { return true; } @@ -4380,15 +4378,18 @@ class HNewArray FINAL : public HExpression<2> { bool CanBeNull() const OVERRIDE { return false; } - QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; } + HLoadClass* GetLoadClass() const { + DCHECK(InputAt(0)->IsLoadClass()); + return InputAt(0)->AsLoadClass(); + } + + HInstruction* GetLength() const { + return InputAt(1); + } DECLARE_INSTRUCTION(NewArray); private: - const dex::TypeIndex type_index_; - const DexFile& dex_file_; - const QuickEntrypointEnum entrypoint_; - DISALLOW_COPY_AND_ASSIGN(HNewArray); }; @@ -5891,7 +5892,10 @@ class HClinitCheck FINAL : public HExpression<1> { bool CanThrow() const OVERRIDE { return true; } - HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); } + HLoadClass* GetLoadClass() const { + DCHECK(InputAt(0)->IsLoadClass()); + return InputAt(0)->AsLoadClass(); + } DECLARE_INSTRUCTION(ClinitCheck); @@ -6757,6 +6761,23 @@ inline void MakeRoomFor(ArenaVector<HBasicBlock*>* blocks, std::copy_backward(blocks->begin() + after + 1u, blocks->begin() + old_size, blocks->end()); } +/* + * Hunt "under the hood" of array lengths (leading to array references), + * null checks (also leading to array references), and new arrays + * (leading to the actual length). This makes it more likely related + * instructions become actually comparable. + */ +inline HInstruction* HuntForDeclaration(HInstruction* instruction) { + while (instruction->IsArrayLength() || + instruction->IsNullCheck() || + instruction->IsNewArray()) { + instruction = instruction->IsNewArray() + ? instruction->AsNewArray()->GetLength() + : instruction->InputAt(0); + } + return instruction; +} + } // namespace art #endif // ART_COMPILER_OPTIMIZING_NODES_H_ diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 8854a2b08b..b02f2509ab 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -548,11 +548,13 @@ void ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* } void ReferenceTypePropagation::RTPVisitor::VisitNewInstance(HNewInstance* instr) { - UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile(), /* is_exact */ true); + ScopedObjectAccess soa(Thread::Current()); + SetClassAsTypeInfo(instr, instr->GetLoadClass()->GetClass().Get(), /* is_exact */ true); } void ReferenceTypePropagation::RTPVisitor::VisitNewArray(HNewArray* instr) { - UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile(), /* is_exact */ true); + ScopedObjectAccess soa(Thread::Current()); + SetClassAsTypeInfo(instr, instr->GetLoadClass()->GetClass().Get(), /* is_exact */ true); } static mirror::Class* GetClassFromDexCache(Thread* self, diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S index ed24a0723f..436d331119 100644 --- a/runtime/arch/arm64/quick_entrypoints_arm64.S +++ b/runtime/arch/arm64/quick_entrypoints_arm64.S @@ -1645,7 +1645,7 @@ GENERATE_ALLOC_ENTRYPOINTS_FOR_NON_REGION_TLAB_ALLOCATORS // GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_region_tlab, RegionTLAB) // GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_region_tlab, RegionTLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_region_tlab, RegionTLAB) -// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_region_tlab, RegionTLAB) implemented in asm +GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_region_tlab, RegionTLAB) // GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_region_tlab, RegionTLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_region_tlab, RegionTLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_BYTES(_region_tlab, RegionTLAB) @@ -1735,13 +1735,6 @@ END art_quick_alloc_object_resolved_rosalloc // The common fast path code for art_quick_alloc_array_region_tlab. -.macro ALLOC_ARRAY_TLAB_FAST_PATH slowPathLabel, xClass, wClass, xCount, wCount, xTemp0, wTemp0, xTemp1, wTemp1, xTemp2, wTemp2 - // Check null class - cbz \wClass, \slowPathLabel - ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED \slowPathLabel, \xClass, \wClass, \xCount, \wCount, \xTemp0, \wTemp0, \xTemp1, \wTemp1, \xTemp2, \wTemp2 -.endm - -// The common fast path code for art_quick_alloc_array_region_tlab. .macro ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED slowPathLabel, xClass, wClass, xCount, wCount, xTemp0, wTemp0, xTemp1, wTemp1, xTemp2, wTemp2 // Array classes are never finalizable or uninitialized, no need to check. ldr \wTemp0, [\xClass, #MIRROR_CLASS_COMPONENT_TYPE_OFFSET] // Load component type @@ -1878,64 +1871,31 @@ GENERATE_ALLOC_OBJECT_RESOLVED_REGION_TLAB art_quick_alloc_object_initialized_re // TODO: We could use this macro for the normal tlab allocator too. // The common code for art_quick_alloc_array_*region_tlab -.macro GENERATE_ALLOC_ARRAY_REGION_TLAB name, entrypoint, fast_path, is_resolved +.macro GENERATE_ALLOC_ARRAY_REGION_TLAB name, entrypoint, fast_path ENTRY \name // Fast path array allocation for region tlab allocation. - // x0: uint32_t type_idx + // x0: mirror::Class* type // x1: int32_t component_count - // x2: ArtMethod* method - // x3-x7: free. + // x2-x7: free. #if !defined(USE_READ_BARRIER) mvn x0, xzr // Read barrier must be enabled here. ret // Return -1. #endif -.if \is_resolved mov x3, x0 - // If already resolved, class is stored in x0 -.else - ldr x3, [x2, #ART_METHOD_DEX_CACHE_TYPES_OFFSET_64] // Load dex cache resolved types array - // Load the class (x2) - ldr w3, [x3, x0, lsl #COMPRESSED_REFERENCE_SIZE_SHIFT] -.endif - // Most common case: GC is not marking. - ldr w4, [xSELF, #THREAD_IS_GC_MARKING_OFFSET] - cbnz x4, .Lmarking\name -.Ldo_allocation\name: \fast_path .Lslow_path\name, x3, w3, x1, w1, x4, w4, x5, w5, x6, w6 -.Lmarking\name: - // GC is marking, check the lock word of the class for the mark bit. - // If the class is null, go slow path. The check is required to read the lock word. - cbz w3, .Lslow_path\name - // Class is not null, check mark bit in lock word. - ldr w4, [x3, #MIRROR_OBJECT_LOCK_WORD_OFFSET] - // If the bit is not zero, do the allocation. - tbnz w4, #LOCK_WORD_MARK_BIT_SHIFT, .Ldo_allocation\name - // The read barrier slow path. Mark - // the class. - stp x0, x1, [sp, #-32]! // Save registers (x0, x1, x2, lr). - stp x2, xLR, [sp, #16] - mov x0, x3 // Pass the class as the first param. - bl artReadBarrierMark - mov x3, x0 // Get the (marked) class back. - ldp x2, xLR, [sp, #16] - ldp x0, x1, [sp], #32 // Restore registers. - b .Ldo_allocation\name .Lslow_path\name: - // x0: uint32_t type_idx / mirror::Class* klass (if resolved) + // x0: mirror::Class* klass // x1: int32_t component_count - // x2: ArtMethod* method - // x3: Thread* self + // x2: Thread* self SETUP_SAVE_REFS_ONLY_FRAME // save callee saves in case of GC - mov x3, xSELF // pass Thread::Current + mov x2, xSELF // pass Thread::Current bl \entrypoint RESTORE_SAVE_REFS_ONLY_FRAME RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER END \name .endm -GENERATE_ALLOC_ARRAY_REGION_TLAB art_quick_alloc_array_region_tlab, artAllocArrayFromCodeRegionTLAB, ALLOC_ARRAY_TLAB_FAST_PATH, 0 -// TODO: art_quick_alloc_array_resolved_region_tlab seems to not get called. Investigate compiler. -GENERATE_ALLOC_ARRAY_REGION_TLAB art_quick_alloc_array_resolved_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED, 1 +GENERATE_ALLOC_ARRAY_REGION_TLAB art_quick_alloc_array_resolved_region_tlab, artAllocArrayFromCodeResolvedRegionTLAB, ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED /* * Called by managed code when the thread has been asked to suspend. diff --git a/runtime/arch/quick_alloc_entrypoints.S b/runtime/arch/quick_alloc_entrypoints.S index 3959cbee05..cd6424a489 100644 --- a/runtime/arch/quick_alloc_entrypoints.S +++ b/runtime/arch/quick_alloc_entrypoints.S @@ -25,7 +25,7 @@ ONE_ARG_DOWNCALL art_quick_alloc_object_with_checks\c_suffix, artAllocObjectFrom // Called by managed code to allocate an array. THREE_ARG_DOWNCALL art_quick_alloc_array\c_suffix, artAllocArrayFromCode\cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER // Called by managed code to allocate an array of a resolve class. -THREE_ARG_DOWNCALL art_quick_alloc_array_resolved\c_suffix, artAllocArrayFromCodeResolved\cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER +TWO_ARG_DOWNCALL art_quick_alloc_array_resolved\c_suffix, artAllocArrayFromCodeResolved\cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER // Called by managed code to allocate an array when the caller doesn't know whether it has access // to the created type. THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check\c_suffix, artAllocArrayFromCodeWithAccessCheck\cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER @@ -64,7 +64,7 @@ GENERATE_ALLOC_ENTRYPOINTS _region_tlab_instrumented, RegionTLABInstrumented #define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(c_suffix, cxx_suffix) \ THREE_ARG_DOWNCALL art_quick_alloc_array ## c_suffix, artAllocArrayFromCode ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER #define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(c_suffix, cxx_suffix) \ - THREE_ARG_DOWNCALL art_quick_alloc_array_resolved ## c_suffix, artAllocArrayFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER + TWO_ARG_DOWNCALL art_quick_alloc_array_resolved ## c_suffix, artAllocArrayFromCodeResolved ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER #define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(c_suffix, cxx_suffix) \ THREE_ARG_DOWNCALL art_quick_alloc_array_with_access_check ## c_suffix, artAllocArrayFromCodeWithAccessCheck ## cxx_suffix, RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER #define GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_BYTES(c_suffix, cxx_suffix) \ diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S index 550a5e8452..f5509bddcb 100644 --- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S +++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S @@ -986,7 +986,7 @@ GENERATE_ALLOC_ENTRYPOINTS_FOR_NON_TLAB_ALLOCATORS // GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_RESOLVED(_region_tlab, RegionTLAB) // GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_region_tlab, RegionTLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_region_tlab, RegionTLAB) -// GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_region_tlab, RegionTLAB) +GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_region_tlab, RegionTLAB) // GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_region_tlab, RegionTLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_region_tlab, RegionTLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_BYTES(_region_tlab, RegionTLAB) @@ -997,6 +997,7 @@ GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_STRING(_region_tlab, RegionTLAB) // GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_INITIALIZED(_tlab, TLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_OBJECT_WITH_ACCESS_CHECK(_tlab, TLAB) // GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab, TLAB) +GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab, TLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_WITH_ACCESS_CHECK(_tlab, TLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_BYTES(_tlab, TLAB) GENERATE_ALLOC_ENTRYPOINTS_ALLOC_STRING_FROM_CHARS(_tlab, TLAB) @@ -1115,12 +1116,11 @@ MACRO1(ALLOC_OBJECT_INITIALIZED_TLAB_FAST_PATH, slowPathLabel) END_MACRO // The fast path code for art_quick_alloc_array_region_tlab. -// Inputs: RDI: uint32_t type_idx, RSI: int32_t component_count, RDX: ArtMethod* method -// Temps: RCX: the class, r8, r9 +// Inputs: RDI: the class, RSI: int32_t component_count +// Free temps: RCX, RDX, R8, R9 // Output: RAX: return value. MACRO1(ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED, slowPathLabel) - movq %rcx, %r8 // Save class for later - movl MIRROR_CLASS_COMPONENT_TYPE_OFFSET(%rcx), %ecx // Load component type. + movl MIRROR_CLASS_COMPONENT_TYPE_OFFSET(%rdi), %ecx // Load component type. UNPOISON_HEAP_REF ecx movl MIRROR_CLASS_OBJECT_PRIMITIVE_TYPE_OFFSET(%rcx), %ecx // Load primitive type. shrq LITERAL(PRIMITIVE_TYPE_SIZE_SHIFT_SHIFT), %rcx // Get component size shift. @@ -1147,8 +1147,8 @@ MACRO1(ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED, slowPathLabel) // Store the class pointer in the // header. // No fence needed for x86. - POISON_HEAP_REF r8d - movl %r8d, MIRROR_OBJECT_CLASS_OFFSET(%rax) + POISON_HEAP_REF edi + movl %edi, MIRROR_OBJECT_CLASS_OFFSET(%rax) movl %esi, MIRROR_ARRAY_LENGTH_OFFSET(%rax) ret // Fast path succeeded. END_MACRO @@ -1169,8 +1169,8 @@ END_MACRO MACRO1(ALLOC_ARRAY_TLAB_SLOW_PATH, cxx_name) SETUP_SAVE_REFS_ONLY_FRAME // save ref containing registers for GC // Outgoing argument set up - movq %gs:THREAD_SELF_OFFSET, %rcx // pass Thread::Current() - call CALLVAR(cxx_name) // cxx_name(arg0, arg1, arg2, Thread*) + movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current() + call CALLVAR(cxx_name) // cxx_name(arg0, arg1, Thread*) RESTORE_SAVE_REFS_ONLY_FRAME // restore frame up to return address RETURN_IF_RESULT_IS_NON_ZERO_OR_DELIVER // return or deliver exception END_MACRO @@ -1195,73 +1195,21 @@ DEFINE_FUNCTION art_quick_alloc_object_initialized_tlab ALLOC_OBJECT_TLAB_SLOW_PATH artAllocObjectFromCodeInitializedTLAB END_FUNCTION art_quick_alloc_object_initialized_tlab -// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_tlab, TLAB). -DEFINE_FUNCTION art_quick_alloc_array_tlab - // RDI: uint32_t type_idx, RSI: int32_t component_count, RDX: ArtMethod* - // RCX: klass, R8, R9: free. RAX: return val. - movq ART_METHOD_DEX_CACHE_TYPES_OFFSET_64(%rdx), %rcx // Load dex cache resolved types array - movl 0(%rcx, %rdi, COMPRESSED_REFERENCE_SIZE), %ecx // Load the class - testl %ecx, %ecx - jz .Lart_quick_alloc_array_tlab_slow_path - ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED .Lart_quick_alloc_array_tlab_slow_path -.Lart_quick_alloc_array_tlab_slow_path: - ALLOC_ARRAY_TLAB_SLOW_PATH artAllocArrayFromCodeTLAB -END_FUNCTION art_quick_alloc_array_tlab - // A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_tlab, TLAB). DEFINE_FUNCTION art_quick_alloc_array_resolved_tlab - // RDI: mirror::Class* klass, RSI: int32_t component_count, RDX: ArtMethod* - // RCX: mirror::Class* klass, R8, R9: free. RAX: return val. - movq %rdi, %rcx - // Already resolved, no null check. + // RDI: mirror::Class* klass, RSI: int32_t component_count + // RDX, RCX, R8, R9: free. RAX: return val. ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED .Lart_quick_alloc_array_resolved_tlab_slow_path .Lart_quick_alloc_array_resolved_tlab_slow_path: ALLOC_ARRAY_TLAB_SLOW_PATH artAllocArrayFromCodeResolvedTLAB END_FUNCTION art_quick_alloc_array_resolved_tlab -// A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY(_region_tlab, RegionTLAB). -DEFINE_FUNCTION art_quick_alloc_array_region_tlab - // Fast path region tlab allocation. - // RDI: uint32_t type_idx, RSI: int32_t component_count, RDX: ArtMethod* - // RCX: klass, R8, R9: free. RAX: return val. - ASSERT_USE_READ_BARRIER - movq ART_METHOD_DEX_CACHE_TYPES_OFFSET_64(%rdx), %rcx // Load dex cache resolved types array - movl 0(%rcx, %rdi, COMPRESSED_REFERENCE_SIZE), %ecx // Load the class - // Null check so that we can load the lock word. - testl %ecx, %ecx - jz .Lart_quick_alloc_array_region_tlab_slow_path - // Since we have allocation entrypoint switching, we know the GC is marking. - // Check the mark bit, if it is 0, do the read barrier mark. - testl LITERAL(LOCK_WORD_MARK_BIT_MASK_SHIFTED), MIRROR_OBJECT_LOCK_WORD_OFFSET(%ecx) - jz .Lart_quick_alloc_array_region_tlab_class_load_read_barrier_slow_path -.Lart_quick_alloc_array_region_tlab_class_load_read_barrier_slow_path_exit: - ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED .Lart_quick_alloc_array_region_tlab_slow_path -.Lart_quick_alloc_array_region_tlab_class_load_read_barrier_slow_path: - // The read barrier slow path. Mark the class. - PUSH rdi - PUSH rsi - PUSH rdx - // Outgoing argument set up - movq %rcx, %rdi // Pass the class as the first param. - call SYMBOL(artReadBarrierMark) // cxx_name(mirror::Object* obj) - movq %rax, %rcx - POP rdx - POP rsi - POP rdi - jmp .Lart_quick_alloc_array_region_tlab_class_load_read_barrier_slow_path_exit -.Lart_quick_alloc_array_region_tlab_slow_path: - ALLOC_ARRAY_TLAB_SLOW_PATH artAllocArrayFromCodeRegionTLAB -END_FUNCTION art_quick_alloc_array_region_tlab - // A hand-written override for GENERATE_ALLOC_ENTRYPOINTS_ALLOC_ARRAY_RESOLVED(_region_tlab, RegionTLAB). DEFINE_FUNCTION art_quick_alloc_array_resolved_region_tlab // Fast path region tlab allocation. - // RDI: mirror::Class* klass, RSI: int32_t component_count, RDX: ArtMethod* - // RCX: mirror::Class* klass, R8, R9: free. RAX: return val. + // RDI: mirror::Class* klass, RSI: int32_t component_count + // RCX, RDX, R8, R9: free. RAX: return val. ASSERT_USE_READ_BARRIER - movq %rdi, %rcx - // Caller is responsible for read barrier. - // Already resolved, no null check. ALLOC_ARRAY_TLAB_FAST_PATH_RESOLVED .Lart_quick_alloc_array_resolved_region_tlab_slow_path .Lart_quick_alloc_array_resolved_region_tlab_slow_path: ALLOC_ARRAY_TLAB_SLOW_PATH artAllocArrayFromCodeResolvedRegionTLAB diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index 87046bc09d..ac0ce36016 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -293,11 +293,10 @@ inline mirror::Array* AllocArrayFromCode(dex::TypeIndex type_idx, klass->GetComponentSizeShift(), allocator_type); } -template <bool kAccessCheck, bool kInstrumented> +template <bool kInstrumented> ALWAYS_INLINE inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass, int32_t component_count, - ArtMethod* method, Thread* self, gc::AllocatorType allocator_type) { DCHECK(klass != nullptr); @@ -305,13 +304,6 @@ inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass, ThrowNegativeArraySizeException(component_count); return nullptr; // Failure } - if (kAccessCheck) { - mirror::Class* referrer = method->GetDeclaringClass(); - if (UNLIKELY(!referrer->CanAccess(klass))) { - ThrowIllegalAccessErrorClass(referrer, klass); - return nullptr; // Failure - } - } // No need to retry a slow-path allocation as the above code won't cause a GC or thread // suspension. return mirror::Array::Alloc<kInstrumented>(self, klass, component_count, diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h index b427c0717f..6a04f20f3a 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -93,10 +93,9 @@ ALWAYS_INLINE inline mirror::Array* AllocArrayFromCode(dex::TypeIndex type_idx, REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); -template <bool kAccessCheck, bool kInstrumented> +template <bool kInstrumented> ALWAYS_INLINE inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass, int32_t component_count, - ArtMethod* method, Thread* self, gc::AllocatorType allocator_type) REQUIRES_SHARED(Locks::mutator_lock_) diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc index 23a99a06c6..3fa5fbf44f 100644 --- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc @@ -93,11 +93,11 @@ extern "C" mirror::Array* artAllocArrayFromCode##suffix##suffix2( \ allocator_type); \ } \ extern "C" mirror::Array* artAllocArrayFromCodeResolved##suffix##suffix2( \ - mirror::Class* klass, int32_t component_count, ArtMethod* method, Thread* self) \ + mirror::Class* klass, int32_t component_count, Thread* self) \ REQUIRES_SHARED(Locks::mutator_lock_) { \ ScopedQuickEntrypointChecks sqec(self); \ - return AllocArrayFromCodeResolved<false, instrumented_bool>(klass, component_count, method, self, \ - allocator_type); \ + return AllocArrayFromCodeResolved<instrumented_bool>(klass, component_count, self, \ + allocator_type); \ } \ extern "C" mirror::Array* artAllocArrayFromCodeWithAccessCheck##suffix##suffix2( \ uint32_t type_idx, int32_t component_count, ArtMethod* method, Thread* self) \ @@ -149,7 +149,7 @@ GENERATE_ENTRYPOINTS_FOR_ALLOCATOR(RegionTLAB, gc::kAllocatorTypeRegionTLAB) #define GENERATE_ENTRYPOINTS(suffix) \ extern "C" void* art_quick_alloc_array##suffix(uint32_t, int32_t, ArtMethod* ref); \ -extern "C" void* art_quick_alloc_array_resolved##suffix(mirror::Class* klass, int32_t, ArtMethod* ref); \ +extern "C" void* art_quick_alloc_array_resolved##suffix(mirror::Class* klass, int32_t); \ extern "C" void* art_quick_alloc_array_with_access_check##suffix(uint32_t, int32_t, ArtMethod* ref); \ extern "C" void* art_quick_alloc_object_resolved##suffix(mirror::Class* klass); \ extern "C" void* art_quick_alloc_object_initialized##suffix(mirror::Class* klass); \ @@ -160,7 +160,7 @@ extern "C" void* art_quick_alloc_string_from_bytes##suffix(void*, int32_t, int32 extern "C" void* art_quick_alloc_string_from_chars##suffix(int32_t, int32_t, void*); \ extern "C" void* art_quick_alloc_string_from_string##suffix(void*); \ extern "C" void* art_quick_alloc_array##suffix##_instrumented(uint32_t, int32_t, ArtMethod* ref); \ -extern "C" void* art_quick_alloc_array_resolved##suffix##_instrumented(mirror::Class* klass, int32_t, ArtMethod* ref); \ +extern "C" void* art_quick_alloc_array_resolved##suffix##_instrumented(mirror::Class* klass, int32_t); \ extern "C" void* art_quick_alloc_array_with_access_check##suffix##_instrumented(uint32_t, int32_t, ArtMethod* ref); \ extern "C" void* art_quick_alloc_object##suffix##_instrumented(uint32_t type_idx, ArtMethod* ref); \ extern "C" void* art_quick_alloc_object_resolved##suffix##_instrumented(mirror::Class* klass); \ diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h index 0e75e94d52..b44f29b410 100644 --- a/runtime/entrypoints/quick/quick_entrypoints_list.h +++ b/runtime/entrypoints/quick/quick_entrypoints_list.h @@ -21,7 +21,7 @@ #define QUICK_ENTRYPOINT_LIST(V) \ V(AllocArray, void*, uint32_t, int32_t, ArtMethod*) \ - V(AllocArrayResolved, void*, mirror::Class*, int32_t, ArtMethod*) \ + V(AllocArrayResolved, void*, mirror::Class*, int32_t) \ V(AllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*) \ V(AllocObjectResolved, void*, mirror::Class*) \ V(AllocObjectInitialized, void*, mirror::Class*) \ diff --git a/runtime/generated/asm_support_gen.h b/runtime/generated/asm_support_gen.h index bebcd71951..9e7f52bfd3 100644 --- a/runtime/generated/asm_support_gen.h +++ b/runtime/generated/asm_support_gen.h @@ -60,10 +60,6 @@ DEFINE_CHECK_EQ(static_cast<uint32_t>(ACCESS_FLAGS_CLASS_IS_FINALIZABLE_BIT), (s DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_DEX_CACHE_METHODS_OFFSET_32), (static_cast<int32_t>(art::ArtMethod:: DexCacheResolvedMethodsOffset(art::PointerSize::k32).Int32Value()))) #define ART_METHOD_DEX_CACHE_METHODS_OFFSET_64 24 DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_DEX_CACHE_METHODS_OFFSET_64), (static_cast<int32_t>(art::ArtMethod:: DexCacheResolvedMethodsOffset(art::PointerSize::k64).Int32Value()))) -#define ART_METHOD_DEX_CACHE_TYPES_OFFSET_32 24 -DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_DEX_CACHE_TYPES_OFFSET_32), (static_cast<int32_t>(art::ArtMethod:: DexCacheResolvedTypesOffset(art::PointerSize::k32).Int32Value()))) -#define ART_METHOD_DEX_CACHE_TYPES_OFFSET_64 32 -DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_DEX_CACHE_TYPES_OFFSET_64), (static_cast<int32_t>(art::ArtMethod:: DexCacheResolvedTypesOffset(art::PointerSize::k64).Int32Value()))) #define ART_METHOD_JNI_OFFSET_32 28 DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_JNI_OFFSET_32), (static_cast<int32_t>(art::ArtMethod:: EntryPointFromJniOffset(art::PointerSize::k32).Int32Value()))) #define ART_METHOD_JNI_OFFSET_64 40 diff --git a/runtime/oat.h b/runtime/oat.h index f9396ae2ca..88fa2329cc 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -32,7 +32,7 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' }; - static constexpr uint8_t kOatVersion[] = { '0', '9', '9', '\0' }; // Remove old entrypoints + static constexpr uint8_t kOatVersion[] = { '1', '0', '0', '\0' }; // AllocArrayResolved change static constexpr const char* kImageLocationKey = "image-location"; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; diff --git a/test/559-checker-rtp-ifnotnull/src/Main.java b/test/559-checker-rtp-ifnotnull/src/Main.java index 2dc5666e18..1e15654950 100644 --- a/test/559-checker-rtp-ifnotnull/src/Main.java +++ b/test/559-checker-rtp-ifnotnull/src/Main.java @@ -18,7 +18,6 @@ public class Main { /// CHECK-START: void Main.boundTypeForIfNotNull() builder (after) - /// CHECK-DAG: <<Method:(i|j)\d+>> CurrentMethod /// CHECK-DAG: <<Null:l\d+>> NullConstant /// CHECK-DAG: <<Cst5:i\d+>> IntConstant 5 /// CHECK-DAG: <<Cst10:i\d+>> IntConstant 10 @@ -28,10 +27,12 @@ public class Main { /// CHECK-DAG: <<LoopPhi>> Phi [<<Null>>,<<MergePhi:l\d+>>] klass:int[] /// CHECK-DAG: <<BoundType:l\d+>> BoundType [<<LoopPhi>>] klass:int[] can_be_null:false - /// CHECK-DAG: <<NewArray10:l\d+>> NewArray [<<Cst10>>,<<Method>>] klass:int[] + /// CHECK-DAG: <<LoadClass1:l\d+>> LoadClass + /// CHECK-DAG: <<LoadClass2:l\d+>> LoadClass + /// CHECK-DAG: <<NewArray10:l\d+>> NewArray [<<LoadClass2>>,<<Cst10>>] klass:int[] /// CHECK-DAG: <<NotNullPhi:l\d+>> Phi [<<BoundType>>,<<NewArray10>>] klass:int[] - /// CHECK-DAG: <<NewArray5:l\d+>> NewArray [<<Cst5>>,<<Method>>] klass:int[] + /// CHECK-DAG: <<NewArray5:l\d+>> NewArray [<<LoadClass1>>,<<Cst5>>] klass:int[] /// CHECK-DAG: <<MergePhi>> Phi [<<NewArray5>>,<<NotNullPhi>>] klass:int[] public static void boundTypeForIfNotNull() { diff --git a/test/572-checker-array-get-regression/src/Main.java b/test/572-checker-array-get-regression/src/Main.java index 89b97ed316..03a84486de 100644 --- a/test/572-checker-array-get-regression/src/Main.java +++ b/test/572-checker-array-get-regression/src/Main.java @@ -21,10 +21,10 @@ public class Main { } /// CHECK-START: java.lang.Integer Main.test() builder (after) - /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod /// CHECK-DAG: <<Const2P19:i\d+>> IntConstant 524288 /// CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 - /// CHECK-DAG: <<Array:l\d+>> NewArray [<<Const2P19>>,<<Method>>] + /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass + /// CHECK-DAG: <<Array:l\d+>> NewArray [<<LoadClass>>,<<Const2P19>>] /// CHECK-DAG: <<Length1:i\d+>> ArrayLength [<<Array>>] /// CHECK-DAG: <<Index:i\d+>> Add [<<Length1>>,<<ConstM1>>] /// CHECK-DAG: <<Length2:i\d+>> ArrayLength [<<Array>>] @@ -34,10 +34,10 @@ public class Main { /// CHECK-START: java.lang.Integer Main.test() register (before) - /// CHECK-DAG: <<Method:[ij]\d+>> CurrentMethod /// CHECK-DAG: <<Const2P19:i\d+>> IntConstant 524288 /// CHECK-DAG: <<Const2P19M1:i\d+>> IntConstant 524287 - /// CHECK-DAG: <<Array:l\d+>> NewArray [<<Const2P19>>,<<Method>>] + /// CHECK-DAG: <<LoadClass:l\d+>> LoadClass + /// CHECK-DAG: <<Array:l\d+>> NewArray [<<LoadClass>>,<<Const2P19>>] /// CHECK-DAG: <<LastElement:l\d+>> ArrayGet [<<Array>>,<<Const2P19M1>>] /// CHECK-DAG: Return [<<LastElement>>] diff --git a/tools/cpp-define-generator/offset_dexcache.def b/tools/cpp-define-generator/offset_dexcache.def index abb5e1ecac..43f94344cc 100644 --- a/tools/cpp-define-generator/offset_dexcache.def +++ b/tools/cpp-define-generator/offset_dexcache.def @@ -34,7 +34,6 @@ // New macro suffix Method Name (of the Offset method) DEFINE_ART_METHOD_OFFSET_SIZED(DEX_CACHE_METHODS, DexCacheResolvedMethods) -DEFINE_ART_METHOD_OFFSET_SIZED(DEX_CACHE_TYPES, DexCacheResolvedTypes) DEFINE_ART_METHOD_OFFSET_SIZED(JNI, EntryPointFromJni) DEFINE_ART_METHOD_OFFSET_SIZED(QUICK_CODE, EntryPointFromQuickCompiledCode) DEFINE_ART_METHOD_OFFSET(DECLARING_CLASS, DeclaringClass) |