blob: e21f554331519625a16161b0f52257f76c7ee5d2 [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
Vladimir Marko93205e32016-04-13 11:59:46 +010049std::unique_ptr<ManagedRuntimeCallingConvention> ManagedRuntimeCallingConvention::Create(
50 ArenaAllocator* arena,
51 bool is_static,
52 bool is_synchronized,
53 const char* shorty,
54 InstructionSet instruction_set) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070055 switch (instruction_set) {
Alex Light50fa9932015-08-10 15:30:07 -070056#ifdef ART_ENABLE_CODEGEN_arm
Brian Carlstrom7940e442013-07-12 13:46:57 -070057 case kArm:
58 case kThumb2:
Vladimir Marko93205e32016-04-13 11:59:46 +010059 return std::unique_ptr<ManagedRuntimeCallingConvention>(
60 new (arena) arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -070061#endif
62#ifdef ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +000063 case kArm64:
Vladimir Marko93205e32016-04-13 11:59:46 +010064 return std::unique_ptr<ManagedRuntimeCallingConvention>(
65 new (arena) arm64::Arm64ManagedRuntimeCallingConvention(
66 is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -070067#endif
68#ifdef ART_ENABLE_CODEGEN_mips
Brian Carlstrom7940e442013-07-12 13:46:57 -070069 case kMips:
Vladimir Marko93205e32016-04-13 11:59:46 +010070 return std::unique_ptr<ManagedRuntimeCallingConvention>(
71 new (arena) mips::MipsManagedRuntimeCallingConvention(
72 is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -070073#endif
74#ifdef ART_ENABLE_CODEGEN_mips64
Maja Gagic6ea651f2015-02-24 16:55:04 +010075 case kMips64:
Vladimir Marko93205e32016-04-13 11:59:46 +010076 return std::unique_ptr<ManagedRuntimeCallingConvention>(
77 new (arena) mips64::Mips64ManagedRuntimeCallingConvention(
78 is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -070079#endif
80#ifdef ART_ENABLE_CODEGEN_x86
Brian Carlstrom7940e442013-07-12 13:46:57 -070081 case kX86:
Vladimir Marko93205e32016-04-13 11:59:46 +010082 return std::unique_ptr<ManagedRuntimeCallingConvention>(
83 new (arena) x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -070084#endif
85#ifdef ART_ENABLE_CODEGEN_x86_64
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070086 case kX86_64:
Vladimir Marko93205e32016-04-13 11:59:46 +010087 return std::unique_ptr<ManagedRuntimeCallingConvention>(
88 new (arena) x86_64::X86_64ManagedRuntimeCallingConvention(
89 is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -070090#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -070091 default:
92 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Vladimir Marko93205e32016-04-13 11:59:46 +010093 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -070094 }
95}
96
97bool ManagedRuntimeCallingConvention::HasNext() {
98 return itr_args_ < NumArgs();
99}
100
101void 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 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700108 if (IsParamAFloatOrDouble(itr_args_)) {
109 itr_float_and_doubles_++;
110 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700111 if (IsCurrentParamAReference()) {
112 itr_refs_++;
113 }
114 itr_args_++;
115 itr_slots_++;
116}
117
118bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
119 // Static methods have no implicit arguments, others implicitly pass this
120 return IsStatic() || (itr_args_ != 0);
121}
122
123bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
124 return IsCurrentArgExplicit(); // any user parameter may be null
125}
126
127size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
128 return ParamSize(itr_args_);
129}
130
131bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
132 return IsParamAReference(itr_args_);
133}
134
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700135bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
136 return IsParamAFloatOrDouble(itr_args_);
137}
138
Serban Constantinescu75b91132014-04-09 18:39:10 +0100139bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() {
140 return IsParamADouble(itr_args_);
141}
142
143bool ManagedRuntimeCallingConvention::IsCurrentParamALong() {
144 return IsParamALong(itr_args_);
145}
146
Brian Carlstrom7940e442013-07-12 13:46:57 -0700147// JNI calling convention
148
Vladimir Marko93205e32016-04-13 11:59:46 +0100149std::unique_ptr<JniCallingConvention> JniCallingConvention::Create(ArenaAllocator* arena,
150 bool is_static,
151 bool is_synchronized,
152 const char* shorty,
153 InstructionSet instruction_set) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700154 switch (instruction_set) {
Alex Light50fa9932015-08-10 15:30:07 -0700155#ifdef ART_ENABLE_CODEGEN_arm
Brian Carlstrom7940e442013-07-12 13:46:57 -0700156 case kArm:
157 case kThumb2:
Vladimir Marko93205e32016-04-13 11:59:46 +0100158 return std::unique_ptr<JniCallingConvention>(
159 new (arena) arm::ArmJniCallingConvention(is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -0700160#endif
161#ifdef ART_ENABLE_CODEGEN_arm64
Stuart Monteithb95a5342014-03-12 13:32:32 +0000162 case kArm64:
Vladimir Marko93205e32016-04-13 11:59:46 +0100163 return std::unique_ptr<JniCallingConvention>(
164 new (arena) arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -0700165#endif
166#ifdef ART_ENABLE_CODEGEN_mips
Brian Carlstrom7940e442013-07-12 13:46:57 -0700167 case kMips:
Vladimir Marko93205e32016-04-13 11:59:46 +0100168 return std::unique_ptr<JniCallingConvention>(
169 new (arena) mips::MipsJniCallingConvention(is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -0700170#endif
171#ifdef ART_ENABLE_CODEGEN_mips64
Maja Gagic6ea651f2015-02-24 16:55:04 +0100172 case kMips64:
Vladimir Marko93205e32016-04-13 11:59:46 +0100173 return std::unique_ptr<JniCallingConvention>(
174 new (arena) mips64::Mips64JniCallingConvention(is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -0700175#endif
176#ifdef ART_ENABLE_CODEGEN_x86
Brian Carlstrom7940e442013-07-12 13:46:57 -0700177 case kX86:
Vladimir Marko93205e32016-04-13 11:59:46 +0100178 return std::unique_ptr<JniCallingConvention>(
179 new (arena) x86::X86JniCallingConvention(is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -0700180#endif
181#ifdef ART_ENABLE_CODEGEN_x86_64
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700182 case kX86_64:
Vladimir Marko93205e32016-04-13 11:59:46 +0100183 return std::unique_ptr<JniCallingConvention>(
184 new (arena) x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty));
Alex Light50fa9932015-08-10 15:30:07 -0700185#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700186 default:
187 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Vladimir Marko93205e32016-04-13 11:59:46 +0100188 UNREACHABLE();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700189 }
190}
191
192size_t JniCallingConvention::ReferenceCount() const {
193 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
194}
195
196FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700197 size_t references_size = handle_scope_pointer_size_ * ReferenceCount(); // size excluding header
Mathieu Chartiere401d142015-04-22 13:56:20 -0700198 return FrameOffset(HandleReferencesOffset().Int32Value() + references_size);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700199}
200
201FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
202 // Segment state is 4 bytes long
203 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
204}
205
206bool 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
215void 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 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700224 if (IsCurrentParamAFloatOrDouble()) {
225 itr_float_and_doubles_++;
226 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700227 if (IsCurrentParamAReference()) {
228 itr_refs_++;
229 }
230 itr_args_++;
231 itr_slots_++;
232}
233
234bool 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
Serban Constantinescu75b91132014-04-09 18:39:10 +0100247bool JniCallingConvention::IsCurrentParamJniEnv() {
248 return (itr_args_ == kJniEnv);
249}
250
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700251bool 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
Serban Constantinescu75b91132014-04-09 18:39:10 +0100264bool 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
277bool 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
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700290// Return position of handle scope entry holding reference at the current iterator
Brian Carlstrom7940e442013-07-12 13:46:57 -0700291// position
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700292FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700293 CHECK(IsCurrentParamAReference());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700294 CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700295 int result = HandleReferencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700296 CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700297 return FrameOffset(result);
298}
299
300size_t JniCallingConvention::CurrentParamSize() {
301 if (itr_args_ <= kObjectOrClass) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700302 return frame_pointer_size_; // JNIEnv or jobject/jclass
Brian Carlstrom7940e442013-07-12 13:46:57 -0700303 } else {
304 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
305 return ParamSize(arg_pos);
306 }
307}
308
309size_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