blob: cef8c5d03dd3ce8eeecb2befc63df8c15ff25ac3 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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"
Alex Light50fa9932015-08-10 15:30:07 -070020
21#ifdef ART_ENABLE_CODEGEN_arm
Brian Carlstrom7940e442013-07-12 13:46:57 -070022#include "jni/quick/arm/calling_convention_arm.h"
Alex Light50fa9932015-08-10 15:30:07 -070023#endif
24
25#ifdef ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +000026#include "jni/quick/arm64/calling_convention_arm64.h"
Alex Light50fa9932015-08-10 15:30:07 -070027#endif
28
29#ifdef ART_ENABLE_CODEGEN_mips
Brian Carlstrom7940e442013-07-12 13:46:57 -070030#include "jni/quick/mips/calling_convention_mips.h"
Alex Light50fa9932015-08-10 15:30:07 -070031#endif
32
33#ifdef ART_ENABLE_CODEGEN_mips64
Maja Gagic6ea651f2015-02-24 16:55:04 +010034#include "jni/quick/mips64/calling_convention_mips64.h"
Alex Light50fa9932015-08-10 15:30:07 -070035#endif
36
37#ifdef ART_ENABLE_CODEGEN_x86
Brian Carlstrom7940e442013-07-12 13:46:57 -070038#include "jni/quick/x86/calling_convention_x86.h"
Alex Light50fa9932015-08-10 15:30:07 -070039#endif
40
41#ifdef ART_ENABLE_CODEGEN_x86_64
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070042#include "jni/quick/x86_64/calling_convention_x86_64.h"
Alex Light50fa9932015-08-10 15:30:07 -070043#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -070044
45namespace art {
46
Brian Carlstrom7940e442013-07-12 13:46:57 -070047// Managed runtime calling convention
48
49ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
50 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
51 switch (instruction_set) {
Alex Light50fa9932015-08-10 15:30:07 -070052#ifdef ART_ENABLE_CODEGEN_arm
Brian Carlstrom7940e442013-07-12 13:46:57 -070053 case kArm:
54 case kThumb2:
55 return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -070056#endif
57#ifdef ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +000058 case kArm64:
59 return new arm64::Arm64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -070060#endif
61#ifdef ART_ENABLE_CODEGEN_mips
Brian Carlstrom7940e442013-07-12 13:46:57 -070062 case kMips:
63 return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -070064#endif
65#ifdef ART_ENABLE_CODEGEN_mips64
Maja Gagic6ea651f2015-02-24 16:55:04 +010066 case kMips64:
67 return new mips64::Mips64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -070068#endif
69#ifdef ART_ENABLE_CODEGEN_x86
Brian Carlstrom7940e442013-07-12 13:46:57 -070070 case kX86:
71 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -070072#endif
73#ifdef ART_ENABLE_CODEGEN_x86_64
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070074 case kX86_64:
75 return new x86_64::X86_64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -070076#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -070077 default:
78 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Mathieu Chartier2cebb242015-04-21 16:50:40 -070079 return nullptr;
Brian Carlstrom7940e442013-07-12 13:46:57 -070080 }
81}
82
83bool ManagedRuntimeCallingConvention::HasNext() {
84 return itr_args_ < NumArgs();
85}
86
87void ManagedRuntimeCallingConvention::Next() {
88 CHECK(HasNext());
89 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args
90 IsParamALongOrDouble(itr_args_)) {
91 itr_longs_and_doubles_++;
92 itr_slots_++;
93 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070094 if (IsParamAFloatOrDouble(itr_args_)) {
95 itr_float_and_doubles_++;
96 }
Brian Carlstrom7940e442013-07-12 13:46:57 -070097 if (IsCurrentParamAReference()) {
98 itr_refs_++;
99 }
100 itr_args_++;
101 itr_slots_++;
102}
103
104bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
105 // Static methods have no implicit arguments, others implicitly pass this
106 return IsStatic() || (itr_args_ != 0);
107}
108
109bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
110 return IsCurrentArgExplicit(); // any user parameter may be null
111}
112
113size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
114 return ParamSize(itr_args_);
115}
116
117bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
118 return IsParamAReference(itr_args_);
119}
120
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700121bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
122 return IsParamAFloatOrDouble(itr_args_);
123}
124
Serban Constantinescu75b91132014-04-09 18:39:10 +0100125bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() {
126 return IsParamADouble(itr_args_);
127}
128
129bool ManagedRuntimeCallingConvention::IsCurrentParamALong() {
130 return IsParamALong(itr_args_);
131}
132
Brian Carlstrom7940e442013-07-12 13:46:57 -0700133// JNI calling convention
134
135JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
136 const char* shorty,
137 InstructionSet instruction_set) {
138 switch (instruction_set) {
Alex Light50fa9932015-08-10 15:30:07 -0700139#ifdef ART_ENABLE_CODEGEN_arm
Brian Carlstrom7940e442013-07-12 13:46:57 -0700140 case kArm:
141 case kThumb2:
142 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -0700143#endif
144#ifdef ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +0000145 case kArm64:
146 return new arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -0700147#endif
148#ifdef ART_ENABLE_CODEGEN_mips
Brian Carlstrom7940e442013-07-12 13:46:57 -0700149 case kMips:
150 return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -0700151#endif
152#ifdef ART_ENABLE_CODEGEN_mips64
Maja Gagic6ea651f2015-02-24 16:55:04 +0100153 case kMips64:
154 return new mips64::Mips64JniCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -0700155#endif
156#ifdef ART_ENABLE_CODEGEN_x86
Brian Carlstrom7940e442013-07-12 13:46:57 -0700157 case kX86:
158 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -0700159#endif
160#ifdef ART_ENABLE_CODEGEN_x86_64
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700161 case kX86_64:
162 return new x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty);
Alex Light50fa9932015-08-10 15:30:07 -0700163#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700164 default:
165 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700166 return nullptr;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700167 }
168}
169
170size_t JniCallingConvention::ReferenceCount() const {
171 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
172}
173
174FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700175 size_t references_size = handle_scope_pointer_size_ * ReferenceCount(); // size excluding header
Mathieu Chartiere401d142015-04-22 13:56:20 -0700176 return FrameOffset(HandleReferencesOffset().Int32Value() + references_size);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700177}
178
179FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
180 // Segment state is 4 bytes long
181 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
182}
183
184bool JniCallingConvention::HasNext() {
185 if (itr_args_ <= kObjectOrClass) {
186 return true;
187 } else {
188 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
189 return arg_pos < NumArgs();
190 }
191}
192
193void JniCallingConvention::Next() {
194 CHECK(HasNext());
195 if (itr_args_ > kObjectOrClass) {
196 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
197 if (IsParamALongOrDouble(arg_pos)) {
198 itr_longs_and_doubles_++;
199 itr_slots_++;
200 }
201 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700202 if (IsCurrentParamAFloatOrDouble()) {
203 itr_float_and_doubles_++;
204 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700205 if (IsCurrentParamAReference()) {
206 itr_refs_++;
207 }
208 itr_args_++;
209 itr_slots_++;
210}
211
212bool JniCallingConvention::IsCurrentParamAReference() {
213 switch (itr_args_) {
214 case kJniEnv:
215 return false; // JNIEnv*
216 case kObjectOrClass:
217 return true; // jobject or jclass
218 default: {
219 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
220 return IsParamAReference(arg_pos);
221 }
222 }
223}
224
Serban Constantinescu75b91132014-04-09 18:39:10 +0100225bool JniCallingConvention::IsCurrentParamJniEnv() {
226 return (itr_args_ == kJniEnv);
227}
228
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700229bool JniCallingConvention::IsCurrentParamAFloatOrDouble() {
230 switch (itr_args_) {
231 case kJniEnv:
232 return false; // JNIEnv*
233 case kObjectOrClass:
234 return false; // jobject or jclass
235 default: {
236 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
237 return IsParamAFloatOrDouble(arg_pos);
238 }
239 }
240}
241
Serban Constantinescu75b91132014-04-09 18:39:10 +0100242bool JniCallingConvention::IsCurrentParamADouble() {
243 switch (itr_args_) {
244 case kJniEnv:
245 return false; // JNIEnv*
246 case kObjectOrClass:
247 return false; // jobject or jclass
248 default: {
249 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
250 return IsParamADouble(arg_pos);
251 }
252 }
253}
254
255bool JniCallingConvention::IsCurrentParamALong() {
256 switch (itr_args_) {
257 case kJniEnv:
258 return false; // JNIEnv*
259 case kObjectOrClass:
260 return false; // jobject or jclass
261 default: {
262 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
263 return IsParamALong(arg_pos);
264 }
265 }
266}
267
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700268// Return position of handle scope entry holding reference at the current iterator
Brian Carlstrom7940e442013-07-12 13:46:57 -0700269// position
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700270FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700271 CHECK(IsCurrentParamAReference());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700272 CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700273 int result = HandleReferencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700274 CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700275 return FrameOffset(result);
276}
277
278size_t JniCallingConvention::CurrentParamSize() {
279 if (itr_args_ <= kObjectOrClass) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700280 return frame_pointer_size_; // JNIEnv or jobject/jclass
Brian Carlstrom7940e442013-07-12 13:46:57 -0700281 } else {
282 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
283 return ParamSize(arg_pos);
284 }
285}
286
287size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
288 // The first argument is the JNIEnv*.
289 // Static methods have an extra argument which is the jclass.
290 return IsStatic() ? 2 : 1;
291}
292
293} // namespace art