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 "method_type.h"
24 #include "obj_ptr.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 ObjPtr<mirror::MethodType> GetMethodType() REQUIRES_SHARED(Locks::mutator_lock_);
71 
72   ALWAYS_INLINE ObjPtr<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  protected:
91   void Initialize(uintptr_t art_field_or_method, Kind kind, Handle<MethodType> method_type)
92       REQUIRES_SHARED(Locks::mutator_lock_);
93 
94  private:
95   HeapReference<mirror::MethodHandle> cached_spread_invoker_;
96   HeapReference<mirror::MethodType> nominal_type_;
97   HeapReference<mirror::MethodType> method_type_;
98   uint32_t handle_kind_;
99   uint64_t art_field_or_method_;
100 
101  private:
CachedSpreadInvokerOffset()102   static MemberOffset CachedSpreadInvokerOffset() {
103     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, cached_spread_invoker_));
104   }
NominalTypeOffset()105   static MemberOffset NominalTypeOffset() {
106     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, nominal_type_));
107   }
MethodTypeOffset()108   static MemberOffset MethodTypeOffset() {
109     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, method_type_));
110   }
ArtFieldOrMethodOffset()111   static MemberOffset ArtFieldOrMethodOffset() {
112     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, art_field_or_method_));
113   }
HandleKindOffset()114   static MemberOffset HandleKindOffset() {
115     return MemberOffset(OFFSETOF_MEMBER(MethodHandle, handle_kind_));
116   }
117 
118   friend struct art::MethodHandleOffsets;  // for verifying offset information
119   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandle);
120 };
121 
122 // C++ mirror of java.lang.invoke.MethodHandleImpl
123 class MANAGED MethodHandleImpl : public MethodHandle {
124  public:
125   static ObjPtr<mirror::MethodHandleImpl> Create(Thread* const self,
126                                                  uintptr_t art_field_or_method,
127                                                  MethodHandle::Kind kind,
128                                                  Handle<MethodType> method_type)
129       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
130 
131  private:
InfoOffset()132   static MemberOffset InfoOffset() {
133     return MemberOffset(OFFSETOF_MEMBER(MethodHandleImpl, info_));
134   }
135 
136   HeapReference<mirror::Object> info_;  // Unused by the runtime.
137 
138   friend struct art::MethodHandleImplOffsets;  // for verifying offset information
139   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandleImpl);
140 };
141 
142 }  // namespace mirror
143 }  // namespace art
144 
145 #endif  // ART_RUNTIME_MIRROR_METHOD_HANDLE_IMPL_H_
146