diff options
-rw-r--r-- | runtime/class_linker.cc | 83 | ||||
-rw-r--r-- | test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom.class | bin | 7055 -> 8737 bytes | |||
-rw-r--r-- | test/952-invoke-custom-kinds/classes/invokecustom/Super.class | bin | 468 -> 468 bytes | |||
-rw-r--r-- | test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator.class | bin | 8641 -> 8699 bytes | |||
-rw-r--r-- | test/952-invoke-custom-kinds/expected.txt | 3 |
5 files changed, 54 insertions, 32 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index a19085f5b5..ca89cee377 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -8376,6 +8376,7 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandle(uint32_t method_handle_id const DexFile* const dex_file = referrer->GetDexFile(); const DexFile::MethodHandleItem& mh = dex_file->GetMethodHandle(method_handle_idx); + mirror::MethodHandle::Kind kind; ArtField* target_field = nullptr; ArtMethod* target_method = nullptr; @@ -8383,22 +8384,27 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandle(uint32_t method_handle_id static_cast<DexFile::MethodHandleType>(mh.method_handle_type_); switch (handle_type) { case DexFile::MethodHandleType::kStaticPut: { + kind = mirror::MethodHandle::Kind::kStaticPut; target_field = ResolveField(mh.field_or_method_idx_, referrer, true /* is_static */); break; } case DexFile::MethodHandleType::kStaticGet: { + kind = mirror::MethodHandle::Kind::kStaticGet; target_field = ResolveField(mh.field_or_method_idx_, referrer, true /* is_static */); break; } case DexFile::MethodHandleType::kInstancePut: { + kind = mirror::MethodHandle::Kind::kInstancePut; target_field = ResolveField(mh.field_or_method_idx_, referrer, false /* is_static */); break; } case DexFile::MethodHandleType::kInstanceGet: { + kind = mirror::MethodHandle::Kind::kInstanceGet; target_field = ResolveField(mh.field_or_method_idx_, referrer, false /* is_static */); break; } case DexFile::MethodHandleType::kInvokeStatic: { + kind = mirror::MethodHandle::Kind::kInvokeStatic; target_method = ResolveMethod<kNoICCECheckForCache>(self, mh.field_or_method_idx_, referrer, @@ -8406,6 +8412,7 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandle(uint32_t method_handle_id break; } case DexFile::MethodHandleType::kInvokeInstance: { + kind = mirror::MethodHandle::Kind::kInvokeVirtual; target_method = ResolveMethod<kNoICCECheckForCache>(self, mh.field_or_method_idx_, referrer, @@ -8417,13 +8424,47 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandle(uint32_t method_handle_id break; } case DexFile::MethodHandleType::kInvokeDirect: { - target_method = ResolveMethod<kNoICCECheckForCache>(self, - mh.field_or_method_idx_, - referrer, - InvokeType::kDirect); + StackHandleScope<2> hs(self); + // A constant method handle with type kInvokeDirect can refer to + // a method that is private or to a method in a super class. To + // disambiguate the two options, we resolve the method ignoring + // the invocation type to determine if the method is private. We + // then resolve again specifying the intended invocation type to + // force the appropriate checks. + target_method = ResolveMethodWithoutInvokeType(*dex_file, + mh.field_or_method_idx_, + hs.NewHandle(referrer->GetDexCache()), + hs.NewHandle(referrer->GetClassLoader())); + if (target_method == nullptr) { + break; + } + + if (target_method->IsPrivate()) { + kind = mirror::MethodHandle::Kind::kInvokeDirect; + target_method = ResolveMethod<kNoICCECheckForCache>(self, + mh.field_or_method_idx_, + referrer, + InvokeType::kDirect); + } else { + kind = mirror::MethodHandle::Kind::kInvokeSuper; + target_method = ResolveMethod<kNoICCECheckForCache>(self, + mh.field_or_method_idx_, + referrer, + InvokeType::kSuper); + if (target_method == nullptr) { + break; + } + // Find the method specified in the parent in referring class + // so invoke-super invokes the method in the parent of the + // referrer. + target_method = + referrer->GetDeclaringClass()->FindVirtualMethodForVirtual(target_method, + kRuntimePointerSize); + } break; } case DexFile::MethodHandleType::kInvokeInterface: { + kind = mirror::MethodHandle::Kind::kInvokeInterface; target_method = ResolveMethod<kNoICCECheckForCache>(self, mh.field_or_method_idx_, referrer, @@ -8452,43 +8493,37 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandle(uint32_t method_handle_id return nullptr; } - // Determine the kind and number of parameters after it's safe to - // follow the field or method pointer. - mirror::MethodHandle::Kind kind; + // Determine the number of parameters after it's safe to follow the + // field or method pointer. uint32_t num_params; switch (handle_type) { case DexFile::MethodHandleType::kStaticPut: { - kind = mirror::MethodHandle::Kind::kStaticPut; num_params = 1; break; } case DexFile::MethodHandleType::kStaticGet: { - kind = mirror::MethodHandle::Kind::kStaticGet; num_params = 0; break; } case DexFile::MethodHandleType::kInstancePut: { - kind = mirror::MethodHandle::Kind::kInstancePut; num_params = 2; break; } case DexFile::MethodHandleType::kInstanceGet: { - kind = mirror::MethodHandle::Kind::kInstanceGet; num_params = 1; break; } case DexFile::MethodHandleType::kInvokeStatic: { - kind = mirror::MethodHandle::Kind::kInvokeStatic; uint32_t shorty_length; target_method->GetShorty(&shorty_length); num_params = shorty_length - 1; // Remove 1 for the return value. break; } - case DexFile::MethodHandleType::kInvokeInstance: { - kind = mirror::MethodHandle::Kind::kInvokeVirtual; - uint32_t shorty_length; - target_method->GetShorty(&shorty_length); - num_params = shorty_length; // Add 1 for the receiver, remove 1 for the return value. + case DexFile::MethodHandleType::kInvokeInstance: + case DexFile::MethodHandleType::kInvokeDirect: + case DexFile::MethodHandleType::kInvokeInterface: { + // Add 1 for the receiver and remove 1 for the return value. + target_method->GetShorty(&num_params); break; } case DexFile::MethodHandleType::kInvokeConstructor: { @@ -8496,20 +8531,6 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandle(uint32_t method_handle_id num_params = 0; break; } - case DexFile::MethodHandleType::kInvokeDirect: { - kind = mirror::MethodHandle::Kind::kInvokeDirect; - uint32_t shorty_length; - target_method->GetShorty(&shorty_length); - num_params = shorty_length; // Add 1 for the receiver, remove 1 for the return value. - break; - } - case DexFile::MethodHandleType::kInvokeInterface: { - kind = mirror::MethodHandle::Kind::kInvokeInterface; - uint32_t shorty_length; - target_method->GetShorty(&shorty_length); - num_params = shorty_length; // Add 1 for the receiver, remove 1 for the return value. - break; - } } StackHandleScope<5> hs(self); diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom.class b/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom.class Binary files differindex 4f0f497c72..a37a49bffa 100644 --- a/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom.class +++ b/test/952-invoke-custom-kinds/classes/invokecustom/InvokeCustom.class diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/Super.class b/test/952-invoke-custom-kinds/classes/invokecustom/Super.class Binary files differindex 5990f28d47..7906f99d2d 100644 --- a/test/952-invoke-custom-kinds/classes/invokecustom/Super.class +++ b/test/952-invoke-custom-kinds/classes/invokecustom/Super.class diff --git a/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator.class b/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator.class Binary files differindex 711db2343b..aa7e5216a4 100644 --- a/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator.class +++ b/test/952-invoke-custom-kinds/classes/invokecustom/TestGenerator.class diff --git a/test/952-invoke-custom-kinds/expected.txt b/test/952-invoke-custom-kinds/expected.txt index c72da25c99..55e1d0bd2f 100644 --- a/test/952-invoke-custom-kinds/expected.txt +++ b/test/952-invoke-custom-kinds/expected.txt @@ -12,7 +12,7 @@ c String bsmLookupStaticWithExtraArgs [1, 123456789, 123.456, 123456.789123] targetMethodTest3 from InvokeCustom -bsmCreateCallSite [MethodHandle(Super)void] +bsmCreateCallSite [MethodHandle(InvokeCustom)void] targetMethodTest4 from Super bsmLookupStatic [] targetMethodTest5 1000 + -923 = 77 @@ -35,4 +35,5 @@ checkStaticFieldTest9: old 0 new 1985229328 expected 1985229328 OK checkFieldTest9: old 0.0 new 1.99E-19 expected 1.99E-19 OK helperMethodTest9 in class invokecustom.InvokeCustom run() for Test9 +InvokeCustom.privateMethodTest9() targetMethodTest9() |