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 "object.h"
25 #include "method_type.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     kInstanceGet,
52     kInstancePut,
53     kStaticGet,
54     kStaticPut,
55     kLastValidKind = kStaticPut,
56     kFirstAccessorKind = kInstanceGet,
57     kLastAccessorKind = kStaticPut,
58     kLastInvokeKind = kInvokeCallSiteTransform
59   };
60 
GetHandleKind()61   Kind GetHandleKind() REQUIRES_SHARED(Locks::mutator_lock_) {
62     const int32_t handle_kind = GetField32(OFFSET_OF_OBJECT_MEMBER(MethodHandle, handle_kind_));
63     DCHECK(handle_kind >= 0 &&
64            handle_kind <= static_cast<int32_t>(Kind::kLastValidKind));
65     return static_cast<Kind>(handle_kind);
66   }
67 
68   ALWAYS_INLINE mirror::MethodType* GetMethodType() REQUIRES_SHARED(Locks::mutator_lock_);
69 
70   ALWAYS_INLINE mirror::MethodType* GetNominalType() REQUIRES_SHARED(Locks::mutator_lock_);
71 
GetTargetField()72   ArtField* GetTargetField() REQUIRES_SHARED(Locks::mutator_lock_) {
73     return reinterpret_cast<ArtField*>(
74         GetField64(OFFSET_OF_OBJECT_MEMBER(MethodHandle, art_field_or_method_)));
75   }
76 
GetTargetMethod()77   ArtMethod* GetTargetMethod() REQUIRES_SHARED(Locks::mutator_lock_) {
78     return reinterpret_cast<ArtMethod*>(
79         GetField64(OFFSET_OF_OBJECT_MEMBER(MethodHandle, art_field_or_method_)));
80   }
81 
82   ALWAYS_INLINE ObjPtr<mirror::Class> GetTargetClass() REQUIRES_SHARED(Locks::mutator_lock_);
83 
84   static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
85 
86  protected:
87   void Initialize(uintptr_t art_field_or_method, Kind kind, Handle<MethodType> method_type)
88       REQUIRES_SHARED(Locks::mutator_lock_);
89 
90  private:
91   HeapReference<mirror::MethodHandle> cached_spread_invoker_;
92   HeapReference<mirror::MethodType> nominal_type_;
93   HeapReference<mirror::MethodType> method_type_;
94   uint32_t handle_kind_;
95   uint64_t art_field_or_method_;
96 
97  private:
CachedSpreadInvokerOffset()98   static MemberOffset CachedSpreadInvokerOffset() {
99     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, cached_spread_invoker_));
100   }
NominalTypeOffset()101   static MemberOffset NominalTypeOffset() {
102     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, nominal_type_));
103   }
MethodTypeOffset()104   static MemberOffset MethodTypeOffset() {
105     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, method_type_));
106   }
ArtFieldOrMethodOffset()107   static MemberOffset ArtFieldOrMethodOffset() {
108     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, art_field_or_method_));
109   }
HandleKindOffset()110   static MemberOffset HandleKindOffset() {
111     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, handle_kind_));
112   }
113 
114   friend struct art::MethodHandleOffsets;  // for verifying offset information
115   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandle);
116 };
117 
118 // C++ mirror of java.lang.invoke.MethodHandleImpl
119 class MANAGED MethodHandleImpl : public MethodHandle {
120  public:
121   static mirror::MethodHandleImpl* Create(Thread* const self,
122                                           uintptr_t art_field_or_method,
123                                           MethodHandle::Kind kind,
124                                           Handle<MethodType> method_type)
125       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
126 
127   static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
128 
129   static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
130   static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
131   static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
132 
133  private:
InfoOffset()134   static MemberOffset InfoOffset() {
135     return MemberOffset(OFFSETOF_MEMBER(MethodHandleImpl, info_));
136   }
137 
138   HeapReference<mirror::Object> info_;  // Unused by the runtime.
139   static GcRoot<mirror::Class> static_class_;  // java.lang.invoke.MethodHandleImpl.class
140 
141   friend struct art::MethodHandleImplOffsets;  // for verifying offset information
142   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandleImpl);
143 };
144 
145 }  // namespace mirror
146 }  // namespace art
147 
148 #endif  // ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_
149