1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_
18 #define ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_
19 
20 #include "art_field.h"
21 #include "art_method.h"
22 #include "class.h"
23 #include "gc_root.h"
24 #include "method_type.h"
25 #include "object.h"
26 
27 namespace art {
28 
29 struct MethodHandleOffsets;
30 struct MethodHandleImplOffsets;
31 
32 namespace mirror {
33 
34 // C++ mirror of java.lang.invoke.MethodHandle
35 class MANAGED MethodHandle : public Object {
36  public:
37   // Defines the behaviour of a given method handle. The behaviour
38   // of a handle of a given kind is identical to the dex bytecode behaviour
39   // of the equivalent instruction.
40   //
41   // NOTE: These must be kept in sync with the constants defined in
42   // java.lang.invoke.MethodHandle.
43   enum Kind {
44     kInvokeVirtual = 0,
45     kInvokeSuper,
46     kInvokeDirect,
47     kInvokeStatic,
48     kInvokeInterface,
49     kInvokeTransform,
50     kInvokeCallSiteTransform,
51     kInvokeVarHandle,
52     kInvokeVarHandleExact,
53     kInstanceGet,
54     kInstancePut,
55     kStaticGet,
56     kStaticPut,
57     kLastValidKind = kStaticPut,
58     kFirstAccessorKind = kInstanceGet,
59     kLastAccessorKind = kStaticPut,
60     kLastInvokeKind = kInvokeVarHandleExact
61   };
62 
GetHandleKind()63   Kind GetHandleKind() REQUIRES_SHARED(Locks::mutator_lock_) {
64     const int32_t handle_kind = GetField32(OFFSET_OF_OBJECT_MEMBER(MethodHandle, handle_kind_));
65     DCHECK(handle_kind >= 0 &&
66            handle_kind <= static_cast<int32_t>(Kind::kLastValidKind));
67     return static_cast<Kind>(handle_kind);
68   }
69 
70   ALWAYS_INLINE mirror::MethodType* GetMethodType() REQUIRES_SHARED(Locks::mutator_lock_);
71 
72   ALWAYS_INLINE mirror::MethodType* GetNominalType() REQUIRES_SHARED(Locks::mutator_lock_);
73 
GetTargetField()74   ArtField* GetTargetField() REQUIRES_SHARED(Locks::mutator_lock_) {
75     return reinterpret_cast<ArtField*>(
76         GetField64(OFFSET_OF_OBJECT_MEMBER(MethodHandle, art_field_or_method_)));
77   }
78 
GetTargetMethod()79   ArtMethod* GetTargetMethod() REQUIRES_SHARED(Locks::mutator_lock_) {
80     return reinterpret_cast<ArtMethod*>(
81         GetField64(OFFSET_OF_OBJECT_MEMBER(MethodHandle, art_field_or_method_)));
82   }
83 
84   ALWAYS_INLINE ObjPtr<mirror::Class> GetTargetClass() REQUIRES_SHARED(Locks::mutator_lock_);
85 
86   // Gets the return type for a named invoke method, or nullptr if the invoke method is not
87   // supported.
88   static const char* GetReturnTypeDescriptor(const char* invoke_method_name);
89 
90   static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
91 
92  protected:
93   void Initialize(uintptr_t art_field_or_method, Kind kind, Handle<MethodType> method_type)
94       REQUIRES_SHARED(Locks::mutator_lock_);
95 
96  private:
97   HeapReference<mirror::MethodHandle> cached_spread_invoker_;
98   HeapReference<mirror::MethodType> nominal_type_;
99   HeapReference<mirror::MethodType> method_type_;
100   uint32_t handle_kind_;
101   uint64_t art_field_or_method_;
102 
103  private:
CachedSpreadInvokerOffset()104   static MemberOffset CachedSpreadInvokerOffset() {
105     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, cached_spread_invoker_));
106   }
NominalTypeOffset()107   static MemberOffset NominalTypeOffset() {
108     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, nominal_type_));
109   }
MethodTypeOffset()110   static MemberOffset MethodTypeOffset() {
111     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, method_type_));
112   }
ArtFieldOrMethodOffset()113   static MemberOffset ArtFieldOrMethodOffset() {
114     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, art_field_or_method_));
115   }
HandleKindOffset()116   static MemberOffset HandleKindOffset() {
117     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, handle_kind_));
118   }
119 
120   friend struct art::MethodHandleOffsets;  // for verifying offset information
121   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandle);
122 };
123 
124 // C++ mirror of java.lang.invoke.MethodHandleImpl
125 class MANAGED MethodHandleImpl : public MethodHandle {
126  public:
127   static mirror::MethodHandleImpl* Create(Thread* const self,
128                                           uintptr_t art_field_or_method,
129                                           MethodHandle::Kind kind,
130                                           Handle<MethodType> method_type)
131       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
132 
133   static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
134 
135   static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
136   static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
137   static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
138 
139  private:
InfoOffset()140   static MemberOffset InfoOffset() {
141     return MemberOffset(OFFSETOF_MEMBER(MethodHandleImpl, info_));
142   }
143 
144   HeapReference<mirror::Object> info_;  // Unused by the runtime.
145   static GcRoot<mirror::Class> static_class_;  // java.lang.invoke.MethodHandleImpl.class
146 
147   friend struct art::MethodHandleImplOffsets;  // for verifying offset information
148   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandleImpl);
149 };
150 
151 }  // namespace mirror
152 }  // namespace art
153 
154 #endif  // ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_
155