diff options
author | 2024-11-13 16:18:03 +0000 | |
---|---|---|
committer | 2024-11-27 15:40:50 +0000 | |
commit | b82da21e55c185dbe031dcfb260578dab576e4bc (patch) | |
tree | bfe0988b7f339fdd0bfede515206dd55bebba8cb /compiler/optimizing/intrinsics_x86_64.cc | |
parent | b16c991a56873f7baddec375ca63691f43a1afd6 (diff) |
x86-64: handle invoke-interface in invokeExact intrinsic.
Bug: 297147201
Test: ./art/test/testrunner/testrunner.py -b --host --64
Test: ./art/test/testrunner/testrunner.py -b --jvm
Change-Id: I2c07ae919921363e8e419ec7296cd24696e7f3b5
Diffstat (limited to 'compiler/optimizing/intrinsics_x86_64.cc')
-rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index b9d1a9f2c7..cf1bc93129 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -4236,6 +4236,8 @@ void IntrinsicLocationsBuilderX86_64::VisitMethodHandleInvokeExact(HInvoke* invo locations->SetInAt(number_of_args, Location::RequiresRegister()); locations->AddTemp(Location::RequiresRegister()); + // Hidden arg for invoke-interface. + locations->AddTemp(Location::RegisterLocation(RAX)); } void IntrinsicCodeGeneratorX86_64::VisitMethodHandleInvokeExact(HInvoke* invoke) { @@ -4273,14 +4275,15 @@ void IntrinsicCodeGeneratorX86_64::VisitMethodHandleInvokeExact(HInvoke* invoke) // No dispatch is needed for invoke-direct. __ j(kEqual, &execute_target_method); + Label non_virtual_dispatch; // Handle invoke-virtual case. __ cmpl(method_handle_kind, Immediate(mirror::MethodHandle::Kind::kInvokeVirtual)); - __ j(kNotEqual, &static_dispatch); + __ j(kNotEqual, &non_virtual_dispatch); + // Skip virtual dispatch if `method` is private. __ testl(Address(method, ArtMethod::AccessFlagsOffset()), Immediate(kAccPrivate)); __ j(kNotZero, &execute_target_method); - Label do_virtual_dispatch; CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>(); __ movl(temp, Address(method, ArtMethod::DeclaringClassOffset())); @@ -4288,7 +4291,6 @@ void IntrinsicCodeGeneratorX86_64::VisitMethodHandleInvokeExact(HInvoke* invoke) // If method is defined in the receiver's class, execute it as it is. __ j(kEqual, &execute_target_method); - __ Bind(&do_virtual_dispatch); // MethodIndex is uint16_t. __ movzxw(temp, Address(method, ArtMethod::MethodIndexOffset())); @@ -4300,6 +4302,48 @@ void IntrinsicCodeGeneratorX86_64::VisitMethodHandleInvokeExact(HInvoke* invoke) mirror::Class::EmbeddedVTableOffset(art::PointerSize::k64).Int32Value(); __ movq(method, Address(method, temp, TIMES_8, vtable_offset)); __ Jump(&execute_target_method); + + __ Bind(&non_virtual_dispatch); + __ cmpl(method_handle_kind, Immediate(mirror::MethodHandle::Kind::kInvokeInterface)); + __ j(kNotEqual, &static_dispatch); + + __ movl(temp, Address(method, ArtMethod::AccessFlagsOffset())); + + __ testl(temp, Immediate(kAccPrivate)); + __ j(kNotZero, &execute_target_method); + + CpuRegister hidden_arg = locations->GetTemp(1).AsRegister<CpuRegister>(); + // Set the hidden argument. + DCHECK_EQ(RAX, hidden_arg.AsRegister()); + __ movq(hidden_arg, method); + + Label get_imt_index_from_method_index; + Label do_imt_dispatch; + + // Get IMT index. + // Not doing default conflict check as IMT index is set for all method which have + // kAccAbstract bit. + __ testl(temp, Immediate(kAccAbstract)); + __ j(kZero, &get_imt_index_from_method_index); + + // imt_index_ is uint16_t + __ movzxw(temp, Address(method, ArtMethod::ImtIndexOffset())); + __ Jump(&do_imt_dispatch); + + // Default method, do method->GetMethodIndex() & (ImTable::kSizeTruncToPowerOfTwo - 1); + __ Bind(&get_imt_index_from_method_index); + __ movl(temp, Address(method, ArtMethod::MethodIndexOffset())); + __ andl(temp, Immediate(ImTable::kSizeTruncToPowerOfTwo - 1)); + + __ Bind(&do_imt_dispatch); + // Re-using `method` to store receiver class and ImTableEntry. + __ movl(method, Address(receiver, mirror::Object::ClassOffset())); + + __ movq(method, Address(method, mirror::Class::ImtPtrOffset(kX86_64PointerSize).Uint32Value())); + // method = receiver->GetClass()->embedded_imtable_->Get(method_offset); + __ movq(method, Address(method, temp, TIMES_8, /* disp= */ 0)); + + __ Jump(&execute_target_method); } __ Bind(&static_dispatch); __ cmpl(method_handle_kind, Immediate(mirror::MethodHandle::Kind::kInvokeStatic)); |