blob: 436fc0cfd0a6ac341169a5b853407742642c3f0a [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#include "utils.h"
27
28namespace art {
29
Brian Carlstrom7940e442013-07-12 13:46:57 -070030// Managed runtime calling convention
31
32ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
33 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
34 switch (instruction_set) {
35 case kArm:
36 case kThumb2:
37 return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Stuart Monteithb95a5342014-03-12 13:32:32 +000038 case kArm64:
39 return new arm64::Arm64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070040 case kMips:
41 return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Maja Gagic6ea651f2015-02-24 16:55:04 +010042 case kMips64:
43 return new mips64::Mips64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070044 case kX86:
45 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070046 case kX86_64:
47 return new x86_64::X86_64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070048 default:
49 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Mathieu Chartier2cebb242015-04-21 16:50:40 -070050 return nullptr;
Brian Carlstrom7940e442013-07-12 13:46:57 -070051 }
52}
53
54bool ManagedRuntimeCallingConvention::HasNext() {
55 return itr_args_ < NumArgs();
56}
57
58void ManagedRuntimeCallingConvention::Next() {
59 CHECK(HasNext());
60 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args
61 IsParamALongOrDouble(itr_args_)) {
62 itr_longs_and_doubles_++;
63 itr_slots_++;
64 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070065 if (IsParamAFloatOrDouble(itr_args_)) {
66 itr_float_and_doubles_++;
67 }
Brian Carlstrom7940e442013-07-12 13:46:57 -070068 if (IsCurrentParamAReference()) {
69 itr_refs_++;
70 }
71 itr_args_++;
72 itr_slots_++;
73}
74
75bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
76 // Static methods have no implicit arguments, others implicitly pass this
77 return IsStatic() || (itr_args_ != 0);
78}
79
80bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
81 return IsCurrentArgExplicit(); // any user parameter may be null
82}
83
84size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
85 return ParamSize(itr_args_);
86}
87
88bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
89 return IsParamAReference(itr_args_);
90}
91
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070092bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
93 return IsParamAFloatOrDouble(itr_args_);
94}
95
Serban Constantinescu75b91132014-04-09 18:39:10 +010096bool ManagedRuntimeCallingConvention::IsCurrentParamADouble() {
97 return IsParamADouble(itr_args_);
98}
99
100bool ManagedRuntimeCallingConvention::IsCurrentParamALong() {
101 return IsParamALong(itr_args_);
102}
103
Brian Carlstrom7940e442013-07-12 13:46:57 -0700104// JNI calling convention
105
106JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
107 const char* shorty,
108 InstructionSet instruction_set) {
109 switch (instruction_set) {
110 case kArm:
111 case kThumb2:
112 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
Stuart Monteithb95a5342014-03-12 13:32:32 +0000113 case kArm64:
114 return new arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700115 case kMips:
116 return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
Maja Gagic6ea651f2015-02-24 16:55:04 +0100117 case kMips64:
118 return new mips64::Mips64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700119 case kX86:
120 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700121 case kX86_64:
122 return new x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700123 default:
124 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700125 return nullptr;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700126 }
127}
128
129size_t JniCallingConvention::ReferenceCount() const {
130 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
131}
132
133FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700134 size_t references_size = handle_scope_pointer_size_ * ReferenceCount(); // size excluding header
135 return FrameOffset(HandleerencesOffset().Int32Value() + references_size);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700136}
137
138FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
139 // Segment state is 4 bytes long
140 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
141}
142
143bool JniCallingConvention::HasNext() {
144 if (itr_args_ <= kObjectOrClass) {
145 return true;
146 } else {
147 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
148 return arg_pos < NumArgs();
149 }
150}
151
152void JniCallingConvention::Next() {
153 CHECK(HasNext());
154 if (itr_args_ > kObjectOrClass) {
155 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
156 if (IsParamALongOrDouble(arg_pos)) {
157 itr_longs_and_doubles_++;
158 itr_slots_++;
159 }
160 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700161 if (IsCurrentParamAFloatOrDouble()) {
162 itr_float_and_doubles_++;
163 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700164 if (IsCurrentParamAReference()) {
165 itr_refs_++;
166 }
167 itr_args_++;
168 itr_slots_++;
169}
170
171bool JniCallingConvention::IsCurrentParamAReference() {
172 switch (itr_args_) {
173 case kJniEnv:
174 return false; // JNIEnv*
175 case kObjectOrClass:
176 return true; // jobject or jclass
177 default: {
178 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
179 return IsParamAReference(arg_pos);
180 }
181 }
182}
183
Serban Constantinescu75b91132014-04-09 18:39:10 +0100184bool JniCallingConvention::IsCurrentParamJniEnv() {
185 return (itr_args_ == kJniEnv);
186}
187
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700188bool JniCallingConvention::IsCurrentParamAFloatOrDouble() {
189 switch (itr_args_) {
190 case kJniEnv:
191 return false; // JNIEnv*
192 case kObjectOrClass:
193 return false; // jobject or jclass
194 default: {
195 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
196 return IsParamAFloatOrDouble(arg_pos);
197 }
198 }
199}
200
Serban Constantinescu75b91132014-04-09 18:39:10 +0100201bool JniCallingConvention::IsCurrentParamADouble() {
202 switch (itr_args_) {
203 case kJniEnv:
204 return false; // JNIEnv*
205 case kObjectOrClass:
206 return false; // jobject or jclass
207 default: {
208 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
209 return IsParamADouble(arg_pos);
210 }
211 }
212}
213
214bool JniCallingConvention::IsCurrentParamALong() {
215 switch (itr_args_) {
216 case kJniEnv:
217 return false; // JNIEnv*
218 case kObjectOrClass:
219 return false; // jobject or jclass
220 default: {
221 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
222 return IsParamALong(arg_pos);
223 }
224 }
225}
226
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700227// Return position of handle scope entry holding reference at the current iterator
Brian Carlstrom7940e442013-07-12 13:46:57 -0700228// position
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700229FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700230 CHECK(IsCurrentParamAReference());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700231 CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset());
232 int result = HandleerencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
233 CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700234 return FrameOffset(result);
235}
236
237size_t JniCallingConvention::CurrentParamSize() {
238 if (itr_args_ <= kObjectOrClass) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700239 return frame_pointer_size_; // JNIEnv or jobject/jclass
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 } else {
241 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
242 return ParamSize(arg_pos);
243 }
244}
245
246size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
247 // The first argument is the JNIEnv*.
248 // Static methods have an extra argument which is the jclass.
249 return IsStatic() ? 2 : 1;
250}
251
252} // namespace art