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 
     21 #ifdef ART_ENABLE_CODEGEN_arm
     22 #include "jni/quick/arm/calling_convention_arm.h"
     23 #endif
     24 
     25 #ifdef ART_ENABLE_CODEGEN_arm64
     26 #include "jni/quick/arm64/calling_convention_arm64.h"
     27 #endif
     28 
     29 #ifdef ART_ENABLE_CODEGEN_mips
     30 #include "jni/quick/mips/calling_convention_mips.h"
     31 #endif
     32 
     33 #ifdef ART_ENABLE_CODEGEN_mips64
     34 #include "jni/quick/mips64/calling_convention_mips64.h"
     35 #endif
     36 
     37 #ifdef ART_ENABLE_CODEGEN_x86
     38 #include "jni/quick/x86/calling_convention_x86.h"
     39 #endif
     40 
     41 #ifdef ART_ENABLE_CODEGEN_x86_64
     42 #include "jni/quick/x86_64/calling_convention_x86_64.h"
     43 #endif
     44 
     45 namespace art {
     46 
     47 // Managed runtime calling convention
     48 
     49 std::unique_ptr<ManagedRuntimeCallingConvention> ManagedRuntimeCallingConvention::Create(
     50     ArenaAllocator* arena,
     51     bool is_static,
     52     bool is_synchronized,
     53     const char* shorty,
     54     InstructionSet instruction_set) {
     55   switch (instruction_set) {
     56 #ifdef ART_ENABLE_CODEGEN_arm
     57     case kArm:
     58     case kThumb2:
     59       return std::unique_ptr<ManagedRuntimeCallingConvention>(
     60           new (arena) arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty));
     61 #endif
     62 #ifdef ART_ENABLE_CODEGEN_arm64
     63     case kArm64:
     64       return std::unique_ptr<ManagedRuntimeCallingConvention>(
     65           new (arena) arm64::Arm64ManagedRuntimeCallingConvention(
     66               is_static, is_synchronized, shorty));
     67 #endif
     68 #ifdef ART_ENABLE_CODEGEN_mips
     69     case kMips:
     70       return std::unique_ptr<ManagedRuntimeCallingConvention>(
     71           new (arena) mips::MipsManagedRuntimeCallingConvention(
     72               is_static, is_synchronized, shorty));
     73 #endif
     74 #ifdef ART_ENABLE_CODEGEN_mips64
     75     case kMips64:
     76       return std::unique_ptr<ManagedRuntimeCallingConvention>(
     77           new (arena) mips64::Mips64ManagedRuntimeCallingConvention(
     78               is_static, is_synchronized, shorty));
     79 #endif
     80 #ifdef ART_ENABLE_CODEGEN_x86
     81     case kX86:
     82       return std::unique_ptr<ManagedRuntimeCallingConvention>(
     83           new (arena) x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty));
     84 #endif
     85 #ifdef ART_ENABLE_CODEGEN_x86_64
     86     case kX86_64:
     87       return std::unique_ptr<ManagedRuntimeCallingConvention>(
     88           new (arena) x86_64::X86_64ManagedRuntimeCallingConvention(
     89               is_static, is_synchronized, shorty));
     90 #endif
     91     default:
     92       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
     93       UNREACHABLE();
     94   }
     95 }
     96 
     97 bool ManagedRuntimeCallingConvention::HasNext() {
     98   return itr_args_ < NumArgs();
     99 }
    100 
    101 void ManagedRuntimeCallingConvention::Next() {
    102   CHECK(HasNext());
    103   if (IsCurrentArgExplicit() &&  // don't query parameter type of implicit args
    104       IsParamALongOrDouble(itr_args_)) {
    105     itr_longs_and_doubles_++;
    106     itr_slots_++;
    107   }
    108   if (IsParamAFloatOrDouble(itr_args_)) {
    109     itr_float_and_doubles_++;
    110   }
    111   if (IsCurrentParamAReference()) {
    112     itr_refs_++;
    113   }
    114   itr_args_++;
    115   itr_slots_++;
    116 }
    117 
    118 bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
    119   // Static methods have no implicit arguments, others implicitly pass this
    120   return IsStatic() || (itr_args_ != 0);
    121 }
    122 
    123 bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
    124   return IsCurrentArgExplicit();  // any user parameter may be null
    125 }
    126 
    127 size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
    128   return ParamSize(itr_args_);
    129 }
    130 
    131 bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
    132   return IsParamAReference(itr_args_);
    133 }
    134 
    135 bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
    136   return IsParamAFloatOrDouble(itr_args_);
    137 }
    138 
    139 bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() {
    140   return IsParamADouble(itr_args_);
    141 }
    142 
    143 bool ManagedRuntimeCallingConvention::IsCurrentParamALong() {
    144   return IsParamALong(itr_args_);
    145 }
    146 
    147 // JNI calling convention
    148 
    149 std::unique_ptr<JniCallingConvention> JniCallingConvention::Create(ArenaAllocator* arena,
    150                                                                    bool is_static,
    151                                                                    bool is_synchronized,
    152                                                                    const char* shorty,
    153                                                                    InstructionSet instruction_set) {
    154   switch (instruction_set) {
    155 #ifdef ART_ENABLE_CODEGEN_arm
    156     case kArm:
    157     case kThumb2:
    158       return std::unique_ptr<JniCallingConvention>(
    159           new (arena) arm::ArmJniCallingConvention(is_static, is_synchronized, shorty));
    160 #endif
    161 #ifdef ART_ENABLE_CODEGEN_arm64
    162     case kArm64:
    163       return std::unique_ptr<JniCallingConvention>(
    164           new (arena) arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty));
    165 #endif
    166 #ifdef ART_ENABLE_CODEGEN_mips
    167     case kMips:
    168       return std::unique_ptr<JniCallingConvention>(
    169           new (arena) mips::MipsJniCallingConvention(is_static, is_synchronized, shorty));
    170 #endif
    171 #ifdef ART_ENABLE_CODEGEN_mips64
    172     case kMips64:
    173       return std::unique_ptr<JniCallingConvention>(
    174           new (arena) mips64::Mips64JniCallingConvention(is_static, is_synchronized, shorty));
    175 #endif
    176 #ifdef ART_ENABLE_CODEGEN_x86
    177     case kX86:
    178       return std::unique_ptr<JniCallingConvention>(
    179           new (arena) x86::X86JniCallingConvention(is_static, is_synchronized, shorty));
    180 #endif
    181 #ifdef ART_ENABLE_CODEGEN_x86_64
    182     case kX86_64:
    183       return std::unique_ptr<JniCallingConvention>(
    184           new (arena) x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty));
    185 #endif
    186     default:
    187       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
    188       UNREACHABLE();
    189   }
    190 }
    191 
    192 size_t JniCallingConvention::ReferenceCount() const {
    193   return NumReferenceArgs() + (IsStatic() ? 1 : 0);
    194 }
    195 
    196 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
    197   size_t references_size = handle_scope_pointer_size_ * ReferenceCount();  // size excluding header
    198   return FrameOffset(HandleReferencesOffset().Int32Value() + references_size);
    199 }
    200 
    201 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
    202   // Segment state is 4 bytes long
    203   return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
    204 }
    205 
    206 bool JniCallingConvention::HasNext() {
    207   if (itr_args_ <= kObjectOrClass) {
    208     return true;
    209   } else {
    210     unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    211     return arg_pos < NumArgs();
    212   }
    213 }
    214 
    215 void JniCallingConvention::Next() {
    216   CHECK(HasNext());
    217   if (itr_args_ > kObjectOrClass) {
    218     int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    219     if (IsParamALongOrDouble(arg_pos)) {
    220       itr_longs_and_doubles_++;
    221       itr_slots_++;
    222     }
    223   }
    224   if (IsCurrentParamAFloatOrDouble()) {
    225     itr_float_and_doubles_++;
    226   }
    227   if (IsCurrentParamAReference()) {
    228     itr_refs_++;
    229   }
    230   itr_args_++;
    231   itr_slots_++;
    232 }
    233 
    234 bool JniCallingConvention::IsCurrentParamAReference() {
    235   switch (itr_args_) {
    236     case kJniEnv:
    237       return false;  // JNIEnv*
    238     case kObjectOrClass:
    239       return true;   // jobject or jclass
    240     default: {
    241       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    242       return IsParamAReference(arg_pos);
    243     }
    244   }
    245 }
    246 
    247 bool JniCallingConvention::IsCurrentParamJniEnv() {
    248   return (itr_args_ == kJniEnv);
    249 }
    250 
    251 bool JniCallingConvention::IsCurrentParamAFloatOrDouble() {
    252   switch (itr_args_) {
    253     case kJniEnv:
    254       return false;  // JNIEnv*
    255     case kObjectOrClass:
    256       return false;   // jobject or jclass
    257     default: {
    258       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    259       return IsParamAFloatOrDouble(arg_pos);
    260     }
    261   }
    262 }
    263 
    264 bool JniCallingConvention::IsCurrentParamADouble() {
    265   switch (itr_args_) {
    266     case kJniEnv:
    267       return false;  // JNIEnv*
    268     case kObjectOrClass:
    269       return false;   // jobject or jclass
    270     default: {
    271       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    272       return IsParamADouble(arg_pos);
    273     }
    274   }
    275 }
    276 
    277 bool JniCallingConvention::IsCurrentParamALong() {
    278   switch (itr_args_) {
    279     case kJniEnv:
    280       return false;  // JNIEnv*
    281     case kObjectOrClass:
    282       return false;   // jobject or jclass
    283     default: {
    284       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    285       return IsParamALong(arg_pos);
    286     }
    287   }
    288 }
    289 
    290 // Return position of handle scope entry holding reference at the current iterator
    291 // position
    292 FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() {
    293   CHECK(IsCurrentParamAReference());
    294   CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset());
    295   int result = HandleReferencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
    296   CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value());
    297   return FrameOffset(result);
    298 }
    299 
    300 size_t JniCallingConvention::CurrentParamSize() {
    301   if (itr_args_ <= kObjectOrClass) {
    302     return frame_pointer_size_;  // JNIEnv or jobject/jclass
    303   } else {
    304     int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    305     return ParamSize(arg_pos);
    306   }
    307 }
    308 
    309 size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
    310   // The first argument is the JNIEnv*.
    311   // Static methods have an extra argument which is the jclass.
    312   return IsStatic() ? 2 : 1;
    313 }
    314 
    315 }  // namespace art
    316