diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/builder.h | 15 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 11 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.cc | 20 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_mips64.h | 9 | ||||
| -rw-r--r-- | compiler/optimizing/common_arm64.h | 4 | ||||
| -rw-r--r-- | compiler/optimizing/inliner.cc | 45 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_builder.cc | 49 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_builder.h | 11 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_arm_vixl.cc | 26 | ||||
| -rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 26 | ||||
| -rw-r--r-- | compiler/optimizing/reference_type_propagation.cc | 46 | ||||
| -rw-r--r-- | compiler/optimizing/reference_type_propagation.h | 3 | ||||
| -rw-r--r-- | compiler/optimizing/reference_type_propagation_test.cc | 1 | ||||
| -rw-r--r-- | compiler/optimizing/ssa_builder.cc | 6 | ||||
| -rw-r--r-- | compiler/optimizing/ssa_builder.h | 3 | ||||
| -rw-r--r-- | compiler/optimizing/stack_map_stream.cc | 8 | ||||
| -rw-r--r-- | compiler/optimizing/stack_map_test.cc | 27 |
17 files changed, 182 insertions, 128 deletions
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 8cf4089eba..223439b0c7 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -51,7 +51,10 @@ class HGraphBuilder : public ValueObject { compiler_driver_(driver), compilation_stats_(compiler_stats), block_builder_(graph, dex_file, code_item), - ssa_builder_(graph, dex_compilation_unit->GetDexCache(), handles), + ssa_builder_(graph, + dex_compilation_unit->GetClassLoader(), + dex_compilation_unit->GetDexCache(), + handles), instruction_builder_(graph, &block_builder_, &ssa_builder_, @@ -76,10 +79,12 @@ class HGraphBuilder : public ValueObject { code_item_(code_item), dex_compilation_unit_(nullptr), compiler_driver_(nullptr), - null_dex_cache_(), compilation_stats_(nullptr), block_builder_(graph, nullptr, code_item), - ssa_builder_(graph, null_dex_cache_, handles), + ssa_builder_(graph, + handles->NewHandle<mirror::ClassLoader>(nullptr), + handles->NewHandle<mirror::DexCache>(nullptr), + handles), instruction_builder_(graph, &block_builder_, &ssa_builder_, @@ -91,7 +96,7 @@ class HGraphBuilder : public ValueObject { /* compiler_driver */ nullptr, /* interpreter_metadata */ nullptr, /* compiler_stats */ nullptr, - null_dex_cache_, + handles->NewHandle<mirror::DexCache>(nullptr), handles) {} GraphAnalysisResult BuildGraph(); @@ -112,8 +117,6 @@ class HGraphBuilder : public ValueObject { CompilerDriver* const compiler_driver_; - ScopedNullHandle<mirror::DexCache> null_dex_cache_; - OptimizingCompilerStats* compilation_stats_; HBasicBlockBuilder block_builder_; diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 1e89ba590c..cf824a14e3 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -1533,7 +1533,9 @@ void CodeGeneratorARM64::MoveLocation(Location destination, HConstant* src_cst = source.GetConstant(); CPURegister temp; if (src_cst->IsZeroBitPattern()) { - temp = (src_cst->IsLongConstant() || src_cst->IsDoubleConstant()) ? xzr : wzr; + temp = (src_cst->IsLongConstant() || src_cst->IsDoubleConstant()) + ? Register(xzr) + : Register(wzr); } else { if (src_cst->IsIntConstant()) { temp = temps.AcquireW(); @@ -1903,6 +1905,9 @@ void LocationsBuilderARM64::HandleFieldGet(HInstruction* instruction) { LocationSummary::kNoCall); if (object_field_get_with_read_barrier && kUseBakerReadBarrier) { locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers. + // We need a temporary register for the read barrier marking slow + // path in CodeGeneratorARM64::GenerateFieldLoadWithBakerReadBarrier. + locations->AddTemp(Location::RequiresRegister()); } locations->SetInAt(0, Location::RequiresRegister()); if (Primitive::IsFloatingPointType(instruction->GetType())) { @@ -1930,11 +1935,9 @@ void InstructionCodeGeneratorARM64::HandleFieldGet(HInstruction* instruction, if (field_type == Primitive::kPrimNot && kEmitCompilerReadBarrier && kUseBakerReadBarrier) { // Object FieldGet with Baker's read barrier case. - MacroAssembler* masm = GetVIXLAssembler(); - UseScratchRegisterScope temps(masm); // /* HeapReference<Object> */ out = *(base + offset) Register base = RegisterFrom(base_loc, Primitive::kPrimNot); - Register temp = temps.AcquireW(); + Register temp = WRegisterFrom(locations->GetTemp(0)); // Note that potential implicit null checks are handled in this // CodeGeneratorARM64::GenerateFieldLoadWithBakerReadBarrier call. codegen_->GenerateFieldLoadWithBakerReadBarrier( diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index 893e465392..f4d3ec54ee 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -7679,15 +7679,21 @@ void InstructionCodeGeneratorARMVIXL::VisitPackedSwitch(HPackedSwitch* switch_in vixl32::Register jump_offset = temps.Acquire(); // Load jump offset from the table. - __ Adr(table_base, jump_table->GetTableStartLabel()); - __ Ldr(jump_offset, MemOperand(table_base, key_reg, vixl32::LSL, 2)); + { + const size_t jump_size = switch_instr->GetNumEntries() * sizeof(int32_t); + ExactAssemblyScope aas(GetVIXLAssembler(), + (vixl32::kMaxInstructionSizeInBytes * 4) + jump_size, + CodeBufferCheckScope::kMaximumSize); + __ adr(table_base, jump_table->GetTableStartLabel()); + __ ldr(jump_offset, MemOperand(table_base, key_reg, vixl32::LSL, 2)); - // Jump to target block by branching to table_base(pc related) + offset. - vixl32::Register target_address = table_base; - __ Add(target_address, table_base, jump_offset); - __ Bx(target_address); + // Jump to target block by branching to table_base(pc related) + offset. + vixl32::Register target_address = table_base; + __ add(target_address, table_base, jump_offset); + __ bx(target_address); - jump_table->EmitTable(codegen_); + jump_table->EmitTable(codegen_); + } } } void LocationsBuilderARMVIXL::VisitArmDexCacheArraysBase(HArmDexCacheArraysBase* base) { diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h index 52b780c106..5ba8912134 100644 --- a/compiler/optimizing/code_generator_mips64.h +++ b/compiler/optimizing/code_generator_mips64.h @@ -115,12 +115,11 @@ class FieldAccessCallingConventionMIPS64 : public FieldAccessCallingConvention { Location GetReturnLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return Location::RegisterLocation(V0); } - Location GetSetValueLocation(Primitive::Type type, bool is_instance) const OVERRIDE { - return Primitive::Is64BitType(type) + Location GetSetValueLocation(Primitive::Type type ATTRIBUTE_UNUSED, + bool is_instance) const OVERRIDE { + return is_instance ? Location::RegisterLocation(A2) - : (is_instance - ? Location::RegisterLocation(A2) - : Location::RegisterLocation(A1)); + : Location::RegisterLocation(A1); } Location GetFpuLocation(Primitive::Type type ATTRIBUTE_UNUSED) const OVERRIDE { return Location::FpuRegisterLocation(F0); diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h index 776a483d43..93ea090583 100644 --- a/compiler/optimizing/common_arm64.h +++ b/compiler/optimizing/common_arm64.h @@ -130,8 +130,8 @@ inline vixl::aarch64::CPURegister InputCPURegisterOrZeroRegAt(HInstruction* inst Primitive::Type input_type = input->GetType(); if (input->IsConstant() && input->AsConstant()->IsZeroBitPattern()) { return (Primitive::ComponentSize(input_type) >= vixl::aarch64::kXRegSizeInBytes) - ? vixl::aarch64::xzr - : vixl::aarch64::wzr; + ? vixl::aarch64::Register(vixl::aarch64::xzr) + : vixl::aarch64::Register(vixl::aarch64::wzr); } return InputCPURegisterAt(instr, index); } diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 7772e8f973..22f0646fd0 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -198,9 +198,9 @@ static uint32_t FindMethodIndexIn(ArtMethod* method, } static dex::TypeIndex FindClassIndexIn(mirror::Class* cls, - const DexFile& dex_file, - Handle<mirror::DexCache> dex_cache) + const DexCompilationUnit& compilation_unit) REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile& dex_file = *compilation_unit.GetDexFile(); dex::TypeIndex index; if (cls->GetDexCache() == nullptr) { DCHECK(cls->IsArrayClass()) << cls->PrettyClass(); @@ -209,22 +209,19 @@ static dex::TypeIndex FindClassIndexIn(mirror::Class* cls, DCHECK(cls->IsProxyClass()) << cls->PrettyClass(); // TODO: deal with proxy classes. } else if (IsSameDexFile(cls->GetDexFile(), dex_file)) { - DCHECK_EQ(cls->GetDexCache(), dex_cache.Get()); + DCHECK_EQ(cls->GetDexCache(), compilation_unit.GetDexCache().Get()); index = cls->GetDexTypeIndex(); - // Update the dex cache to ensure the class is in. The generated code will - // consider it is. We make it safe by updating the dex cache, as other - // dex files might also load the class, and there is no guarantee the dex - // cache of the dex file of the class will be updated. - if (dex_cache->GetResolvedType(index) == nullptr) { - dex_cache->SetResolvedType(index, cls); - } } else { index = cls->FindTypeIndexInOtherDexFile(dex_file); - // We cannot guarantee the entry in the dex cache will resolve to the same class, + // We cannot guarantee the entry 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.IsValid() && dex_cache->GetResolvedType(index) != cls) { - index = dex::TypeIndex::Invalid(); + // the right class already resolved with the class loader. + if (index.IsValid()) { + ObjPtr<mirror::Class> resolved = ClassLinker::LookupResolvedType( + index, compilation_unit.GetDexCache().Get(), compilation_unit.GetClassLoader().Get()); + if (resolved != cls) { + index = dex::TypeIndex::Invalid(); + } } } @@ -451,9 +448,8 @@ bool HInliner::TryInlineMonomorphicCall(HInvoke* invoke_instruction, DCHECK(invoke_instruction->IsInvokeVirtual() || invoke_instruction->IsInvokeInterface()) << invoke_instruction->DebugName(); - const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile(); dex::TypeIndex class_index = FindClassIndexIn( - GetMonomorphicType(classes), caller_dex_file, caller_compilation_unit_.GetDexCache()); + GetMonomorphicType(classes), caller_compilation_unit_); if (!class_index.IsValid()) { VLOG(compiler) << "Call to " << ArtMethod::PrettyMethod(resolved_method) << " from inline cache is not inlined because its class is not" @@ -496,6 +492,7 @@ bool HInliner::TryInlineMonomorphicCall(HInvoke* invoke_instruction, // Run type propagation to get the guard typed, and eventually propagate the // type of the receiver. ReferenceTypePropagation rtp_fixup(graph_, + outer_compilation_unit_.GetClassLoader(), outer_compilation_unit_.GetDexCache(), handles_, /* is_first_run */ false); @@ -586,7 +583,6 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker(); PointerSize pointer_size = class_linker->GetImagePointerSize(); - const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile(); bool all_targets_inlined = true; bool one_target_inlined = false; @@ -608,8 +604,7 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, HInstruction* cursor = invoke_instruction->GetPrevious(); HBasicBlock* bb_cursor = invoke_instruction->GetBlock(); - dex::TypeIndex class_index = FindClassIndexIn( - handle.Get(), caller_dex_file, caller_compilation_unit_.GetDexCache()); + dex::TypeIndex class_index = FindClassIndexIn(handle.Get(), caller_compilation_unit_); HInstruction* return_replacement = nullptr; if (!class_index.IsValid() || !TryBuildAndInline(invoke_instruction, @@ -665,6 +660,7 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, // Run type propagation to get the guards typed. ReferenceTypePropagation rtp_fixup(graph_, + outer_compilation_unit_.GetClassLoader(), outer_compilation_unit_.GetDexCache(), handles_, /* is_first_run */ false); @@ -859,6 +855,7 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget( // Run type propagation to get the guard typed. ReferenceTypePropagation rtp_fixup(graph_, + outer_compilation_unit_.GetClassLoader(), outer_compilation_unit_.GetDexCache(), handles_, /* is_first_run */ false); @@ -927,6 +924,7 @@ bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction, // Actual return value has a more specific type than the method's declared // return type. Run RTP again on the outer graph to propagate it. ReferenceTypePropagation(graph_, + outer_compilation_unit_.GetClassLoader(), outer_compilation_unit_.GetDexCache(), handles_, /* is_first_run */ false).Run(); @@ -1179,7 +1177,11 @@ HInstanceFieldGet* HInliner::CreateInstanceFieldGet(Handle<mirror::DexCache> dex /* dex_pc */ 0); if (iget->GetType() == Primitive::kPrimNot) { // Use the same dex_cache that we used for field lookup as the hint_dex_cache. - ReferenceTypePropagation rtp(graph_, dex_cache, handles_, /* is_first_run */ false); + ReferenceTypePropagation rtp(graph_, + outer_compilation_unit_.GetClassLoader(), + dex_cache, + handles_, + /* is_first_run */ false); rtp.Visit(iget); } return iget; @@ -1225,7 +1227,7 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, resolved_method->GetDeclaringClass()->GetClassLoader())); DexCompilationUnit dex_compilation_unit( - class_loader.ToJObject(), + class_loader, class_linker, callee_dex_file, code_item, @@ -1341,6 +1343,7 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, // are more specific than the declared ones, run RTP again on the inner graph. if (run_rtp || ArgumentTypesMoreSpecific(invoke_instruction, resolved_method)) { ReferenceTypePropagation(callee_graph, + outer_compilation_unit_.GetClassLoader(), dex_compilation_unit.GetDexCache(), handles_, /* is_first_run */ false).Run(); diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index cac385ce3c..3d911d77ba 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -668,11 +668,10 @@ static InvokeType GetInvokeTypeFromOpCode(Instruction::Code opcode) { ArtMethod* HInstructionBuilder::ResolveMethod(uint16_t method_idx, InvokeType invoke_type) { ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<3> hs(soa.Self()); + StackHandleScope<2> hs(soa.Self()); ClassLinker* class_linker = dex_compilation_unit_->GetClassLinker(); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle( - soa.Decode<mirror::ClassLoader>(dex_compilation_unit_->GetClassLoader()))); + Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader(); Handle<mirror::Class> compiling_class(hs.NewHandle(GetCompilingClass())); // We fetch the referenced class eagerly (that is, the class pointed by in the MethodId // at method_idx), as `CanAccessResolvedMethod` expects it be be in the dex cache. @@ -1284,9 +1283,7 @@ bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instructio static mirror::Class* GetClassFrom(CompilerDriver* driver, const DexCompilationUnit& compilation_unit) { ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<1> hs(soa.Self()); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle( - soa.Decode<mirror::ClassLoader>(compilation_unit.GetClassLoader()))); + Handle<mirror::ClassLoader> class_loader = compilation_unit.GetClassLoader(); Handle<mirror::DexCache> dex_cache = compilation_unit.GetDexCache(); return driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, &compilation_unit); @@ -1302,10 +1299,9 @@ mirror::Class* HInstructionBuilder::GetCompilingClass() const { bool HInstructionBuilder::IsOutermostCompilingClass(dex::TypeIndex type_index) const { ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<3> hs(soa.Self()); + StackHandleScope<2> hs(soa.Self()); Handle<mirror::DexCache> dex_cache = dex_compilation_unit_->GetDexCache(); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle( - soa.Decode<mirror::ClassLoader>(dex_compilation_unit_->GetClassLoader()))); + Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader(); Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass( soa, dex_cache, class_loader, type_index, dex_compilation_unit_))); Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass())); @@ -1343,10 +1339,8 @@ bool HInstructionBuilder::BuildStaticFieldAccess(const Instruction& instruction, uint16_t field_index = instruction.VRegB_21c(); ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<3> hs(soa.Self()); Handle<mirror::DexCache> dex_cache = dex_compilation_unit_->GetDexCache(); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle( - soa.Decode<mirror::ClassLoader>(dex_compilation_unit_->GetClassLoader()))); + Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader(); ArtField* resolved_field = compiler_driver_->ResolveField( soa, dex_cache, class_loader, dex_compilation_unit_, field_index, true); @@ -1357,6 +1351,7 @@ bool HInstructionBuilder::BuildStaticFieldAccess(const Instruction& instruction, return true; } + StackHandleScope<2> hs(soa.Self()); Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType(); Handle<mirror::DexCache> outer_dex_cache = outer_compilation_unit_->GetDexCache(); Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass())); @@ -1635,9 +1630,7 @@ 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(); - StackHandleScope<1> hs(soa.Self()); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle( - soa.Decode<mirror::ClassLoader>(dex_compilation_unit_->GetClassLoader()))); + Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader(); Handle<mirror::Class> klass = handles_->NewHandle(compiler_driver_->ResolveClass( soa, compilation_unit->GetDexCache(), class_loader, type_index, compilation_unit)); @@ -1692,17 +1685,9 @@ void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction, } } -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(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); + return !compiler_driver_->CanAccessInstantiableTypeWithoutChecks( + LookupReferrerClass(), LookupResolvedType(type_index, *dex_compilation_unit_), finalizable); } bool HInstructionBuilder::CanDecodeQuickenedInfo() const { @@ -2742,4 +2727,18 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, return true; } // NOLINT(readability/fn_size) +ObjPtr<mirror::Class> HInstructionBuilder::LookupResolvedType( + dex::TypeIndex type_index, + const DexCompilationUnit& compilation_unit) const { + return ClassLinker::LookupResolvedType( + type_index, compilation_unit.GetDexCache().Get(), compilation_unit.GetClassLoader().Get()); +} + +ObjPtr<mirror::Class> HInstructionBuilder::LookupReferrerClass() const { + // TODO: Cache the result in a Handle<mirror::Class>. + const DexFile::MethodId& method_id = + dex_compilation_unit_->GetDexFile()->GetMethodId(dex_compilation_unit_->GetDexMethodIndex()); + return LookupResolvedType(method_id.class_idx_, *dex_compilation_unit_); +} + } // namespace art diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h index 5efe95094c..6e3b078dbb 100644 --- a/compiler/optimizing/instruction_builder.h +++ b/compiler/optimizing/instruction_builder.h @@ -103,11 +103,8 @@ class HInstructionBuilder : public ValueObject { // Returns whether the current method needs access check for the type. // Output parameter finalizable is set to whether the type is finalizable. - bool NeedsAccessCheck(dex::TypeIndex type_index, - Handle<mirror::DexCache> dex_cache, - /*out*/bool* finalizable) const + bool NeedsAccessCheck(dex::TypeIndex type_index, /*out*/bool* finalizable) const REQUIRES_SHARED(Locks::mutator_lock_); - 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); @@ -290,6 +287,12 @@ class HInstructionBuilder : public ValueObject { // not be resolved. ArtMethod* ResolveMethod(uint16_t method_idx, InvokeType invoke_type); + ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_index, + const DexCompilationUnit& compilation_unit) const + REQUIRES_SHARED(Locks::mutator_lock_); + + ObjPtr<mirror::Class> LookupReferrerClass() const REQUIRES_SHARED(Locks::mutator_lock_); + ArenaAllocator* const arena_; HGraph* const graph_; VariableSizedHandleScope* handles_; diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index 68c2d2e36e..91d9c56d10 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc @@ -2742,14 +2742,36 @@ void IntrinsicCodeGeneratorARMVIXL::VisitReferenceGetReferent(HInvoke* invoke) { __ Bind(slow_path->GetExitLabel()); } +void IntrinsicLocationsBuilderARMVIXL::VisitMathCeil(HInvoke* invoke) { + if (features_.HasARMv8AInstructions()) { + CreateFPToFPLocations(arena_, invoke); + } +} + +void IntrinsicCodeGeneratorARMVIXL::VisitMathCeil(HInvoke* invoke) { + ArmVIXLAssembler* assembler = GetAssembler(); + DCHECK(codegen_->GetInstructionSetFeatures().HasARMv8AInstructions()); + __ Vrintp(F64, F64, OutputDRegister(invoke), InputDRegisterAt(invoke, 0)); +} + +void IntrinsicLocationsBuilderARMVIXL::VisitMathFloor(HInvoke* invoke) { + if (features_.HasARMv8AInstructions()) { + CreateFPToFPLocations(arena_, invoke); + } +} + +void IntrinsicCodeGeneratorARMVIXL::VisitMathFloor(HInvoke* invoke) { + ArmVIXLAssembler* assembler = GetAssembler(); + DCHECK(codegen_->GetInstructionSetFeatures().HasARMv8AInstructions()); + __ Vrintm(F64, F64, OutputDRegister(invoke), InputDRegisterAt(invoke, 0)); +} + UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathMinDoubleDouble) UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathMinFloatFloat) UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathMaxDoubleDouble) UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathMaxFloatFloat) UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathMinLongLong) UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathMaxLongLong) -UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathCeil) // Could be done by changing rounding mode, maybe? -UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathFloor) // Could be done by changing rounding mode, maybe? UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathRint) UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathRoundDouble) // Could be done by changing rounding mode, maybe? UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathRoundFloat) // Could be done by changing rounding mode, maybe? diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 297500b12f..dad87e3d9e 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -305,7 +305,7 @@ class OptimizingCompiler FINAL : public Compiler { InvokeType invoke_type, uint16_t class_def_idx, uint32_t method_idx, - jobject class_loader, + Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file, Handle<mirror::DexCache> dex_cache) const OVERRIDE; @@ -374,7 +374,7 @@ class OptimizingCompiler FINAL : public Compiler { InvokeType invoke_type, uint16_t class_def_idx, uint32_t method_idx, - jobject class_loader, + Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file, Handle<mirror::DexCache> dex_cache, ArtMethod* method, @@ -871,7 +871,7 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena, InvokeType invoke_type, uint16_t class_def_idx, uint32_t method_idx, - jobject class_loader, + Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file, Handle<mirror::DexCache> dex_cache, ArtMethod* method, @@ -942,11 +942,8 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena, const uint8_t* interpreter_metadata = nullptr; if (method == nullptr) { ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<1> hs(soa.Self()); - Handle<mirror::ClassLoader> loader(hs.NewHandle( - soa.Decode<mirror::ClassLoader>(class_loader))); method = compiler_driver->ResolveMethod( - soa, dex_cache, loader, &dex_compilation_unit, method_idx, invoke_type); + soa, dex_cache, class_loader, &dex_compilation_unit, method_idx, invoke_type); } // For AOT compilation, we may not get a method, for example if its class is erroneous. // JIT should always have a method. @@ -955,16 +952,6 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena, graph->SetArtMethod(method); ScopedObjectAccess soa(Thread::Current()); interpreter_metadata = method->GetQuickenedInfo(class_linker->GetImagePointerSize()); - 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 - // don't necessarily run the verifier. - // The compiler and the compiler driver assume the compiling class is - // in the dex cache. - if (dex_cache->GetResolvedType(type_index) == nullptr) { - dex_cache->SetResolvedType(type_index, method->GetDeclaringClass()); - } } std::unique_ptr<CodeGenerator> codegen( @@ -1044,7 +1031,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, InvokeType invoke_type, uint16_t class_def_idx, uint32_t method_idx, - jobject jclass_loader, + Handle<mirror::ClassLoader> jclass_loader, const DexFile& dex_file, Handle<mirror::DexCache> dex_cache) const { CompilerDriver* compiler_driver = GetCompilerDriver(); @@ -1139,7 +1126,6 @@ bool OptimizingCompiler::JitCompile(Thread* self, Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache())); DCHECK(method->IsCompilable()); - jobject jclass_loader = class_loader.ToJObject(); const DexFile* dex_file = method->GetDexFile(); const uint16_t class_def_idx = method->GetClassDefIndex(); const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset()); @@ -1163,7 +1149,7 @@ bool OptimizingCompiler::JitCompile(Thread* self, invoke_type, class_def_idx, method_idx, - jclass_loader, + class_loader, *dex_file, dex_cache, method, diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index b02f2509ab..be4857a49a 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -66,11 +66,13 @@ ReferenceTypeInfo::TypeHandle ReferenceTypePropagation::HandleCache::GetThrowabl class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { public: RTPVisitor(HGraph* graph, + Handle<mirror::ClassLoader> class_loader, Handle<mirror::DexCache> hint_dex_cache, HandleCache* handle_cache, ArenaVector<HInstruction*>* worklist, bool is_first_run) : HGraphDelegateVisitor(graph), + class_loader_(class_loader), hint_dex_cache_(hint_dex_cache), handle_cache_(handle_cache), worklist_(worklist), @@ -102,6 +104,7 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { bool is_exact); private: + Handle<mirror::ClassLoader> class_loader_; Handle<mirror::DexCache> hint_dex_cache_; HandleCache* handle_cache_; ArenaVector<HInstruction*>* worklist_; @@ -109,11 +112,13 @@ class ReferenceTypePropagation::RTPVisitor : public HGraphDelegateVisitor { }; ReferenceTypePropagation::ReferenceTypePropagation(HGraph* graph, + Handle<mirror::ClassLoader> class_loader, Handle<mirror::DexCache> hint_dex_cache, VariableSizedHandleScope* handles, bool is_first_run, const char* name) : HOptimization(graph, name), + class_loader_(class_loader), hint_dex_cache_(hint_dex_cache), handle_cache_(handles), worklist_(graph->GetArena()->Adapter(kArenaAllocReferenceTypePropagation)), @@ -148,7 +153,12 @@ void ReferenceTypePropagation::ValidateTypes() { } void ReferenceTypePropagation::Visit(HInstruction* instruction) { - RTPVisitor visitor(graph_, hint_dex_cache_, &handle_cache_, &worklist_, is_first_run_); + RTPVisitor visitor(graph_, + class_loader_, + hint_dex_cache_, + &handle_cache_, + &worklist_, + is_first_run_); instruction->Accept(&visitor); } @@ -322,7 +332,12 @@ void ReferenceTypePropagation::Run() { } void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) { - RTPVisitor visitor(graph_, hint_dex_cache_, &handle_cache_, &worklist_, is_first_run_); + RTPVisitor visitor(graph_, + class_loader_, + hint_dex_cache_, + &handle_cache_, + &worklist_, + is_first_run_); // Handle Phis first as there might be instructions in the same block who depend on them. for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) { VisitPhi(it.Current()->AsPhi()); @@ -542,9 +557,10 @@ void ReferenceTypePropagation::RTPVisitor::UpdateReferenceTypeInfo(HInstruction* DCHECK_EQ(instr->GetType(), Primitive::kPrimNot); ScopedObjectAccess soa(Thread::Current()); - mirror::DexCache* dex_cache = FindDexCacheWithHint(soa.Self(), dex_file, hint_dex_cache_); - // Get type from dex cache assuming it was populated by the verifier. - SetClassAsTypeInfo(instr, dex_cache->GetResolvedType(type_idx), is_exact); + ObjPtr<mirror::DexCache> dex_cache = FindDexCacheWithHint(soa.Self(), dex_file, hint_dex_cache_); + ObjPtr<mirror::Class> klass = + ClassLinker::LookupResolvedType(type_idx, dex_cache, class_loader_.Get()); + SetClassAsTypeInfo(instr, klass, is_exact); } void ReferenceTypePropagation::RTPVisitor::VisitNewInstance(HNewInstance* instr) { @@ -557,25 +573,13 @@ void ReferenceTypePropagation::RTPVisitor::VisitNewArray(HNewArray* instr) { SetClassAsTypeInfo(instr, instr->GetLoadClass()->GetClass().Get(), /* is_exact */ true); } -static mirror::Class* GetClassFromDexCache(Thread* self, - const DexFile& dex_file, - 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); - // Get type from dex cache assuming it was populated by the verifier. - return dex_cache->GetResolvedType(type_idx); -} - void ReferenceTypePropagation::RTPVisitor::VisitParameterValue(HParameterValue* instr) { // We check if the existing type is valid: the inliner may have set it. if (instr->GetType() == Primitive::kPrimNot && !instr->GetReferenceTypeInfo().IsValid()) { - ScopedObjectAccess soa(Thread::Current()); - mirror::Class* resolved_class = GetClassFromDexCache(soa.Self(), - instr->GetDexFile(), - instr->GetTypeIndex(), - hint_dex_cache_); - SetClassAsTypeInfo(instr, resolved_class, /* is_exact */ false); + UpdateReferenceTypeInfo(instr, + instr->GetTypeIndex(), + instr->GetDexFile(), + /* is_exact */ false); } } diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h index 4663471729..215e96786b 100644 --- a/compiler/optimizing/reference_type_propagation.h +++ b/compiler/optimizing/reference_type_propagation.h @@ -33,6 +33,7 @@ namespace art { class ReferenceTypePropagation : public HOptimization { public: ReferenceTypePropagation(HGraph* graph, + Handle<mirror::ClassLoader> class_loader, Handle<mirror::DexCache> hint_dex_cache, VariableSizedHandleScope* handles, bool is_first_run, @@ -105,6 +106,8 @@ class ReferenceTypePropagation : public HOptimization { void ValidateTypes(); + Handle<mirror::ClassLoader> class_loader_; + // Note: hint_dex_cache_ is usually, but not necessarily, the dex cache associated with // graph_->GetDexFile(). Since we may look up also in other dex files, it's used only // as a hint, to reduce the number of calls to the costly ClassLinker::FindDexCache(). diff --git a/compiler/optimizing/reference_type_propagation_test.cc b/compiler/optimizing/reference_type_propagation_test.cc index b061c871b0..84a4bab1a9 100644 --- a/compiler/optimizing/reference_type_propagation_test.cc +++ b/compiler/optimizing/reference_type_propagation_test.cc @@ -38,6 +38,7 @@ class ReferenceTypePropagationTest : public CommonCompilerTest { void SetupPropagation(VariableSizedHandleScope* handles) { graph_->InitializeInexactObjectRTI(handles); propagation_ = new (&allocator_) ReferenceTypePropagation(graph_, + Handle<mirror::ClassLoader>(), Handle<mirror::DexCache>(), handles, true, diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc index ae1e369999..d6edb650ba 100644 --- a/compiler/optimizing/ssa_builder.cc +++ b/compiler/optimizing/ssa_builder.cc @@ -497,7 +497,11 @@ GraphAnalysisResult SsaBuilder::BuildSsa() { // 4) Compute type of reference type instructions. The pass assumes that // NullConstant has been fixed up. - ReferenceTypePropagation(graph_, dex_cache_, handles_, /* is_first_run */ true).Run(); + ReferenceTypePropagation(graph_, + class_loader_, + dex_cache_, + handles_, + /* is_first_run */ true).Run(); // 5) HInstructionBuilder duplicated ArrayGet instructions with ambiguous type // (int/float or long/double) and marked ArraySets with ambiguous input type. diff --git a/compiler/optimizing/ssa_builder.h b/compiler/optimizing/ssa_builder.h index 45dac54115..978f113ec4 100644 --- a/compiler/optimizing/ssa_builder.h +++ b/compiler/optimizing/ssa_builder.h @@ -48,9 +48,11 @@ namespace art { class SsaBuilder : public ValueObject { public: SsaBuilder(HGraph* graph, + Handle<mirror::ClassLoader> class_loader, Handle<mirror::DexCache> dex_cache, VariableSizedHandleScope* handles) : graph_(graph), + class_loader_(class_loader), dex_cache_(dex_cache), handles_(handles), agets_fixed_(false), @@ -115,6 +117,7 @@ class SsaBuilder : public ValueObject { void RemoveRedundantUninitializedStrings(); HGraph* graph_; + Handle<mirror::ClassLoader> class_loader_; Handle<mirror::DexCache> dex_cache_; VariableSizedHandleScope* const handles_; diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc index a9a1e6f592..1b9bd7eb31 100644 --- a/compiler/optimizing/stack_map_stream.cc +++ b/compiler/optimizing/stack_map_stream.cc @@ -165,7 +165,7 @@ size_t StackMapStream::PrepareForFillIn() { inline_info_size_, register_mask_max_, stack_mask_number_of_bits); - stack_maps_size_ = stack_maps_.size() * stack_map_size; + stack_maps_size_ = RoundUp(stack_maps_.size() * stack_map_size, kBitsPerByte) / kBitsPerByte; dex_register_location_catalog_size_ = ComputeDexRegisterLocationCatalogSize(); size_t non_header_size = @@ -178,7 +178,7 @@ size_t StackMapStream::PrepareForFillIn() { CodeInfoEncoding code_info_encoding; code_info_encoding.non_header_size = non_header_size; code_info_encoding.number_of_stack_maps = stack_maps_.size(); - code_info_encoding.stack_map_size_in_bytes = stack_map_size; + code_info_encoding.stack_map_size_in_bits = stack_map_size; code_info_encoding.stack_map_encoding = stack_map_encoding_; code_info_encoding.inline_info_encoding = inline_info_encoding_; code_info_encoding.number_of_location_catalog_entries = location_catalog_entries_.size(); @@ -322,7 +322,7 @@ void StackMapStream::FillIn(MemoryRegion region) { stack_map.SetDexPc(stack_map_encoding_, entry.dex_pc); stack_map.SetNativePcCodeOffset(stack_map_encoding_, entry.native_pc_code_offset); stack_map.SetRegisterMask(stack_map_encoding_, entry.register_mask); - size_t number_of_stack_mask_bits = stack_map.GetNumberOfStackMaskBits(stack_map_encoding_); + size_t number_of_stack_mask_bits = code_info.GetNumberOfStackMaskBits(encoding); if (entry.sp_mask != nullptr) { for (size_t bit = 0; bit < number_of_stack_mask_bits; bit++) { stack_map.SetStackMaskBit(stack_map_encoding_, bit, entry.sp_mask->IsBitSet(bit)); @@ -551,7 +551,7 @@ void StackMapStream::CheckCodeInfo(MemoryRegion region) const { entry.native_pc_code_offset.Uint32Value(instruction_set_)); DCHECK_EQ(stack_map.GetDexPc(stack_map_encoding), entry.dex_pc); DCHECK_EQ(stack_map.GetRegisterMask(stack_map_encoding), entry.register_mask); - size_t num_stack_mask_bits = stack_map.GetNumberOfStackMaskBits(stack_map_encoding); + size_t num_stack_mask_bits = code_info.GetNumberOfStackMaskBits(encoding); if (entry.sp_mask != nullptr) { DCHECK_GE(num_stack_mask_bits, entry.sp_mask->GetNumberOfBits()); for (size_t b = 0; b < num_stack_mask_bits; b++) { diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc index f68695bcbc..da4597e385 100644 --- a/compiler/optimizing/stack_map_test.cc +++ b/compiler/optimizing/stack_map_test.cc @@ -27,10 +27,10 @@ namespace art { // Check that the stack mask of given stack map is identical // to the given bit vector. Returns true if they are same. static bool CheckStackMask( + int number_of_bits, const StackMap& stack_map, StackMapEncoding& encoding, const BitVector& bit_vector) { - int number_of_bits = stack_map.GetNumberOfStackMaskBits(encoding); if (bit_vector.GetHighestBitSet() >= number_of_bits) { return false; } @@ -81,7 +81,10 @@ TEST(StackMapTest, Test1) { ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map_encoding, kRuntimeISA)); ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding.stack_map_encoding)); - ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask)); + ASSERT_TRUE(CheckStackMask(code_info.GetNumberOfStackMaskBits(encoding), + stack_map, + encoding.stack_map_encoding, + sp_mask)); ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding)); DexRegisterMap dex_register_map = @@ -196,7 +199,10 @@ TEST(StackMapTest, Test2) { ASSERT_EQ(64u, stack_map.GetNativePcOffset(encoding.stack_map_encoding, kRuntimeISA)); ASSERT_EQ(0x3u, stack_map.GetRegisterMask(encoding.stack_map_encoding)); - ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask1)); + ASSERT_TRUE(CheckStackMask(code_info.GetNumberOfStackMaskBits(encoding), + stack_map, + encoding.stack_map_encoding, + sp_mask1)); ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding)); DexRegisterMap dex_register_map = @@ -255,7 +261,10 @@ TEST(StackMapTest, Test2) { ASSERT_EQ(128u, stack_map.GetNativePcOffset(encoding.stack_map_encoding, kRuntimeISA)); ASSERT_EQ(0xFFu, stack_map.GetRegisterMask(encoding.stack_map_encoding)); - ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask2)); + ASSERT_TRUE(CheckStackMask(code_info.GetNumberOfStackMaskBits(encoding), + stack_map, + encoding.stack_map_encoding, + sp_mask2)); ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding)); DexRegisterMap dex_register_map = @@ -309,7 +318,10 @@ TEST(StackMapTest, Test2) { ASSERT_EQ(192u, stack_map.GetNativePcOffset(encoding.stack_map_encoding, kRuntimeISA)); ASSERT_EQ(0xABu, stack_map.GetRegisterMask(encoding.stack_map_encoding)); - ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask3)); + ASSERT_TRUE(CheckStackMask(code_info.GetNumberOfStackMaskBits(encoding), + stack_map, + encoding.stack_map_encoding, + sp_mask3)); ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding)); DexRegisterMap dex_register_map = @@ -363,7 +375,10 @@ TEST(StackMapTest, Test2) { ASSERT_EQ(256u, stack_map.GetNativePcOffset(encoding.stack_map_encoding, kRuntimeISA)); ASSERT_EQ(0xCDu, stack_map.GetRegisterMask(encoding.stack_map_encoding)); - ASSERT_TRUE(CheckStackMask(stack_map, encoding.stack_map_encoding, sp_mask4)); + ASSERT_TRUE(CheckStackMask(code_info.GetNumberOfStackMaskBits(encoding), + stack_map, + encoding.stack_map_encoding, + sp_mask4)); ASSERT_TRUE(stack_map.HasDexRegisterMap(encoding.stack_map_encoding)); DexRegisterMap dex_register_map = |