Home | History | Annotate | Download | only in quick
      1 /*
      2  * Copyright (C) 2011 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 "calling_convention.h"
     18 
     19 #include "base/logging.h"
     20 #include "jni/quick/arm/calling_convention_arm.h"
     21 #include "jni/quick/arm64/calling_convention_arm64.h"
     22 #include "jni/quick/mips/calling_convention_mips.h"
     23 #include "jni/quick/x86/calling_convention_x86.h"
     24 #include "jni/quick/x86_64/calling_convention_x86_64.h"
     25 #include "utils.h"
     26 
     27 namespace art {
     28 
     29 // Managed runtime calling convention
     30 
     31 ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
     32     bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
     33   switch (instruction_set) {
     34     case kArm:
     35     case kThumb2:
     36       return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
     37     case kArm64:
     38       return new arm64::Arm64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
     39     case kMips:
     40       return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
     41     case kX86:
     42       return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
     43     case kX86_64:
     44       return new x86_64::X86_64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
     45     default:
     46       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
     47       return NULL;
     48   }
     49 }
     50 
     51 bool ManagedRuntimeCallingConvention::HasNext() {
     52   return itr_args_ < NumArgs();
     53 }
     54 
     55 void ManagedRuntimeCallingConvention::Next() {
     56   CHECK(HasNext());
     57   if (IsCurrentArgExplicit() &&  // don't query parameter type of implicit args
     58       IsParamALongOrDouble(itr_args_)) {
     59     itr_longs_and_doubles_++;
     60     itr_slots_++;
     61   }
     62   if (IsParamAFloatOrDouble(itr_args_)) {
     63     itr_float_and_doubles_++;
     64   }
     65   if (IsCurrentParamAReference()) {
     66     itr_refs_++;
     67   }
     68   itr_args_++;
     69   itr_slots_++;
     70 }
     71 
     72 bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
     73   // Static methods have no implicit arguments, others implicitly pass this
     74   return IsStatic() || (itr_args_ != 0);
     75 }
     76 
     77 bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
     78   return IsCurrentArgExplicit();  // any user parameter may be null
     79 }
     80 
     81 size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
     82   return ParamSize(itr_args_);
     83 }
     84 
     85 bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
     86   return IsParamAReference(itr_args_);
     87 }
     88 
     89 bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
     90   return IsParamAFloatOrDouble(itr_args_);
     91 }
     92 
     93 bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() {
     94   return IsParamADouble(itr_args_);
     95 }
     96 
     97 bool ManagedRuntimeCallingConvention::IsCurrentParamALong() {
     98   return IsParamALong(itr_args_);
     99 }
    100 
    101 // JNI calling convention
    102 
    103 JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
    104                                                    const char* shorty,
    105                                                    InstructionSet instruction_set) {
    106   switch (instruction_set) {
    107     case kArm:
    108     case kThumb2:
    109       return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
    110     case kArm64:
    111       return new arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty);
    112     case kMips:
    113       return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
    114     case kX86:
    115       return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
    116     case kX86_64:
    117       return new x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty);
    118     default:
    119       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
    120       return NULL;
    121   }
    122 }
    123 
    124 size_t JniCallingConvention::ReferenceCount() const {
    125   return NumReferenceArgs() + (IsStatic() ? 1 : 0);
    126 }
    127 
    128 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
    129   size_t references_size = handle_scope_pointer_size_ * ReferenceCount();  // size excluding header
    130   return FrameOffset(HandleerencesOffset().Int32Value() + references_size);
    131 }
    132 
    133 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
    134   // Segment state is 4 bytes long
    135   return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
    136 }
    137 
    138 bool JniCallingConvention::HasNext() {
    139   if (itr_args_ <= kObjectOrClass) {
    140     return true;
    141   } else {
    142     unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    143     return arg_pos < NumArgs();
    144   }
    145 }
    146 
    147 void JniCallingConvention::Next() {
    148   CHECK(HasNext());
    149   if (itr_args_ > kObjectOrClass) {
    150     int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    151     if (IsParamALongOrDouble(arg_pos)) {
    152       itr_longs_and_doubles_++;
    153       itr_slots_++;
    154     }
    155   }
    156   if (IsCurrentParamAFloatOrDouble()) {
    157     itr_float_and_doubles_++;
    158   }
    159   if (IsCurrentParamAReference()) {
    160     itr_refs_++;
    161   }
    162   itr_args_++;
    163   itr_slots_++;
    164 }
    165 
    166 bool JniCallingConvention::IsCurrentParamAReference() {
    167   switch (itr_args_) {
    168     case kJniEnv:
    169       return false;  // JNIEnv*
    170     case kObjectOrClass:
    171       return true;   // jobject or jclass
    172     default: {
    173       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    174       return IsParamAReference(arg_pos);
    175     }
    176   }
    177 }
    178 
    179 bool JniCallingConvention::IsCurrentParamJniEnv() {
    180   return (itr_args_ == kJniEnv);
    181 }
    182 
    183 bool JniCallingConvention::IsCurrentParamAFloatOrDouble() {
    184   switch (itr_args_) {
    185     case kJniEnv:
    186       return false;  // JNIEnv*
    187     case kObjectOrClass:
    188       return false;   // jobject or jclass
    189     default: {
    190       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    191       return IsParamAFloatOrDouble(arg_pos);
    192     }
    193   }
    194 }
    195 
    196 bool JniCallingConvention::IsCurrentParamADouble() {
    197   switch (itr_args_) {
    198     case kJniEnv:
    199       return false;  // JNIEnv*
    200     case kObjectOrClass:
    201       return false;   // jobject or jclass
    202     default: {
    203       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    204       return IsParamADouble(arg_pos);
    205     }
    206   }
    207 }
    208 
    209 bool JniCallingConvention::IsCurrentParamALong() {
    210   switch (itr_args_) {
    211     case kJniEnv:
    212       return false;  // JNIEnv*
    213     case kObjectOrClass:
    214       return false;   // jobject or jclass
    215     default: {
    216       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    217       return IsParamALong(arg_pos);
    218     }
    219   }
    220 }
    221 
    222 // Return position of handle scope entry holding reference at the current iterator
    223 // position
    224 FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() {
    225   CHECK(IsCurrentParamAReference());
    226   CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset());
    227   int result = HandleerencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
    228   CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value());
    229   return FrameOffset(result);
    230 }
    231 
    232 size_t JniCallingConvention::CurrentParamSize() {
    233   if (itr_args_ <= kObjectOrClass) {
    234     return frame_pointer_size_;  // JNIEnv or jobject/jclass
    235   } else {
    236     int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    237     return ParamSize(arg_pos);
    238   }
    239 }
    240 
    241 size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
    242   // The first argument is the JNIEnv*.
    243   // Static methods have an extra argument which is the jclass.
    244   return IsStatic() ? 2 : 1;
    245 }
    246 
    247 }  // namespace art
    248