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
23 namespace art {
24 namespace mirror {
25
26 GcRoot<Class> MethodType::static_class_;
27
Create(Thread * const self,Handle<Class> return_type,Handle<ObjectArray<Class>> parameter_types)28 MethodType* 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
CloneWithoutLeadingParameter(Thread * const self,ObjPtr<MethodType> method_type)47 MethodType* 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
NumberOfVRegs()64 size_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
IsExactMatch(MethodType * target)80 bool 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
IsConvertible(MethodType * target)96 bool 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
PrettyDescriptor()121 std::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
SetClass(Class * klass)140 void 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
ResetClass()146 void MethodType::ResetClass() {
147 CHECK(!static_class_.IsNull());
148 static_class_ = GcRoot<Class>(nullptr);
149 }
150
VisitRoots(RootVisitor * visitor)151 void MethodType::VisitRoots(RootVisitor* visitor) {
152 static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
153 }
154
155 } // namespace mirror
156 } // namespace art
157