Home | History | Annotate | Download | only in mirror
      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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    146 void MethodType::ResetClass() {
    147   CHECK(!static_class_.IsNull());
    148   static_class_ = GcRoot<Class>(nullptr);
    149 }
    150 
    151 void MethodType::VisitRoots(RootVisitor* visitor) {
    152   static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
    153 }
    154 
    155 }  // namespace mirror
    156 }  // namespace art
    157