blob: 4950905d4cbdf83aee13c9b0a80a04c21f78d346 [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
Ian Rogers0d666d82011-08-14 16:03:46 -070020#include <vector>
Elliott Hughes68e76522011-10-05 13:22:16 -070021#include "stack_indirect_reference_table.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070022#include "thread.h"
Ian Rogers166db042013-07-26 12:05:57 -070023#include "utils/managed_register.h"
Ian Rogersb033c752011-07-20 12:22:35 -070024
25namespace art {
26
27// Top-level abstraction for different calling conventions
28class CallingConvention {
29 public:
Ian Rogers169c9a72011-11-13 20:13:17 -080030 bool IsReturnAReference() const { return shorty_[0] == 'L'; }
Ian Rogersb033c752011-07-20 12:22:35 -070031
jeffhao58136ca2012-05-24 13:40:11 -070032 Primitive::Type GetReturnType() const {
33 return Primitive::GetType(shorty_[0]);
34 }
35
Ian Rogers169c9a72011-11-13 20:13:17 -080036 size_t SizeOfReturnValue() const {
37 size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[0]));
38 if (result >= 1 && result < 4) {
39 result = 4;
40 }
41 return result;
42 }
Ian Rogersdf20fe02011-07-20 20:34:16 -070043
Ian Rogers00f7d0e2012-07-19 15:28:27 -070044 // Register that holds result of this method invocation.
Ian Rogers2c8f6532011-09-02 17:16:34 -070045 virtual ManagedRegister ReturnRegister() = 0;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070046 // Register reserved for scratch usage during procedure calls.
Ian Rogers2c8f6532011-09-02 17:16:34 -070047 virtual ManagedRegister InterproceduralScratchRegister() = 0;
Shih-wei Liao668512a2011-09-01 14:18:34 -070048
Carl Shapiroe2d373e2011-07-25 15:20:06 -070049 // Offset of Method within the frame
50 FrameOffset MethodStackOffset();
51
Ian Rogersb033c752011-07-20 12:22:35 -070052 // Iterator interface
53
54 // Place iterator at start of arguments. The displacement is applied to
55 // frame offset methods to account for frames which may be on the stack
56 // below the one being iterated over.
57 void ResetIterator(FrameOffset displacement) {
58 displacement_ = displacement;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070059 itr_slots_ = 0;
60 itr_args_ = 0;
Shih-wei Liao668512a2011-09-01 14:18:34 -070061 itr_refs_ = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070062 itr_longs_and_doubles_ = 0;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070063 itr_float_and_doubles_ = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070064 }
65
Ian Rogers2c8f6532011-09-02 17:16:34 -070066 virtual ~CallingConvention() {}
67
Ian Rogersb033c752011-07-20 12:22:35 -070068 protected:
Ian Rogers169c9a72011-11-13 20:13:17 -080069 CallingConvention(bool is_static, bool is_synchronized, const char* shorty)
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070070 : displacement_(0), kSirtPointerSize(sizeof(StackReference<mirror::Object>)), is_static_(is_static), is_synchronized_(is_synchronized),
Ian Rogers169c9a72011-11-13 20:13:17 -080071 shorty_(shorty) {
72 num_args_ = (is_static ? 0 : 1) + strlen(shorty) - 1;
73 num_ref_args_ = is_static ? 0 : 1; // The implicit this pointer.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070074 num_float_or_double_args_ = 0;
Ian Rogers169c9a72011-11-13 20:13:17 -080075 num_long_or_double_args_ = 0;
76 for (size_t i = 1; i < strlen(shorty); i++) {
77 char ch = shorty_[i];
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070078 switch (ch) {
79 case 'L':
Ian Rogers169c9a72011-11-13 20:13:17 -080080 num_ref_args_++;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070081 break;
82 case 'J':
Ian Rogers169c9a72011-11-13 20:13:17 -080083 num_long_or_double_args_++;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070084 break;
85 case 'D':
86 num_long_or_double_args_++;
87 num_float_or_double_args_++;
88 break;
89 case 'F':
90 num_float_or_double_args_++;
91 break;
Ian Rogers169c9a72011-11-13 20:13:17 -080092 }
93 }
94 }
Ian Rogers2c8f6532011-09-02 17:16:34 -070095
Ian Rogers169c9a72011-11-13 20:13:17 -080096 bool IsStatic() const {
97 return is_static_;
98 }
99 bool IsSynchronized() const {
100 return is_synchronized_;
101 }
102 bool IsParamALongOrDouble(unsigned int param) const {
103 DCHECK_LT(param, NumArgs());
104 if (IsStatic()) {
105 param++; // 0th argument must skip return value at start of the shorty
106 } else if (param == 0) {
107 return false; // this argument
108 }
109 char ch = shorty_[param];
110 return (ch == 'J' || ch == 'D');
111 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700112 bool IsParamAFloatOrDouble(unsigned int param) const {
113 DCHECK_LT(param, NumArgs());
114 if (IsStatic()) {
115 param++; // 0th argument must skip return value at start of the shorty
116 } else if (param == 0) {
117 return false; // this argument
118 }
119 char ch = shorty_[param];
120 return (ch == 'F' || ch == 'D');
121 }
Ian Rogers169c9a72011-11-13 20:13:17 -0800122 bool IsParamAReference(unsigned int param) const {
123 DCHECK_LT(param, NumArgs());
124 if (IsStatic()) {
125 param++; // 0th argument must skip return value at start of the shorty
126 } else if (param == 0) {
127 return true; // this argument
128 }
129 return shorty_[param] == 'L';
Ian Rogers169c9a72011-11-13 20:13:17 -0800130 }
131 size_t NumArgs() const {
132 return num_args_;
133 }
134 size_t NumLongOrDoubleArgs() const {
135 return num_long_or_double_args_;
136 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700137 size_t NumFloatOrDoubleArgs() const {
138 return num_float_or_double_args_;
139 }
Ian Rogers169c9a72011-11-13 20:13:17 -0800140 size_t NumReferenceArgs() const {
141 return num_ref_args_;
142 }
143 size_t ParamSize(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) {
148 return kPointerSize; // this argument
149 }
150 size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[param]));
151 if (result >= 1 && result < 4) {
152 result = 4;
153 }
154 return result;
155 }
156 const char* GetShorty() const {
157 return shorty_.c_str();
158 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700159 // The slot number for current calling_convention argument.
160 // Note that each slot is 32-bit. When the current argument is bigger
161 // than 32 bits, return the first slot number for this argument.
162 unsigned int itr_slots_;
Ian Rogers7a99c112011-09-07 12:48:27 -0700163 // The number of references iterated past
164 unsigned int itr_refs_;
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700165 // The argument number along argument list for current argument
166 unsigned int itr_args_;
167 // Number of longs and doubles seen along argument list
Ian Rogersb033c752011-07-20 12:22:35 -0700168 unsigned int itr_longs_and_doubles_;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700169 // Number of float and doubles seen along argument list
170 unsigned int itr_float_and_doubles_;
Ian Rogersb033c752011-07-20 12:22:35 -0700171 // Space for frames below this on the stack
172 FrameOffset displacement_;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700173 size_t kSirtPointerSize;
Ian Rogersb033c752011-07-20 12:22:35 -0700174
175 private:
Ian Rogers169c9a72011-11-13 20:13:17 -0800176 const bool is_static_;
177 const bool is_synchronized_;
178 std::string shorty_;
179 size_t num_args_;
180 size_t num_ref_args_;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700181 size_t num_float_or_double_args_;
Ian Rogers169c9a72011-11-13 20:13:17 -0800182 size_t num_long_or_double_args_;
Ian Rogersb033c752011-07-20 12:22:35 -0700183};
184
185// Abstraction for managed code's calling conventions
Ian Rogersbdb03912011-09-14 00:55:44 -0700186// | { Incoming stack args } |
187// | { Prior Method* } | <-- Prior SP
188// | { Return address } |
189// | { Callee saves } |
190// | { Spills ... } |
191// | { Outgoing stack args } |
192// | { Method* } | <-- SP
Ian Rogersb033c752011-07-20 12:22:35 -0700193class ManagedRuntimeCallingConvention : public CallingConvention {
194 public:
Ian Rogers169c9a72011-11-13 20:13:17 -0800195 static ManagedRuntimeCallingConvention* Create(bool is_static, bool is_synchronized,
196 const char* shorty,
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700197 InstructionSet instruction_set);
Ian Rogersb033c752011-07-20 12:22:35 -0700198
Ian Rogers2c8f6532011-09-02 17:16:34 -0700199 // Register that holds the incoming method argument
200 virtual ManagedRegister MethodRegister() = 0;
201
Ian Rogersb033c752011-07-20 12:22:35 -0700202 // Iterator interface
203 bool HasNext();
204 void Next();
205 bool IsCurrentParamAReference();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700206 bool IsCurrentParamAFloatOrDouble();
Ian Rogers7a99c112011-09-07 12:48:27 -0700207 bool IsCurrentArgExplicit(); // ie a non-implict argument such as this
208 bool IsCurrentArgPossiblyNull();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700209 size_t CurrentParamSize();
Ian Rogers2c8f6532011-09-02 17:16:34 -0700210 virtual bool IsCurrentParamInRegister() = 0;
211 virtual bool IsCurrentParamOnStack() = 0;
212 virtual ManagedRegister CurrentParamRegister() = 0;
213 virtual FrameOffset CurrentParamStackOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700214
Ian Rogers2c8f6532011-09-02 17:16:34 -0700215 virtual ~ManagedRuntimeCallingConvention() {}
216
Ian Rogersb5d09b22012-03-06 22:14:17 -0800217 // Registers to spill to caller's out registers on entry.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700218 virtual const ManagedRegisterEntrySpills& EntrySpills() = 0;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800219
Ian Rogers2c8f6532011-09-02 17:16:34 -0700220 protected:
Ian Rogersca190662012-06-26 15:45:57 -0700221 ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
222 : CallingConvention(is_static, is_synchronized, shorty) {}
Ian Rogersb033c752011-07-20 12:22:35 -0700223};
224
225// Abstraction for JNI calling conventions
Ian Rogersbdb03912011-09-14 00:55:44 -0700226// | { Incoming stack args } | <-- Prior SP
227// | { Return address } |
228// | { Callee saves } | ([1])
229// | { Return value spill } | (live on return slow paths)
Ian Rogersdc51b792011-09-22 20:41:37 -0700230// | { Local Ref. Table State } |
Ian Rogersbdb03912011-09-14 00:55:44 -0700231// | { Stack Indirect Ref. Table |
232// | num. refs./link } | (here to prior SP is frame size)
233// | { Method* } | <-- Anchor SP written to thread
234// | { Outgoing stack args } | <-- SP at point of call
235// | Native frame |
236//
237// [1] We must save all callee saves here to enable any exception throws to restore
238// callee saves for frames above this one.
Ian Rogersb033c752011-07-20 12:22:35 -0700239class JniCallingConvention : public CallingConvention {
240 public:
Ian Rogers169c9a72011-11-13 20:13:17 -0800241 static JniCallingConvention* Create(bool is_static, bool is_synchronized, const char* shorty,
Ian Rogers2c8f6532011-09-02 17:16:34 -0700242 InstructionSet instruction_set);
Ian Rogersb033c752011-07-20 12:22:35 -0700243
244 // Size of frame excluding space for outgoing args (its assumed Method* is
245 // always at the bottom of a frame, but this doesn't work for outgoing
246 // native args). Includes alignment.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700247 virtual size_t FrameSize() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700248 // Size of outgoing arguments, including alignment
Ian Rogers2c8f6532011-09-02 17:16:34 -0700249 virtual size_t OutArgSize() = 0;
Ian Rogers408f79a2011-08-23 18:22:33 -0700250 // Number of references in stack indirect reference table
Ian Rogersdc51b792011-09-22 20:41:37 -0700251 size_t ReferenceCount() const;
252 // Location where the segment state of the local indirect reference table is saved
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700253 FrameOffset SavedLocalReferenceCookieOffset() const;
Ian Rogersdf20fe02011-07-20 20:34:16 -0700254 // Location where the return value of a call can be squirreled if another
255 // call is made following the native call
Ian Rogersdc51b792011-09-22 20:41:37 -0700256 FrameOffset ReturnValueSaveLocation() const;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700257 // Register that holds result if it is integer.
258 virtual ManagedRegister IntReturnRegister() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700259
Ian Rogersbdb03912011-09-14 00:55:44 -0700260 // Callee save registers to spill prior to native code (which may clobber)
261 virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const = 0;
262
263 // Spill mask values
264 virtual uint32_t CoreSpillMask() const = 0;
265 virtual uint32_t FpSpillMask() const = 0;
Ian Rogers0d666d82011-08-14 16:03:46 -0700266
Ian Rogersdc51b792011-09-22 20:41:37 -0700267 // An extra scratch register live after the call
268 virtual ManagedRegister ReturnScratchRegister() const = 0;
269
Ian Rogersb033c752011-07-20 12:22:35 -0700270 // Iterator interface
271 bool HasNext();
Ian Rogers67375ac2011-09-14 00:55:44 -0700272 virtual void Next();
Ian Rogersb033c752011-07-20 12:22:35 -0700273 bool IsCurrentParamAReference();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700274 bool IsCurrentParamAFloatOrDouble();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700275 size_t CurrentParamSize();
Ian Rogers2c8f6532011-09-02 17:16:34 -0700276 virtual bool IsCurrentParamInRegister() = 0;
277 virtual bool IsCurrentParamOnStack() = 0;
278 virtual ManagedRegister CurrentParamRegister() = 0;
279 virtual FrameOffset CurrentParamStackOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700280
281 // Iterator interface extension for JNI
Ian Rogers408f79a2011-08-23 18:22:33 -0700282 FrameOffset CurrentParamSirtEntryOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700283
Ian Rogers408f79a2011-08-23 18:22:33 -0700284 // Position of SIRT and interior fields
Ian Rogersdc51b792011-09-22 20:41:37 -0700285 FrameOffset SirtOffset() const {
Ian Rogersb033c752011-07-20 12:22:35 -0700286 return FrameOffset(displacement_.Int32Value() +
287 kPointerSize); // above Method*
288 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700289
290 FrameOffset SirtLinkOffset() const {
291 return FrameOffset(SirtOffset().Int32Value() +
292 StackIndirectReferenceTable::LinkOffset());
293 }
294
Ian Rogersdc51b792011-09-22 20:41:37 -0700295 FrameOffset SirtNumRefsOffset() const {
Ian Rogers408f79a2011-08-23 18:22:33 -0700296 return FrameOffset(SirtOffset().Int32Value() +
297 StackIndirectReferenceTable::NumberOfReferencesOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700298 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700299
300 FrameOffset SirtReferencesOffset() const {
Dmitry Petrochenkof0513c52014-03-31 09:12:31 +0700301 return FrameOffset(SirtOffset().Int32Value() +
302 StackIndirectReferenceTable::ReferencesOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700303 }
304
Ian Rogers2c8f6532011-09-02 17:16:34 -0700305 virtual ~JniCallingConvention() {}
306
307 protected:
Ian Rogersb033c752011-07-20 12:22:35 -0700308 // Named iterator positions
309 enum IteratorPos {
310 kJniEnv = 0,
311 kObjectOrClass = 1
312 };
313
Ian Rogersca190662012-06-26 15:45:57 -0700314 explicit JniCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
315 : CallingConvention(is_static, is_synchronized, shorty) {}
Ian Rogers2c8f6532011-09-02 17:16:34 -0700316
Ian Rogers408f79a2011-08-23 18:22:33 -0700317 // Number of stack slots for outgoing arguments, above which the SIRT is
Ian Rogersb033c752011-07-20 12:22:35 -0700318 // located
Ian Rogers2c8f6532011-09-02 17:16:34 -0700319 virtual size_t NumberOfOutgoingStackArgs() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700320
Ian Rogers2c8f6532011-09-02 17:16:34 -0700321 protected:
Ian Rogers169c9a72011-11-13 20:13:17 -0800322 size_t NumberOfExtraArgumentsForJni();
Ian Rogersb033c752011-07-20 12:22:35 -0700323};
324
325} // namespace art
326
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700327#endif // ART_COMPILER_JNI_QUICK_CALLING_CONVENTION_H_