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 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 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 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> 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> 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> 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