blob: 41c8384e0d6a8248a797a41068e35f33abe1a772 [file] [log] [blame]
Narayan Kamath208f8572016-08-03 12:46:58 +01001/*
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"
David Sehr9e734c72018-01-04 17:56:19 -080023#include "dex/dex_instruction.h"
Narayan Kamath208f8572016-08-03 12:46:58 +010024#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
32namespace art {
33
Orion Hodsonba28f9f2016-10-26 10:56:25 +010034inline bool ConvertArgumentValue(Handle<mirror::MethodType> callsite_type,
35 Handle<mirror::MethodType> callee_type,
Orion Hodsonb8b93872018-01-30 07:51:10 +000036 ObjPtr<mirror::Class> from_class,
37 ObjPtr<mirror::Class> to_class,
Orion Hodsonba28f9f2016-10-26 10:56:25 +010038 JValue* value) REQUIRES_SHARED(Locks::mutator_lock_) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +010039 if (from_class == to_class) {
Narayan Kamath208f8572016-08-03 12:46:58 +010040 return true;
Orion Hodsonba28f9f2016-10-26 10:56:25 +010041 }
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());
Narayan Kamath208f8572016-08-03 12:46:58 +010049 return true;
50 } else {
Orion Hodsonba28f9f2016-10-26 10:56:25 +010051 DCHECK(Thread::Current()->IsExceptionPending());
52 value->SetJ(0);
Narayan Kamath208f8572016-08-03 12:46:58 +010053 return false;
54 }
55}
56
Orion Hodsonb8b93872018-01-30 07:51:10 +000057inline 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
Orion Hodsonba28f9f2016-10-26 10:56:25 +010068inline 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;
Narayan Kamathda246502016-10-20 18:39:22 +010075 }
76
Orion Hodsonba28f9f2016-10-26 10:56:25 +010077 // |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 }
Narayan Kamathda246502016-10-20 18:39:22 +010089}
90
Narayan Kamath000e1882016-10-24 17:14:25 +010091template <typename G, typename S>
92bool PerformConversions(Thread* self,
Orion Hodsonba28f9f2016-10-26 10:56:25 +010093 Handle<mirror::MethodType> callsite_type,
94 Handle<mirror::MethodType> callee_type,
Narayan Kamath000e1882016-10-24 17:14:25 +010095 G* getter,
96 S* setter,
Orion Hodsonb8b93872018-01-30 07:51:10 +000097 int32_t start_index,
98 int32_t end_index) REQUIRES_SHARED(Locks::mutator_lock_) {
Narayan Kamath000e1882016-10-24 17:14:25 +010099 StackHandleScope<2> hs(self);
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100100 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()));
Narayan Kamath000e1882016-10-24 17:14:25 +0100102
Orion Hodsonb8b93872018-01-30 07:51:10 +0000103 for (int32_t i = start_index; i < end_index; ++i) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100104 ObjPtr<mirror::Class> from(from_types->GetWithoutChecks(i));
Orion Hodsonb8b93872018-01-30 07:51:10 +0000105 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();
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100108 if (from == to) {
Narayan Kamath000e1882016-10-24 17:14:25 +0100109 // 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 }
Narayan Kamath000e1882016-10-24 17:14:25 +0100118 } else {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100119 JValue value;
Narayan Kamath000e1882016-10-24 17:14:25 +0100120 if (Primitive::Is64BitType(from_type)) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100121 value.SetJ(getter->GetLong());
Narayan Kamath000e1882016-10-24 17:14:25 +0100122 } else if (from_type == Primitive::kPrimNot) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100123 value.SetL(getter->GetReference());
Narayan Kamath000e1882016-10-24 17:14:25 +0100124 } else {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100125 value.SetI(getter->Get());
Narayan Kamath000e1882016-10-24 17:14:25 +0100126 }
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100127 // Caveat emptor - ObjPtr's not guaranteed valid after this call.
Orion Hodsonb8b93872018-01-30 07:51:10 +0000128 if (!ConvertArgumentValue(callsite_type, callee_type, from, to, &value)) {
Narayan Kamath000e1882016-10-24 17:14:25 +0100129 DCHECK(self->IsExceptionPending());
130 return false;
131 }
Narayan Kamath000e1882016-10-24 17:14:25 +0100132 if (Primitive::Is64BitType(to_type)) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100133 setter->SetLong(value.GetJ());
Narayan Kamath000e1882016-10-24 17:14:25 +0100134 } else if (to_type == Primitive::kPrimNot) {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100135 setter->SetReference(value.GetL());
Narayan Kamath000e1882016-10-24 17:14:25 +0100136 } else {
Orion Hodsonba28f9f2016-10-26 10:56:25 +0100137 setter->Set(value.GetI());
Narayan Kamath000e1882016-10-24 17:14:25 +0100138 }
139 }
140 }
Narayan Kamath000e1882016-10-24 17:14:25 +0100141 return true;
142}
143
Orion Hodsonb8b93872018-01-30 07:51:10 +0000144template <typename G, typename S>
145bool 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
155template <typename G, typename S>
156bool 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
Narayan Kamath208f8572016-08-03 12:46:58 +0100166} // namespace art
167
168#endif // ART_RUNTIME_METHOD_HANDLES_INL_H_