summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/intrinsics_riscv64.cc64
-rw-r--r--compiler/optimizing/load_store_elimination.cc28
-rw-r--r--compiler/optimizing/nodes.h10
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(); }