blob: 335a2dfa3c26c75cc54facbfb6d0c23a2bcad9a6 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Ian Rogersb033c752011-07-20 12:22:35 -070016
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_
18#define ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_
Ian Rogersb033c752011-07-20 12:22:35 -070019
Vladimir Marko93205e32016-04-13 11:59:46 +010020#include "base/arena_object.h"
David Brazdild9c90372016-09-14 16:53:55 +010021#include "base/array_ref.h"
Andreas Gampe542451c2016-07-26 09:02:02 -070022#include "base/enums.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070023#include "handle_scope.h"
Ian Rogerse63db272014-07-15 15:36:11 -070024#include "primitive.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070025#include "thread.h"
Ian Rogers166db042013-07-26 12:05:57 -070026#include "utils/managed_register.h"
Ian Rogersb033c752011-07-20 12:22:35 -070027
28namespace art {
29
Ian Rogers790a6b72014-04-01 10:36:00 -070030// Top-level abstraction for different calling conventions.
Vladimir Marko93205e32016-04-13 11:59:46 +010031class CallingConvention : public DeletableArenaObject<kArenaAllocCallingConvention> {
Ian Rogersb033c752011-07-20 12:22:35 -070032 public:
Ian Rogers169c9a72011-11-13 20:13:17 -080033 bool IsReturnAReference() const { return shorty_[0] == 'L'; }
Ian Rogersb033c752011-07-20 12:22:35 -070034
jeffhao58136ca2012-05-24 13:40:11 -070035 Primitive::Type GetReturnType() const {
36 return Primitive::GetType(shorty_[0]);
37 }
38
Ian Rogers169c9a72011-11-13 20:13:17 -080039 size_t SizeOfReturnValue() const {
40 size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[0]));
41 if (result >= 1 && result < 4) {
42 result = 4;
43 }
44 return result;
45 }
Ian Rogersdf20fe02011-07-20 20:34:16 -070046
Ian Rogers00f7d0e2012-07-19 15:28:27 -070047 // Register that holds result of this method invocation.
Ian Rogers2c8f6532011-09-02 17:16:34 -070048 virtual ManagedRegister ReturnRegister() = 0;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070049 // Register reserved for scratch usage during procedure calls.
Ian Rogers2c8f6532011-09-02 17:16:34 -070050 virtual ManagedRegister InterproceduralScratchRegister() = 0;
Shih-wei Liao668512a2011-09-01 14:18:34 -070051
Ian Rogers790a6b72014-04-01 10:36:00 -070052 // Offset of Method within the frame.
53 FrameOffset MethodStackOffset() {
54 return displacement_;
55 }
Carl Shapiroe2d373e2011-07-25 15:20:06 -070056
Ian Rogersb033c752011-07-20 12:22:35 -070057 // Iterator interface
58
59 // Place iterator at start of arguments. The displacement is applied to
60 // frame offset methods to account for frames which may be on the stack
61 // below the one being iterated over.
62 void ResetIterator(FrameOffset displacement) {
63 displacement_ = displacement;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070064 itr_slots_ = 0;
65 itr_args_ = 0;
Shih-wei Liao668512a2011-09-01 14:18:34 -070066 itr_refs_ = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070067 itr_longs_and_doubles_ = 0;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070068 itr_float_and_doubles_ = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070069 }
70
Ian Rogers2c8f6532011-09-02 17:16:34 -070071 virtual ~CallingConvention() {}
72
Ian Rogersb033c752011-07-20 12:22:35 -070073 protected:
Andreas Gampe542451c2016-07-26 09:02:02 -070074 CallingConvention(bool is_static,
75 bool is_synchronized,
76 const char* shorty,
77 PointerSize frame_pointer_size)
Ian Rogers790a6b72014-04-01 10:36:00 -070078 : itr_slots_(0), itr_refs_(0), itr_args_(0), itr_longs_and_doubles_(0),
79 itr_float_and_doubles_(0), displacement_(0),
80 frame_pointer_size_(frame_pointer_size),
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070081 handle_scope_pointer_size_(sizeof(StackReference<mirror::Object>)),
Ian Rogers790a6b72014-04-01 10:36:00 -070082 is_static_(is_static), is_synchronized_(is_synchronized),
Ian Rogers169c9a72011-11-13 20:13:17 -080083 shorty_(shorty) {
84 num_args_ = (is_static ? 0 : 1) + strlen(shorty) - 1;
85 num_ref_args_ = is_static ? 0 : 1; // The implicit this pointer.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070086 num_float_or_double_args_ = 0;
Ian Rogers169c9a72011-11-13 20:13:17 -080087 num_long_or_double_args_ = 0;
88 for (size_t i = 1; i < strlen(shorty); i++) {
89 char ch = shorty_[i];
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070090 switch (ch) {
91 case 'L':
Ian Rogers169c9a72011-11-13 20:13:17 -080092 num_ref_args_++;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070093 break;
94 case 'J':
Ian Rogers169c9a72011-11-13 20:13:17 -080095 num_long_or_double_args_++;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070096 break;
97 case 'D':
98 num_long_or_double_args_++;
99 num_float_or_double_args_++;
100 break;
101 case 'F':
102 num_float_or_double_args_++;
103 break;
Ian Rogers169c9a72011-11-13 20:13:17 -0800104 }
105 }
106 }
Ian Rogers2c8f6532011-09-02 17:16:34 -0700107
Ian Rogers169c9a72011-11-13 20:13:17 -0800108 bool IsStatic() const {
109 return is_static_;
110 }
111 bool IsSynchronized() const {
112 return is_synchronized_;
113 }
114 bool IsParamALongOrDouble(unsigned int param) const {
115 DCHECK_LT(param, NumArgs());
116 if (IsStatic()) {
117 param++; // 0th argument must skip return value at start of the shorty
118 } else if (param == 0) {
119 return false; // this argument
120 }
121 char ch = shorty_[param];
122 return (ch == 'J' || ch == 'D');
123 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700124 bool IsParamAFloatOrDouble(unsigned int param) const {
125 DCHECK_LT(param, NumArgs());
126 if (IsStatic()) {
127 param++; // 0th argument must skip return value at start of the shorty
128 } else if (param == 0) {
129 return false; // this argument
130 }
131 char ch = shorty_[param];
132 return (ch == 'F' || ch == 'D');
133 }
Serban Constantinescu75b91132014-04-09 18:39:10 +0100134 bool IsParamADouble(unsigned int param) const {
135 DCHECK_LT(param, NumArgs());
136 if (IsStatic()) {
137 param++; // 0th argument must skip return value at start of the shorty
138 } else if (param == 0) {
139 return false; // this argument
140 }
141 return shorty_[param] == 'D';
142 }
143 bool IsParamALong(unsigned int param) const {
144 DCHECK_LT(param, NumArgs());
145 if (IsStatic()) {
146 param++; // 0th argument must skip return value at start of the shorty
147 } else if (param == 0) {
Mark Mendell3e6a3bf2015-01-19 14:09:22 -0500148 return false; // this argument
Serban Constantinescu75b91132014-04-09 18:39:10 +0100149 }
150 return shorty_[param] == 'J';
151 }
Ian Rogers169c9a72011-11-13 20:13:17 -0800152 bool IsParamAReference(unsigned int param) const {
153 DCHECK_LT(param, NumArgs());
154 if (IsStatic()) {
155 param++; // 0th argument must skip return value at start of the shorty
156 } else if (param == 0) {
157 return true; // this argument
158 }
159 return shorty_[param] == 'L';
Ian Rogers169c9a72011-11-13 20:13:17 -0800160 }
161 size_t NumArgs() const {
162 return num_args_;
163 }
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700164 // Implicit argument count: 1 for instance functions, 0 for static functions.
165 // (The implicit argument is only relevant to the shorty, i.e.
166 // the 0th arg is not in the shorty if it's implicit).
167 size_t NumImplicitArgs() const {
168 return IsStatic() ? 0 : 1;
169 }
Ian Rogers169c9a72011-11-13 20:13:17 -0800170 size_t NumLongOrDoubleArgs() const {
171 return num_long_or_double_args_;
172 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700173 size_t NumFloatOrDoubleArgs() const {
174 return num_float_or_double_args_;
175 }
Ian Rogers169c9a72011-11-13 20:13:17 -0800176 size_t NumReferenceArgs() const {
177 return num_ref_args_;
178 }
179 size_t ParamSize(unsigned int param) const {
180 DCHECK_LT(param, NumArgs());
181 if (IsStatic()) {
182 param++; // 0th argument must skip return value at start of the shorty
183 } else if (param == 0) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700184 return sizeof(mirror::HeapReference<mirror::Object>); // this argument
Ian Rogers169c9a72011-11-13 20:13:17 -0800185 }
186 size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[param]));
187 if (result >= 1 && result < 4) {
188 result = 4;
189 }
190 return result;
191 }
192 const char* GetShorty() const {
193 return shorty_.c_str();
194 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700195 // The slot number for current calling_convention argument.
196 // Note that each slot is 32-bit. When the current argument is bigger
197 // than 32 bits, return the first slot number for this argument.
198 unsigned int itr_slots_;
Ian Rogers790a6b72014-04-01 10:36:00 -0700199 // The number of references iterated past.
Ian Rogers7a99c112011-09-07 12:48:27 -0700200 unsigned int itr_refs_;
Ian Rogers790a6b72014-04-01 10:36:00 -0700201 // The argument number along argument list for current argument.
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700202 unsigned int itr_args_;
Ian Rogers790a6b72014-04-01 10:36:00 -0700203 // Number of longs and doubles seen along argument list.
Ian Rogersb033c752011-07-20 12:22:35 -0700204 unsigned int itr_longs_and_doubles_;
Ian Rogers790a6b72014-04-01 10:36:00 -0700205 // Number of float and doubles seen along argument list.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700206 unsigned int itr_float_and_doubles_;
Ian Rogers790a6b72014-04-01 10:36:00 -0700207 // Space for frames below this on the stack.
Ian Rogersb033c752011-07-20 12:22:35 -0700208 FrameOffset displacement_;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700209 // The size of a pointer.
Andreas Gampe542451c2016-07-26 09:02:02 -0700210 const PointerSize frame_pointer_size_;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700211 // The size of a reference entry within the handle scope.
212 const size_t handle_scope_pointer_size_;
Ian Rogersb033c752011-07-20 12:22:35 -0700213
214 private:
Ian Rogers169c9a72011-11-13 20:13:17 -0800215 const bool is_static_;
216 const bool is_synchronized_;
217 std::string shorty_;
218 size_t num_args_;
219 size_t num_ref_args_;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700220 size_t num_float_or_double_args_;
Ian Rogers169c9a72011-11-13 20:13:17 -0800221 size_t num_long_or_double_args_;
Ian Rogersb033c752011-07-20 12:22:35 -0700222};
223
224// Abstraction for managed code's calling conventions
Ian Rogersbdb03912011-09-14 00:55:44 -0700225// | { Incoming stack args } |
226// | { Prior Method* } | <-- Prior SP
227// | { Return address } |
228// | { Callee saves } |
229// | { Spills ... } |
230// | { Outgoing stack args } |
231// | { Method* } | <-- SP
Ian Rogersb033c752011-07-20 12:22:35 -0700232class ManagedRuntimeCallingConvention : public CallingConvention {
233 public:
Vladimir Marko93205e32016-04-13 11:59:46 +0100234 static std::unique_ptr<ManagedRuntimeCallingConvention> Create(ArenaAllocator* arena,
235 bool is_static,
236 bool is_synchronized,
237 const char* shorty,
238 InstructionSet instruction_set);
Ian Rogersb033c752011-07-20 12:22:35 -0700239
Ian Rogers2c8f6532011-09-02 17:16:34 -0700240 // Register that holds the incoming method argument
241 virtual ManagedRegister MethodRegister() = 0;
242
Ian Rogersb033c752011-07-20 12:22:35 -0700243 // Iterator interface
244 bool HasNext();
245 void Next();
246 bool IsCurrentParamAReference();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700247 bool IsCurrentParamAFloatOrDouble();
Serban Constantinescu75b91132014-04-09 18:39:10 +0100248 bool IsCurrentParamADouble();
249 bool IsCurrentParamALong();
Ian Rogers7a99c112011-09-07 12:48:27 -0700250 bool IsCurrentArgExplicit(); // ie a non-implict argument such as this
251 bool IsCurrentArgPossiblyNull();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700252 size_t CurrentParamSize();
Ian Rogers2c8f6532011-09-02 17:16:34 -0700253 virtual bool IsCurrentParamInRegister() = 0;
254 virtual bool IsCurrentParamOnStack() = 0;
255 virtual ManagedRegister CurrentParamRegister() = 0;
256 virtual FrameOffset CurrentParamStackOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700257
Ian Rogers2c8f6532011-09-02 17:16:34 -0700258 virtual ~ManagedRuntimeCallingConvention() {}
259
Ian Rogersb5d09b22012-03-06 22:14:17 -0800260 // Registers to spill to caller's out registers on entry.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700261 virtual const ManagedRegisterEntrySpills& EntrySpills() = 0;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800262
Ian Rogers2c8f6532011-09-02 17:16:34 -0700263 protected:
Vladimir Marko93205e32016-04-13 11:59:46 +0100264 ManagedRuntimeCallingConvention(bool is_static,
265 bool is_synchronized,
266 const char* shorty,
Andreas Gampe542451c2016-07-26 09:02:02 -0700267 PointerSize frame_pointer_size)
Ian Rogers790a6b72014-04-01 10:36:00 -0700268 : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {}
Ian Rogersb033c752011-07-20 12:22:35 -0700269};
270
271// Abstraction for JNI calling conventions
Ian Rogersbdb03912011-09-14 00:55:44 -0700272// | { Incoming stack args } | <-- Prior SP
273// | { Return address } |
274// | { Callee saves } | ([1])
275// | { Return value spill } | (live on return slow paths)
Ian Rogersdc51b792011-09-22 20:41:37 -0700276// | { Local Ref. Table State } |
Ian Rogersbdb03912011-09-14 00:55:44 -0700277// | { Stack Indirect Ref. Table |
278// | num. refs./link } | (here to prior SP is frame size)
279// | { Method* } | <-- Anchor SP written to thread
280// | { Outgoing stack args } | <-- SP at point of call
281// | Native frame |
282//
283// [1] We must save all callee saves here to enable any exception throws to restore
284// callee saves for frames above this one.
Ian Rogersb033c752011-07-20 12:22:35 -0700285class JniCallingConvention : public CallingConvention {
286 public:
Vladimir Marko93205e32016-04-13 11:59:46 +0100287 static std::unique_ptr<JniCallingConvention> Create(ArenaAllocator* arena,
288 bool is_static,
289 bool is_synchronized,
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700290 bool is_critical_native,
Vladimir Marko93205e32016-04-13 11:59:46 +0100291 const char* shorty,
292 InstructionSet instruction_set);
Ian Rogersb033c752011-07-20 12:22:35 -0700293
294 // Size of frame excluding space for outgoing args (its assumed Method* is
295 // always at the bottom of a frame, but this doesn't work for outgoing
296 // native args). Includes alignment.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700297 virtual size_t FrameSize() = 0;
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700298 // Size of outgoing arguments (stack portion), including alignment.
299 // -- Arguments that are passed via registers are excluded from this size.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700300 virtual size_t OutArgSize() = 0;
Ian Rogers408f79a2011-08-23 18:22:33 -0700301 // Number of references in stack indirect reference table
Ian Rogersdc51b792011-09-22 20:41:37 -0700302 size_t ReferenceCount() const;
303 // Location where the segment state of the local indirect reference table is saved
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700304 FrameOffset SavedLocalReferenceCookieOffset() const;
Ian Rogersdf20fe02011-07-20 20:34:16 -0700305 // Location where the return value of a call can be squirreled if another
306 // call is made following the native call
Ian Rogersdc51b792011-09-22 20:41:37 -0700307 FrameOffset ReturnValueSaveLocation() const;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700308 // Register that holds result if it is integer.
309 virtual ManagedRegister IntReturnRegister() = 0;
Andreas Gamped1104322014-05-01 14:38:56 -0700310 // Whether the compiler needs to ensure zero-/sign-extension of a small result type
311 virtual bool RequiresSmallResultTypeExtension() const = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700312
Ian Rogersbdb03912011-09-14 00:55:44 -0700313 // Callee save registers to spill prior to native code (which may clobber)
Vladimir Marko32248382016-05-19 10:37:24 +0100314 virtual ArrayRef<const ManagedRegister> CalleeSaveRegisters() const = 0;
Ian Rogersbdb03912011-09-14 00:55:44 -0700315
316 // Spill mask values
317 virtual uint32_t CoreSpillMask() const = 0;
318 virtual uint32_t FpSpillMask() const = 0;
Ian Rogers0d666d82011-08-14 16:03:46 -0700319
Ian Rogersdc51b792011-09-22 20:41:37 -0700320 // An extra scratch register live after the call
321 virtual ManagedRegister ReturnScratchRegister() const = 0;
322
Ian Rogersb033c752011-07-20 12:22:35 -0700323 // Iterator interface
324 bool HasNext();
Ian Rogers67375ac2011-09-14 00:55:44 -0700325 virtual void Next();
Ian Rogersb033c752011-07-20 12:22:35 -0700326 bool IsCurrentParamAReference();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700327 bool IsCurrentParamAFloatOrDouble();
Serban Constantinescu75b91132014-04-09 18:39:10 +0100328 bool IsCurrentParamADouble();
329 bool IsCurrentParamALong();
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700330 bool IsCurrentParamALongOrDouble() {
331 return IsCurrentParamALong() || IsCurrentParamADouble();
332 }
Serban Constantinescu75b91132014-04-09 18:39:10 +0100333 bool IsCurrentParamJniEnv();
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700334 size_t CurrentParamSize() const;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700335 virtual bool IsCurrentParamInRegister() = 0;
336 virtual bool IsCurrentParamOnStack() = 0;
337 virtual ManagedRegister CurrentParamRegister() = 0;
338 virtual FrameOffset CurrentParamStackOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700339
340 // Iterator interface extension for JNI
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700341 FrameOffset CurrentParamHandleScopeEntryOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700342
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700343 // Position of handle scope and interior fields
344 FrameOffset HandleScopeOffset() const {
Andreas Gampe542451c2016-07-26 09:02:02 -0700345 return FrameOffset(this->displacement_.Int32Value() + static_cast<size_t>(frame_pointer_size_));
Andreas Gampecf4035a2014-05-28 22:43:01 -0700346 // above Method reference
Ian Rogersb033c752011-07-20 12:22:35 -0700347 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700348
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700349 FrameOffset HandleScopeLinkOffset() const {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700350 return FrameOffset(HandleScopeOffset().Int32Value() +
351 HandleScope::LinkOffset(frame_pointer_size_));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700352 }
353
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700354 FrameOffset HandleScopeNumRefsOffset() const {
355 return FrameOffset(HandleScopeOffset().Int32Value() +
356 HandleScope::NumberOfReferencesOffset(frame_pointer_size_));
Ian Rogersb033c752011-07-20 12:22:35 -0700357 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700358
Mathieu Chartiere401d142015-04-22 13:56:20 -0700359 FrameOffset HandleReferencesOffset() const {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700360 return FrameOffset(HandleScopeOffset().Int32Value() +
361 HandleScope::ReferencesOffset(frame_pointer_size_));
Ian Rogersb033c752011-07-20 12:22:35 -0700362 }
363
Ian Rogers2c8f6532011-09-02 17:16:34 -0700364 virtual ~JniCallingConvention() {}
365
366 protected:
Ian Rogersb033c752011-07-20 12:22:35 -0700367 // Named iterator positions
368 enum IteratorPos {
369 kJniEnv = 0,
370 kObjectOrClass = 1
371 };
372
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700373 JniCallingConvention(bool is_static,
374 bool is_synchronized,
375 bool is_critical_native,
376 const char* shorty,
377 PointerSize frame_pointer_size)
378 : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size),
379 is_critical_native_(is_critical_native) {}
Ian Rogers2c8f6532011-09-02 17:16:34 -0700380
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700381 // Number of stack slots for outgoing arguments, above which the handle scope is
Ian Rogersb033c752011-07-20 12:22:35 -0700382 // located
Ian Rogers2c8f6532011-09-02 17:16:34 -0700383 virtual size_t NumberOfOutgoingStackArgs() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700384
Ian Rogers2c8f6532011-09-02 17:16:34 -0700385 protected:
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700386 size_t NumberOfExtraArgumentsForJni() const;
387
388 // Does the transition have a StackHandleScope?
389 bool HasHandleScope() const;
390 // Does the transition have a local reference segment state?
391 bool HasLocalReferenceSegmentState() const;
392 // Has a JNIEnv* parameter implicitly?
393 bool HasJniEnv() const;
394 // Has a 'jclass' parameter implicitly?
395 bool HasSelfClass() const;
396
397 // Are there extra JNI arguments (JNIEnv* and maybe jclass)?
398 bool HasExtraArgumentsForJni() const;
399
400 // Returns the position of itr_args_, fixed up by removing the offset of extra JNI arguments.
401 unsigned int GetIteratorPositionWithinShorty() const;
402
403 // Is the current argument (at the iterator) an extra argument for JNI?
404 bool IsCurrentArgExtraForJni() const;
405
406 const bool is_critical_native_;
407
408 private:
409 // Shorthand for switching on the switch value but only IF there are extra JNI arguments.
410 //
411 // Puts the case value into return_value.
412 // * (switch_value == kJniEnv) => case_jni_env
413 // * (switch_value == kObjectOrClass) => case_object_or_class
414 //
415 // Returns false otherwise (or if there are no extra JNI arguments).
416 bool SwitchExtraJniArguments(size_t switch_value,
417 bool case_jni_env,
418 bool case_object_or_class,
419 /* out parameters */
420 bool* return_value) const;
Ian Rogersb033c752011-07-20 12:22:35 -0700421};
422
423} // namespace art
424
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700425#endif // ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_