diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/intrinsics_riscv64.cc | 64 | ||||
| -rw-r--r-- | compiler/optimizing/load_store_elimination.cc | 28 | ||||
| -rw-r--r-- | compiler/optimizing/nodes.h | 10 |
3 files changed, 71 insertions, 31 deletions
diff --git a/compiler/optimizing/intrinsics_riscv64.cc b/compiler/optimizing/intrinsics_riscv64.cc index 4c56800920..9379c8d3f6 100644 --- a/compiler/optimizing/intrinsics_riscv64.cc +++ b/compiler/optimizing/intrinsics_riscv64.cc @@ -5783,8 +5783,8 @@ void IntrinsicLocationsBuilderRISCV64::VisitMethodHandleInvokeExact(HInvoke* inv // The last input is MethodType object corresponding to the call-site. locations->SetInAt(number_of_args, Location::RequiresRegister()); - locations->AddTemp(Location::RequiresRegister()); locations->AddTemp(calling_convention.GetMethodLocation()); + locations->AddRegisterTemps(2); } void IntrinsicCodeGeneratorRISCV64::VisitMethodHandleInvokeExact(HInvoke* invoke) { @@ -5799,17 +5799,67 @@ void IntrinsicCodeGeneratorRISCV64::VisitMethodHandleInvokeExact(HInvoke* invoke locations->InAt(invoke->GetNumberOfArguments()).AsRegister<XRegister>(); // Call site should match with MethodHandle's type. - XRegister temp = locations->GetTemp(0).AsRegister<XRegister>(); + XRegister temp = locations->GetTemp(1).AsRegister<XRegister>(); __ Loadwu(temp, method_handle, mirror::MethodHandle::MethodTypeOffset().Int32Value()); codegen_->MaybeUnpoisonHeapReference(temp); __ Bne(call_site_type, temp, slow_path->GetEntryLabel()); - __ Loadwu(temp, method_handle, mirror::MethodHandle::HandleKindOffset().Int32Value()); - __ AddConst32(temp, temp, -mirror::MethodHandle::Kind::kInvokeStatic); - __ Bnez(temp, slow_path->GetEntryLabel()); - - XRegister method = locations->GetTemp(1).AsRegister<XRegister>(); + XRegister method = locations->GetTemp(0).AsRegister<XRegister>(); __ Loadd(method, method_handle, mirror::MethodHandle::ArtFieldOrMethodOffset().Int32Value()); + + Riscv64Label execute_target_method; + + XRegister method_handle_kind = locations->GetTemp(2).AsRegister<XRegister>(); + __ Loadd(method_handle_kind, + method_handle, mirror::MethodHandle::HandleKindOffset().Int32Value()); + __ Li(temp, mirror::MethodHandle::Kind::kInvokeStatic); + __ Beq(method_handle_kind, temp, &execute_target_method); + + if (invoke->AsInvokePolymorphic()->CanTargetInstanceMethod()) { + XRegister receiver = locations->InAt(1).AsRegister<XRegister>(); + + // Receiver shouldn't be null for all the following cases. + __ Beqz(receiver, slow_path->GetEntryLabel()); + + __ Li(temp, mirror::MethodHandle::Kind::kInvokeDirect); + // No dispatch is needed for invoke-direct. + __ Beq(method_handle_kind, temp, &execute_target_method); + + Riscv64Label non_virtual_dispatch; + __ Li(temp, mirror::MethodHandle::Kind::kInvokeVirtual); + __ Bne(method_handle_kind, temp, &non_virtual_dispatch); + + // Skip virtual dispatch if `method` is private. + __ Loadd(temp, method, ArtMethod::AccessFlagsOffset().Int32Value()); + __ Andi(temp, temp, kAccPrivate); + __ Bnez(temp, &execute_target_method); + + XRegister receiver_class = locations->GetTemp(2).AsRegister<XRegister>(); + // If method is defined in the receiver's class, execute it as it is. + __ Loadd(temp, method, ArtMethod::DeclaringClassOffset().Int32Value()); + __ Loadd(receiver_class, receiver, mirror::Object::ClassOffset().Int32Value()); + codegen_->MaybeUnpoisonHeapReference(receiver_class); + + // We're not emitting the read barrier for the receiver_class, so false negatives just go + // through the virtual dispath below. + __ Beq(temp, receiver_class, &execute_target_method); + + // MethodIndex is uint16_t. + __ Loadhu(temp, method, ArtMethod::MethodIndexOffset().Int32Value()); + + constexpr uint32_t vtable_offset = + mirror::Class::EmbeddedVTableOffset(art::PointerSize::k64).Int32Value(); + __ Sh3Add(temp, temp, receiver_class); + __ Loadd(method, temp, vtable_offset); + __ J(&execute_target_method); + __ Bind(&non_virtual_dispatch); + } + + // Checks above are jumping to `execute_target_method` is they succeed. If none match, try to + // handle in the slow path. + __ J(slow_path->GetEntryLabel()); + + __ Bind(&execute_target_method); Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kRiscv64PointerSize); __ Loadd(RA, method, entry_point.SizeValue()); __ Jalr(RA); diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc index c4b68e41c9..efe6253f96 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -785,8 +785,10 @@ class LSEVisitor final : private HGraphDelegateVisitor { // Treat it as a normal load if it is a removable singleton. } - const FieldInfo& field = instruction->GetFieldInfo(); - VisitGetLocation(instruction, heap_location_collector_.GetFieldHeapLocation(object, &field)); + const FieldInfo& field_info = instruction->GetFieldInfo(); + size_t idx = heap_location_collector_.GetFieldHeapLocation(object, &field_info); + RecordFieldInfo(&field_info, idx); + VisitGetLocation(instruction, idx); } void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override { @@ -801,9 +803,10 @@ class LSEVisitor final : private HGraphDelegateVisitor { // Treat it as a normal store if it is a removable singleton. } - const FieldInfo& field = instruction->GetFieldInfo(); + const FieldInfo& field_info = instruction->GetFieldInfo(); HInstruction* value = instruction->InputAt(1); - size_t idx = heap_location_collector_.GetFieldHeapLocation(object, &field); + size_t idx = heap_location_collector_.GetFieldHeapLocation(object, &field_info); + RecordFieldInfo(&field_info, idx); VisitSetLocation(instruction, idx, value); } @@ -813,9 +816,11 @@ class LSEVisitor final : private HGraphDelegateVisitor { return; } - const FieldInfo& field = instruction->GetFieldInfo(); + const FieldInfo& field_info = instruction->GetFieldInfo(); HInstruction* cls = instruction->InputAt(0); - VisitGetLocation(instruction, heap_location_collector_.GetFieldHeapLocation(cls, &field)); + size_t idx = heap_location_collector_.GetFieldHeapLocation(cls, &field_info); + RecordFieldInfo(&field_info, idx); + VisitGetLocation(instruction, idx); } void VisitStaticFieldSet(HStaticFieldSet* instruction) override { @@ -824,10 +829,11 @@ class LSEVisitor final : private HGraphDelegateVisitor { return; } - const FieldInfo& field = instruction->GetFieldInfo(); + const FieldInfo& field_info = instruction->GetFieldInfo(); HInstruction* cls = instruction->InputAt(0); HInstruction* value = instruction->InputAt(1); - size_t idx = heap_location_collector_.GetFieldHeapLocation(cls, &field); + size_t idx = heap_location_collector_.GetFieldHeapLocation(cls, &field_info); + RecordFieldInfo(&field_info, idx); VisitSetLocation(instruction, idx, value); } @@ -1544,9 +1550,6 @@ void LSEVisitor::VisitGetLocation(HInstruction* instruction, size_t idx) { uint32_t block_id = instruction->GetBlock()->GetBlockId(); ScopedArenaVector<ValueRecord>& heap_values = heap_values_for_[block_id]; ValueRecord& record = heap_values[idx]; - if (instruction->IsFieldAccess()) { - RecordFieldInfo(&instruction->GetFieldInfo(), idx); - } DCHECK(record.value.IsUnknown() || record.value.Equals(ReplacementOrValue(record.value))); loads_and_stores_.push_back({ instruction, idx }); if ((record.value.IsDefault() || record.value.NeedsNonLoopPhi()) && @@ -1587,9 +1590,6 @@ void LSEVisitor::VisitGetLocation(HInstruction* instruction, size_t idx) { void LSEVisitor::VisitSetLocation(HInstruction* instruction, size_t idx, HInstruction* value) { DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound); DCHECK(!IsStore(value)) << value->DebugName(); - if (instruction->IsFieldAccess()) { - RecordFieldInfo(&instruction->GetFieldInfo(), idx); - } // value may already have a substitute. value = FindSubstitute(value); HBasicBlock* block = instruction->GetBlock(); diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index bcf27ae9fa..66bef7a8f1 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -2442,13 +2442,7 @@ class HInstruction : public ArenaObject<kArenaAllocInstruction> { UNREACHABLE(); } - virtual bool IsFieldAccess() const { - return false; - } - virtual const FieldInfo& GetFieldInfo() const { - CHECK(IsFieldAccess()) << "Only callable on field accessors not " << DebugName() << " " - << *this; LOG(FATAL) << "Must be overridden by field accessors. Not implemented by " << *this; UNREACHABLE(); } @@ -6105,7 +6099,6 @@ class HInstanceFieldGet final : public HExpression<1> { return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue(); } - bool IsFieldAccess() const override { return true; } const FieldInfo& GetFieldInfo() const override { return field_info_; } MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } DataType::Type GetFieldType() const { return field_info_.GetFieldType(); } @@ -6179,7 +6172,6 @@ class HInstanceFieldSet final : public HExpression<2> { return (obj == InputAt(0)) && art::CanDoImplicitNullCheckOn(GetFieldOffset().Uint32Value()); } - bool IsFieldAccess() const override { return true; } const FieldInfo& GetFieldInfo() const override { return field_info_; } MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } DataType::Type GetFieldType() const { return field_info_.GetFieldType(); } @@ -7252,7 +7244,6 @@ class HStaticFieldGet final : public HExpression<1> { return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue(); } - bool IsFieldAccess() const override { return true; } const FieldInfo& GetFieldInfo() const override { return field_info_; } MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } DataType::Type GetFieldType() const { return field_info_.GetFieldType(); } @@ -7306,7 +7297,6 @@ class HStaticFieldSet final : public HExpression<2> { } bool IsClonable() const override { return true; } - bool IsFieldAccess() const override { return true; } const FieldInfo& GetFieldInfo() const override { return field_info_; } MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } DataType::Type GetFieldType() const { return field_info_.GetFieldType(); } |