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