Home | History | Annotate | Download | only in runtime
      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