• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
MethodStackOffset()28 FrameOffset CallingConvention::MethodStackOffset() {
29   return displacement_;
30 }
31 
32 // Managed runtime calling convention
33 
Create(bool is_static,bool is_synchronized,const char * shorty,InstructionSet instruction_set)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 
HasNext()50 bool ManagedRuntimeCallingConvention::HasNext() {
51   return itr_args_ < NumArgs();
52 }
53 
Next()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 
IsCurrentArgExplicit()68 bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
69   // Static methods have no implicit arguments, others implicitly pass this
70   return IsStatic() || (itr_args_ != 0);
71 }
72 
IsCurrentArgPossiblyNull()73 bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
74   return IsCurrentArgExplicit();  // any user parameter may be null
75 }
76 
CurrentParamSize()77 size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
78   return ParamSize(itr_args_);
79 }
80 
IsCurrentParamAReference()81 bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
82   return IsParamAReference(itr_args_);
83 }
84 
85 // JNI calling convention
86 
Create(bool is_static,bool is_synchronized,const char * shorty,InstructionSet instruction_set)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 
ReferenceCount() const104 size_t JniCallingConvention::ReferenceCount() const {
105   return NumReferenceArgs() + (IsStatic() ? 1 : 0);
106 }
107 
SavedLocalReferenceCookieOffset() const108 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 
ReturnValueSaveLocation() const114 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
115   // Segment state is 4 bytes long
116   return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
117 }
118 
HasNext()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 
Next()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 
IsCurrentParamAReference()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
CurrentParamSirtEntryOffset()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 
CurrentParamSize()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 
NumberOfExtraArgumentsForJni()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