blob: bb8136bfe1a23f1aeb914d673f1f372e768c884b [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"
20#include "jni/quick/arm/calling_convention_arm.h"
Stuart Monteithb95a5342014-03-12 13:32:32 +000021#include "jni/quick/arm64/calling_convention_arm64.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070022#include "jni/quick/mips/calling_convention_mips.h"
Maja Gagic6ea651f2015-02-24 16:55:04 +010023#include "jni/quick/mips64/calling_convention_mips64.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070024#include "jni/quick/x86/calling_convention_x86.h"
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070025#include "jni/quick/x86_64/calling_convention_x86_64.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070026
27namespace art {
28
Brian Carlstrom7940e442013-07-12 13:46:57 -070029// Managed runtime calling convention
30
31ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
32 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
33 switch (instruction_set) {
34 case kArm:
35 case kThumb2:
36 return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Stuart Monteithb95a5342014-03-12 13:32:32 +000037 case kArm64:
38 return new arm64::Arm64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070039 case kMips:
40 return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Maja Gagic6ea651f2015-02-24 16:55:04 +010041 case kMips64:
42 return new mips64::Mips64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070043 case kX86:
44 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070045 case kX86_64:
46 return new x86_64::X86_64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070047 default:
48 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Mathieu Chartier2cebb242015-04-21 16:50:40 -070049 return nullptr;
Brian Carlstrom7940e442013-07-12 13:46:57 -070050 }
51}
52
53bool ManagedRuntimeCallingConvention::HasNext() {
54 return itr_args_ < NumArgs();
55}
56
57void ManagedRuntimeCallingConvention::Next() {
58 CHECK(HasNext());
59 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args
60 IsParamALongOrDouble(itr_args_)) {
61 itr_longs_and_doubles_++;
62 itr_slots_++;
63 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070064 if (IsParamAFloatOrDouble(itr_args_)) {
65 itr_float_and_doubles_++;
66 }
Brian Carlstrom7940e442013-07-12 13:46:57 -070067 if (IsCurrentParamAReference()) {
68 itr_refs_++;
69 }
70 itr_args_++;
71 itr_slots_++;
72}
73
74bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
75 // Static methods have no implicit arguments, others implicitly pass this
76 return IsStatic() || (itr_args_ != 0);
77}
78
79bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
80 return IsCurrentArgExplicit(); // any user parameter may be null
81}
82
83size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
84 return ParamSize(itr_args_);
85}
86
87bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
88 return IsParamAReference(itr_args_);
89}
90
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070091bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
92 return IsParamAFloatOrDouble(itr_args_);
93}
94
Serban Constantinescu75b91132014-04-09 18:39:10 +010095bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() {
96 return IsParamADouble(itr_args_);
97}
98
99bool ManagedRuntimeCallingConvention::IsCurrentParamALong() {
100 return IsParamALong(itr_args_);
101}
102
Brian Carlstrom7940e442013-07-12 13:46:57 -0700103// JNI calling convention
104
105JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
106 const char* shorty,
107 InstructionSet instruction_set) {
108 switch (instruction_set) {
109 case kArm:
110 case kThumb2:
111 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
Stuart Monteithb95a5342014-03-12 13:32:32 +0000112 case kArm64:
113 return new arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700114 case kMips:
115 return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
Maja Gagic6ea651f2015-02-24 16:55:04 +0100116 case kMips64:
117 return new mips64::Mips64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700118 case kX86:
119 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700120 case kX86_64:
121 return new x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700122 default:
123 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700124 return nullptr;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700125 }
126}
127
128size_t JniCallingConvention::ReferenceCount() const {
129 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
130}
131
132FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700133 size_t references_size = handle_scope_pointer_size_ * ReferenceCount(); // size excluding header
Mathieu Chartiere401d142015-04-22 13:56:20 -0700134 return FrameOffset(HandleReferencesOffset().Int32Value() + references_size);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700135}
136
137FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
138 // Segment state is 4 bytes long
139 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
140}
141
142bool JniCallingConvention::HasNext() {
143 if (itr_args_ <= kObjectOrClass) {
144 return true;
145 } else {
146 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
147 return arg_pos < NumArgs();
148 }
149}
150
151void JniCallingConvention::Next() {
152 CHECK(HasNext());
153 if (itr_args_ > kObjectOrClass) {
154 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
155 if (IsParamALongOrDouble(arg_pos)) {
156 itr_longs_and_doubles_++;
157 itr_slots_++;
158 }
159 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700160 if (IsCurrentParamAFloatOrDouble()) {
161 itr_float_and_doubles_++;
162 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 if (IsCurrentParamAReference()) {
164 itr_refs_++;
165 }
166 itr_args_++;
167 itr_slots_++;
168}
169
170bool JniCallingConvention::IsCurrentParamAReference() {
171 switch (itr_args_) {
172 case kJniEnv:
173 return false; // JNIEnv*
174 case kObjectOrClass:
175 return true; // jobject or jclass
176 default: {
177 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
178 return IsParamAReference(arg_pos);
179 }
180 }
181}
182
Serban Constantinescu75b91132014-04-09 18:39:10 +0100183bool JniCallingConvention::IsCurrentParamJniEnv() {
184 return (itr_args_ == kJniEnv);
185}
186
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700187bool JniCallingConvention::IsCurrentParamAFloatOrDouble() {
188 switch (itr_args_) {
189 case kJniEnv:
190 return false; // JNIEnv*
191 case kObjectOrClass:
192 return false; // jobject or jclass
193 default: {
194 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
195 return IsParamAFloatOrDouble(arg_pos);
196 }
197 }
198}
199
Serban Constantinescu75b91132014-04-09 18:39:10 +0100200bool JniCallingConvention::IsCurrentParamADouble() {
201 switch (itr_args_) {
202 case kJniEnv:
203 return false; // JNIEnv*
204 case kObjectOrClass:
205 return false; // jobject or jclass
206 default: {
207 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
208 return IsParamADouble(arg_pos);
209 }
210 }
211}
212
213bool JniCallingConvention::IsCurrentParamALong() {
214 switch (itr_args_) {
215 case kJniEnv:
216 return false; // JNIEnv*
217 case kObjectOrClass:
218 return false; // jobject or jclass
219 default: {
220 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
221 return IsParamALong(arg_pos);
222 }
223 }
224}
225
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700226// Return position of handle scope entry holding reference at the current iterator
Brian Carlstrom7940e442013-07-12 13:46:57 -0700227// position
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700228FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700229 CHECK(IsCurrentParamAReference());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700230 CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset());
Mathieu Chartiere401d142015-04-22 13:56:20 -0700231 int result = HandleReferencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700232 CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700233 return FrameOffset(result);
234}
235
236size_t JniCallingConvention::CurrentParamSize() {
237 if (itr_args_ <= kObjectOrClass) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700238 return frame_pointer_size_; // JNIEnv or jobject/jclass
Brian Carlstrom7940e442013-07-12 13:46:57 -0700239 } else {
240 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
241 return ParamSize(arg_pos);
242 }
243}
244
245size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
246 // The first argument is the JNIEnv*.
247 // Static methods have an extra argument which is the jclass.
248 return IsStatic() ? 2 : 1;
249}
250
251} // namespace art