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_METHOD_HANDLES_INL_H_
18 #define ART_RUNTIME_METHOD_HANDLES_INL_H_
19
20 #include "method_handles.h"
21
22 #include "common_throws.h"
23 #include "dex/dex_instruction.h"
24 #include "interpreter/interpreter_common.h"
25 #include "jvalue.h"
26 #include "mirror/class.h"
27 #include "mirror/method_type.h"
28 #include "mirror/object.h"
29 #include "reflection.h"
30 #include "stack.h"
31
32 namespace art {
33
ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,ObjPtr<mirror::Class> from_class,ObjPtr<mirror::Class> to_class,JValue * value)34 inline bool ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,
35 Handle<mirror::MethodType> callee_type,
36 ObjPtr<mirror::Class> from_class,
37 ObjPtr<mirror::Class> to_class,
38 JValue* value) REQUIRES_SHARED(Locks::mutator_lock_) {
39 if (from_class == to_class) {
40 return true;
41 }
42
43 // |value| may contain a bare heap pointer which is generally
44 // |unsafe. ConvertJValueCommon() saves |value|, |from_class|, and
45 // |to_class| to Handles where necessary to avoid issues if the heap
46 // changes.
47 if (ConvertJValueCommon(callsite_type, callee_type, from_class, to_class, value)) {
48 DCHECK(!Thread::Current()->IsExceptionPending());
49 return true;
50 } else {
51 DCHECK(Thread::Current()->IsExceptionPending());
52 value->SetJ(0);
53 return false;
54 }
55 }
56
ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,int index,JValue * value)57 inline bool ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,
58 Handle<mirror::MethodType> callee_type,
59 int index,
60 JValue* value) REQUIRES_SHARED(Locks::mutator_lock_) {
61 return ConvertArgumentValue(callsite_type,
62 callee_type,
63 callsite_type->GetPTypes()->GetWithoutChecks(index),
64 callee_type->GetPTypes()->GetWithoutChecks(index),
65 value);
66 }
67
ConvertReturnValue(Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,JValue * value)68 inline bool ConvertReturnValue(Handle<mirror::MethodType> callsite_type,
69 Handle<mirror::MethodType> callee_type,
70 JValue* value) REQUIRES_SHARED(Locks::mutator_lock_) {
71 ObjPtr<mirror::Class> from_class(callee_type->GetRType());
72 ObjPtr<mirror::Class> to_class(callsite_type->GetRType());
73 if (to_class->GetPrimitiveType() == Primitive::kPrimVoid || from_class == to_class) {
74 return true;
75 }
76
77 // |value| may contain a bare heap pointer which is generally
78 // unsafe. ConvertJValueCommon() saves |value|, |from_class|, and
79 // |to_class| to Handles where necessary to avoid issues if the heap
80 // changes.
81 if (ConvertJValueCommon(callsite_type, callee_type, from_class, to_class, value)) {
82 DCHECK(!Thread::Current()->IsExceptionPending());
83 return true;
84 } else {
85 DCHECK(Thread::Current()->IsExceptionPending());
86 value->SetJ(0);
87 return false;
88 }
89 }
90
91 template <typename G, typename S>
PerformConversions(Thread * self,Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,G * getter,S * setter,int32_t start_index,int32_t end_index)92 bool PerformConversions(Thread* self,
93 Handle<mirror::MethodType> callsite_type,
94 Handle<mirror::MethodType> callee_type,
95 G* getter,
96 S* setter,
97 int32_t start_index,
98 int32_t end_index) REQUIRES_SHARED(Locks::mutator_lock_) {
99 StackHandleScope<2> hs(self);
100 Handle<mirror::ObjectArray<mirror::Class>> from_types(hs.NewHandle(callsite_type->GetPTypes()));
101 Handle<mirror::ObjectArray<mirror::Class>> to_types(hs.NewHandle(callee_type->GetPTypes()));
102
103 for (int32_t i = start_index; i < end_index; ++i) {
104 ObjPtr<mirror::Class> from(from_types->GetWithoutChecks(i));
105 ObjPtr<mirror::Class> to(to_types->GetWithoutChecks(i - start_index));
106 const Primitive::Type from_type = from->GetPrimitiveType();
107 const Primitive::Type to_type = to->GetPrimitiveType();
108 if (from == to) {
109 // Easy case - the types are identical. Nothing left to do except to pass
110 // the arguments along verbatim.
111 if (Primitive::Is64BitType(from_type)) {
112 setter->SetLong(getter->GetLong());
113 } else if (from_type == Primitive::kPrimNot) {
114 setter->SetReference(getter->GetReference());
115 } else {
116 setter->Set(getter->Get());
117 }
118 } else {
119 JValue value;
120 if (Primitive::Is64BitType(from_type)) {
121 value.SetJ(getter->GetLong());
122 } else if (from_type == Primitive::kPrimNot) {
123 value.SetL(getter->GetReference());
124 } else {
125 value.SetI(getter->Get());
126 }
127 // Caveat emptor - ObjPtr's not guaranteed valid after this call.
128 if (!ConvertArgumentValue(callsite_type, callee_type, from, to, &value)) {
129 DCHECK(self->IsExceptionPending());
130 return false;
131 }
132 if (Primitive::Is64BitType(to_type)) {
133 setter->SetLong(value.GetJ());
134 } else if (to_type == Primitive::kPrimNot) {
135 setter->SetReference(value.GetL());
136 } else {
137 setter->Set(value.GetI());
138 }
139 }
140 }
141 return true;
142 }
143
144 template <typename G, typename S>
PerformConversions(Thread * self,Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,G * getter,S * setter,int32_t num_conversions)145 bool PerformConversions(Thread* self,
146 Handle<mirror::MethodType> callsite_type,
147 Handle<mirror::MethodType> callee_type,
148 G* getter,
149 S* setter,
150 int32_t num_conversions)
151 REQUIRES_SHARED(Locks::mutator_lock_) {
152 return PerformConversions(self, callsite_type, callee_type, getter, setter, 0, num_conversions);
153 }
154
155 template <typename G, typename S>
PerformConversions(Thread * self,Handle<mirror::MethodType> callsite_type,Handle<mirror::MethodType> callee_type,G * getter,S * setter)156 bool PerformConversions(Thread* self,
157 Handle<mirror::MethodType> callsite_type,
158 Handle<mirror::MethodType> callee_type,
159 G* getter,
160 S* setter)
161 REQUIRES_SHARED(Locks::mutator_lock_) {
162 int32_t num_conversions = callee_type->GetPTypes()->GetLength();
163 return PerformConversions(self, callsite_type, callee_type, getter, setter, 0, num_conversions);
164 }
165
166 } // namespace art
167
168 #endif // ART_RUNTIME_METHOD_HANDLES_INL_H_
169