diff options
| -rw-r--r-- | runtime/class_linker.cc | 26 | ||||
| -rw-r--r-- | test/979-const-method-handle/expected.txt | 8 | ||||
| -rw-r--r-- | test/979-const-method-handle/src/Main.java | 77 |
3 files changed, 101 insertions, 10 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 6f560ef96f..bcc3a22c86 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -8474,7 +8474,7 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForMethod( target_method->GetShorty(&shorty_length); int32_t num_params = static_cast<int32_t>(shorty_length + receiver_count - 1); - StackHandleScope<7> hs(self); + StackHandleScope<5> hs(self); ObjPtr<mirror::Class> array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>(this); Handle<mirror::ObjectArray<mirror::Class>> method_params(hs.NewHandle( mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, num_params))); @@ -8483,20 +8483,25 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForMethod( return nullptr; } + const DexFile* dex_file = referrer->GetDexFile(); + const DexFile::MethodId& method_id = dex_file->GetMethodId(method_handle.field_or_method_idx_); int32_t index = 0; if (receiver_count != 0) { - // Insert receiver - method_params->Set(index++, target_method->GetDeclaringClass()); + // Insert receiver. Use the class identified in the method handle rather than the declaring + // class of the resolved method which may be super class or default interface method + // (b/115964401). + ObjPtr<mirror::Class> receiver_class = LookupResolvedType(method_id.class_idx_, referrer); + // receiver_class should have been resolved when resolving the target method. + DCHECK(receiver_class != nullptr); + method_params->Set(index++, receiver_class); } - DexFileParameterIterator it(*target_method->GetDexFile(), target_method->GetPrototype()); - Handle<mirror::DexCache> target_method_dex_cache(hs.NewHandle(target_method->GetDexCache())); - Handle<mirror::ClassLoader> target_method_class_loader(hs.NewHandle(target_method->GetClassLoader())); + + const DexFile::ProtoId& proto_id = dex_file->GetProtoId(method_id.proto_idx_); + DexFileParameterIterator it(*dex_file, proto_id); while (it.HasNext()) { DCHECK_LT(index, num_params); const dex::TypeIndex type_idx = it.GetTypeIdx(); - ObjPtr<mirror::Class> klass = ResolveType(type_idx, - target_method_dex_cache, - target_method_class_loader); + ObjPtr<mirror::Class> klass = ResolveType(type_idx, referrer); if (nullptr == klass) { DCHECK(self->IsExceptionPending()); return nullptr; @@ -8505,7 +8510,8 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForMethod( it.Next(); } - Handle<mirror::Class> return_type = hs.NewHandle(target_method->ResolveReturnType()); + Handle<mirror::Class> return_type = + hs.NewHandle(ResolveType(proto_id.return_type_idx_, referrer)); if (UNLIKELY(return_type.IsNull())) { DCHECK(self->IsExceptionPending()); return nullptr; diff --git a/test/979-const-method-handle/expected.txt b/test/979-const-method-handle/expected.txt index bbaaedb0af..85317092ff 100644 --- a/test/979-const-method-handle/expected.txt +++ b/test/979-const-method-handle/expected.txt @@ -7,3 +7,11 @@ name is HoverFly 2.718281828459045 repeatConstMethodHandle() Attempting to set Math.E raised IAE +Quack +Moo +Woof +Test +Getting field in TestTokenizer raised WMTE (woohoo!) +Stack: tos was 7 +Stack: capacity was 10 +Stack: capacity is 2 diff --git a/test/979-const-method-handle/src/Main.java b/test/979-const-method-handle/src/Main.java index 427ca7a306..5368a22b21 100644 --- a/test/979-const-method-handle/src/Main.java +++ b/test/979-const-method-handle/src/Main.java @@ -18,6 +18,11 @@ import annotations.ConstantMethodHandle; import annotations.ConstantMethodType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; +import java.lang.invoke.WrongMethodTypeException; + +import java.io.StreamTokenizer; +import java.io.StringReader; +import java.util.Stack; class Main { /** @@ -45,6 +50,12 @@ class Main { private int field; } + private static class TestTokenizer extends StreamTokenizer { + public TestTokenizer(String message) { + super(new StringReader(message)); + } + } + @ConstantMethodType( returnType = String.class, parameterTypes = {int.class, Integer.class, System.class}) @@ -136,6 +147,48 @@ class Main { return null; } + @ConstantMethodHandle( + kind = ConstantMethodHandle.INSTANCE_GET, + owner = "java/io/StreamTokenizer", + fieldOrMethodName = "sval", + descriptor = "Ljava/lang/String;") + private static MethodHandle getSval() { + unreachable(); + return null; + } + + // This constant-method-handle references a private instance field. If + // referenced in bytecode it raises IAE at load time. + @ConstantMethodHandle( + kind = ConstantMethodHandle.INSTANCE_PUT, + owner = "java/io/StreamTokenizer", + fieldOrMethodName = "peekc", + descriptor = "I") + private static MethodHandle putPeekc() { + unreachable(); + return null; + } + + @ConstantMethodHandle( + kind = ConstantMethodHandle.INVOKE_VIRTUAL, + owner = "java/util/Stack", + fieldOrMethodName = "pop", + descriptor = "()Ljava/lang/Object;") + private static MethodHandle stackPop() { + unreachable(); + return null; + } + + @ConstantMethodHandle( + kind = ConstantMethodHandle.INVOKE_VIRTUAL, + owner = "java/util/Stack", + fieldOrMethodName = "trimToSize", + descriptor = "()V") + private static MethodHandle stackTrim() { + unreachable(); + return null; + } + private static void repeatConstMethodHandle() throws Throwable { System.out.println("repeatConstMethodHandle()"); String[] values = {"A", "B", "C"}; @@ -166,5 +219,29 @@ class Main { } catch (IllegalAccessError expected) { System.out.println("Attempting to set Math.E raised IAE"); } + + StreamTokenizer st = new StreamTokenizer(new StringReader("Quack Moo Woof")); + while (st.nextToken() != StreamTokenizer.TT_EOF) { + System.out.println((String) getSval().invokeExact(st)); + } + + TestTokenizer tt = new TestTokenizer("Test message 123"); + tt.nextToken(); + System.out.println((String) getSval().invoke(tt)); + try { + System.out.println((String) getSval().invokeExact(tt)); + } catch (WrongMethodTypeException wmte) { + System.out.println("Getting field in TestTokenizer raised WMTE (woohoo!)"); + } + + Stack stack = new Stack(); + stack.push(Integer.valueOf(3)); + stack.push(Integer.valueOf(5)); + stack.push(Integer.valueOf(7)); + Object tos = stackPop().invokeExact(stack); + System.out.println("Stack: tos was " + tos); + System.out.println("Stack: capacity was " + stack.capacity()); + stackTrim().invokeExact(stack); + System.out.println("Stack: capacity is " + stack.capacity()); } } |