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/mips/calling_convention_mips.h"
     22 #include "jni/quick/x86/calling_convention_x86.h"
     23 #include "utils.h"
     24 
     25 namespace art {
     26 
     27 // Offset of Method within the frame
     28 FrameOffset CallingConvention::MethodStackOffset() {
     29   return displacement_;
     30 }
     31 
     32 // Managed runtime calling convention
     33 
     34 ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
     35     bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
     36   switch (instruction_set) {
     37     case kArm:
     38     case kThumb2:
     39       return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
     40     case kMips:
     41       return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
     42     case kX86:
     43       return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
     44     default:
     45       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
     46       return NULL;
     47   }
     48 }
     49 
     50 bool ManagedRuntimeCallingConvention::HasNext() {
     51   return itr_args_ < NumArgs();
     52 }
     53 
     54 void ManagedRuntimeCallingConvention::Next() {
     55   CHECK(HasNext());
     56   if (IsCurrentArgExplicit() &&  // don't query parameter type of implicit args
     57       IsParamALongOrDouble(itr_args_)) {
     58     itr_longs_and_doubles_++;
     59     itr_slots_++;
     60   }
     61   if (IsCurrentParamAReference()) {
     62     itr_refs_++;
     63   }
     64   itr_args_++;
     65   itr_slots_++;
     66 }
     67 
     68 bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
     69   // Static methods have no implicit arguments, others implicitly pass this
     70   return IsStatic() || (itr_args_ != 0);
     71 }
     72 
     73 bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
     74   return IsCurrentArgExplicit();  // any user parameter may be null
     75 }
     76 
     77 size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
     78   return ParamSize(itr_args_);
     79 }
     80 
     81 bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
     82   return IsParamAReference(itr_args_);
     83 }
     84 
     85 // JNI calling convention
     86 
     87 JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
     88                                                    const char* shorty,
     89                                                    InstructionSet instruction_set) {
     90   switch (instruction_set) {
     91     case kArm:
     92     case kThumb2:
     93       return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
     94     case kMips:
     95       return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
     96     case kX86:
     97       return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
     98     default:
     99       LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
    100       return NULL;
    101   }
    102 }
    103 
    104 size_t JniCallingConvention::ReferenceCount() const {
    105   return NumReferenceArgs() + (IsStatic() ? 1 : 0);
    106 }
    107 
    108 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
    109   size_t start_of_sirt = SirtLinkOffset().Int32Value() +  kPointerSize;
    110   size_t references_size = kPointerSize * ReferenceCount();  // size excluding header
    111   return FrameOffset(start_of_sirt + references_size);
    112 }
    113 
    114 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
    115   // Segment state is 4 bytes long
    116   return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
    117 }
    118 
    119 bool JniCallingConvention::HasNext() {
    120   if (itr_args_ <= kObjectOrClass) {
    121     return true;
    122   } else {
    123     unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    124     return arg_pos < NumArgs();
    125   }
    126 }
    127 
    128 void JniCallingConvention::Next() {
    129   CHECK(HasNext());
    130   if (itr_args_ > kObjectOrClass) {
    131     int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    132     if (IsParamALongOrDouble(arg_pos)) {
    133       itr_longs_and_doubles_++;
    134       itr_slots_++;
    135     }
    136   }
    137   if (IsCurrentParamAReference()) {
    138     itr_refs_++;
    139   }
    140   itr_args_++;
    141   itr_slots_++;
    142 }
    143 
    144 bool JniCallingConvention::IsCurrentParamAReference() {
    145   switch (itr_args_) {
    146     case kJniEnv:
    147       return false;  // JNIEnv*
    148     case kObjectOrClass:
    149       return true;   // jobject or jclass
    150     default: {
    151       int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    152       return IsParamAReference(arg_pos);
    153     }
    154   }
    155 }
    156 
    157 // Return position of SIRT entry holding reference at the current iterator
    158 // position
    159 FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
    160   CHECK(IsCurrentParamAReference());
    161   CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset());
    162   // Address of 1st SIRT entry
    163   int result = SirtLinkOffset().Int32Value() + kPointerSize;
    164   result += itr_refs_ * kPointerSize;
    165   CHECK_GT(result, SirtLinkOffset().Int32Value());
    166   return FrameOffset(result);
    167 }
    168 
    169 size_t JniCallingConvention::CurrentParamSize() {
    170   if (itr_args_ <= kObjectOrClass) {
    171     return kPointerSize;  // JNIEnv or jobject/jclass
    172   } else {
    173     int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
    174     return ParamSize(arg_pos);
    175   }
    176 }
    177 
    178 size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
    179   // The first argument is the JNIEnv*.
    180   // Static methods have an extra argument which is the jclass.
    181   return IsStatic() ? 2 : 1;
    182 }
    183 
    184 }  // namespace art
    185