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#include "method_type.h" 18 19#include "class-inl.h" 20#include "gc_root-inl.h" 21#include "method_handles.h" 22 23namespace art { 24namespace mirror { 25 26GcRoot<Class> MethodType::static_class_; 27 28MethodType* MethodType::Create(Thread* const self, 29 Handle<Class> return_type, 30 Handle<ObjectArray<Class>> parameter_types) { 31 StackHandleScope<1> hs(self); 32 Handle<MethodType> mt( 33 hs.NewHandle(ObjPtr<MethodType>::DownCast(StaticClass()->AllocObject(self)))); 34 35 // TODO: Do we ever create a MethodType during a transaction ? There doesn't 36 // seem like a good reason to do a polymorphic invoke that results in the 37 // resolution of a method type in an unstarted runtime. 38 mt->SetFieldObject<false>(FormOffset(), nullptr); 39 mt->SetFieldObject<false>(MethodDescriptorOffset(), nullptr); 40 mt->SetFieldObject<false>(RTypeOffset(), return_type.Get()); 41 mt->SetFieldObject<false>(PTypesOffset(), parameter_types.Get()); 42 mt->SetFieldObject<false>(WrapAltOffset(), nullptr); 43 44 return mt.Get(); 45} 46 47MethodType* MethodType::CloneWithoutLeadingParameter(Thread* const self, 48 ObjPtr<MethodType> method_type) { 49 StackHandleScope<3> hs(self); 50 Handle<Class> rtype = hs.NewHandle(method_type->GetRType()); 51 Handle<ObjectArray<Class>> src_ptypes = hs.NewHandle(method_type->GetPTypes()); 52 ObjPtr<Class> class_type = Class::GetJavaLangClass(); 53 ObjPtr<Class> class_array_type = 54 Runtime::Current()->GetClassLinker()->FindArrayClass(self, &class_type); 55 const int32_t dst_ptypes_count = src_ptypes->GetLength() - 1; 56 Handle<ObjectArray<Class>> dst_ptypes = hs.NewHandle( 57 ObjectArray<Class>::Alloc(self, class_array_type, dst_ptypes_count)); 58 for (int32_t i = 0; i < dst_ptypes_count; ++i) { 59 dst_ptypes->Set(i, src_ptypes->Get(i + 1)); 60 } 61 return Create(self, rtype, dst_ptypes); 62} 63 64size_t MethodType::NumberOfVRegs() REQUIRES_SHARED(Locks::mutator_lock_) { 65 ObjectArray<Class>* const p_types = GetPTypes(); 66 const int32_t p_types_length = p_types->GetLength(); 67 68 // Initialize |num_vregs| with number of parameters and only increment it for 69 // types requiring a second vreg. 70 size_t num_vregs = static_cast<size_t>(p_types_length); 71 for (int32_t i = 0; i < p_types_length; ++i) { 72 Class* klass = p_types->GetWithoutChecks(i); 73 if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) { 74 ++num_vregs; 75 } 76 } 77 return num_vregs; 78} 79 80bool MethodType::IsExactMatch(MethodType* target) REQUIRES_SHARED(Locks::mutator_lock_) { 81 ObjectArray<Class>* const p_types = GetPTypes(); 82 const int32_t params_length = p_types->GetLength(); 83 84 ObjectArray<Class>* const target_p_types = target->GetPTypes(); 85 if (params_length != target_p_types->GetLength()) { 86 return false; 87 } 88 for (int32_t i = 0; i < params_length; ++i) { 89 if (p_types->GetWithoutChecks(i) != target_p_types->GetWithoutChecks(i)) { 90 return false; 91 } 92 } 93 return GetRType() == target->GetRType(); 94} 95 96bool MethodType::IsConvertible(MethodType* target) REQUIRES_SHARED(Locks::mutator_lock_) { 97 ObjectArray<Class>* const p_types = GetPTypes(); 98 const int32_t params_length = p_types->GetLength(); 99 100 ObjectArray<Class>* const target_p_types = target->GetPTypes(); 101 if (params_length != target_p_types->GetLength()) { 102 return false; 103 } 104 105 // Perform return check before invoking method handle otherwise side 106 // effects from the invocation may be observable before 107 // WrongMethodTypeException is raised. 108 if (!IsReturnTypeConvertible(target->GetRType(), GetRType())) { 109 return false; 110 } 111 112 for (int32_t i = 0; i < params_length; ++i) { 113 if (!IsParameterTypeConvertible(p_types->GetWithoutChecks(i), 114 target_p_types->GetWithoutChecks(i))) { 115 return false; 116 } 117 } 118 return true; 119} 120 121std::string MethodType::PrettyDescriptor() REQUIRES_SHARED(Locks::mutator_lock_) { 122 std::ostringstream ss; 123 ss << "("; 124 125 ObjectArray<Class>* const p_types = GetPTypes(); 126 const int32_t params_length = p_types->GetLength(); 127 for (int32_t i = 0; i < params_length; ++i) { 128 ss << p_types->GetWithoutChecks(i)->PrettyDescriptor(); 129 if (i != (params_length - 1)) { 130 ss << ", "; 131 } 132 } 133 134 ss << ")"; 135 ss << GetRType()->PrettyDescriptor(); 136 137 return ss.str(); 138} 139 140void MethodType::SetClass(Class* klass) { 141 CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass; 142 CHECK(klass != nullptr); 143 static_class_ = GcRoot<Class>(klass); 144} 145 146void MethodType::ResetClass() { 147 CHECK(!static_class_.IsNull()); 148 static_class_ = GcRoot<Class>(nullptr); 149} 150 151void MethodType::VisitRoots(RootVisitor* visitor) { 152 static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass)); 153} 154 155} // namespace mirror 156} // namespace art 157