blob: 043bceae1717c16c35cb8f736fab82a1371371a1 [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"
23#include "jni/quick/x86/calling_convention_x86.h"
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070024#include "jni/quick/x86_64/calling_convention_x86_64.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070025#include "utils.h"
26
27namespace art {
28
29// Offset of Method within the frame
30FrameOffset CallingConvention::MethodStackOffset() {
31 return displacement_;
32}
33
34// Managed runtime calling convention
35
36ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
37 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
38 switch (instruction_set) {
39 case kArm:
40 case kThumb2:
41 return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Stuart Monteithb95a5342014-03-12 13:32:32 +000042 case kArm64:
43 return new arm64::Arm64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070044 case kMips:
45 return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
46 case kX86:
47 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070048 case kX86_64:
49 return new x86_64::X86_64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070050 default:
51 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
52 return NULL;
53 }
54}
55
56bool ManagedRuntimeCallingConvention::HasNext() {
57 return itr_args_ < NumArgs();
58}
59
60void ManagedRuntimeCallingConvention::Next() {
61 CHECK(HasNext());
62 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args
63 IsParamALongOrDouble(itr_args_)) {
64 itr_longs_and_doubles_++;
65 itr_slots_++;
66 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070067 if (IsParamAFloatOrDouble(itr_args_)) {
68 itr_float_and_doubles_++;
69 }
Brian Carlstrom7940e442013-07-12 13:46:57 -070070 if (IsCurrentParamAReference()) {
71 itr_refs_++;
72 }
73 itr_args_++;
74 itr_slots_++;
75}
76
77bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
78 // Static methods have no implicit arguments, others implicitly pass this
79 return IsStatic() || (itr_args_ != 0);
80}
81
82bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
83 return IsCurrentArgExplicit(); // any user parameter may be null
84}
85
86size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
87 return ParamSize(itr_args_);
88}
89
90bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
91 return IsParamAReference(itr_args_);
92}
93
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070094bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
95 return IsParamAFloatOrDouble(itr_args_);
96}
97
Brian Carlstrom7940e442013-07-12 13:46:57 -070098// JNI calling convention
99
100JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
101 const char* shorty,
102 InstructionSet instruction_set) {
103 switch (instruction_set) {
104 case kArm:
105 case kThumb2:
106 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
Stuart Monteithb95a5342014-03-12 13:32:32 +0000107 case kArm64:
108 return new arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700109 case kMips:
110 return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
111 case kX86:
112 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700113 case kX86_64:
114 return new x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700115 default:
116 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
117 return NULL;
118 }
119}
120
121size_t JniCallingConvention::ReferenceCount() const {
122 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
123}
124
125FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700126 size_t references_size = kSirtPointerSize * ReferenceCount(); // size excluding header
127 return FrameOffset(SirtReferencesOffset().Int32Value() + references_size);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700128}
129
130FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
131 // Segment state is 4 bytes long
132 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
133}
134
135bool JniCallingConvention::HasNext() {
136 if (itr_args_ <= kObjectOrClass) {
137 return true;
138 } else {
139 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
140 return arg_pos < NumArgs();
141 }
142}
143
144void JniCallingConvention::Next() {
145 CHECK(HasNext());
146 if (itr_args_ > kObjectOrClass) {
147 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
148 if (IsParamALongOrDouble(arg_pos)) {
149 itr_longs_and_doubles_++;
150 itr_slots_++;
151 }
152 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700153 if (IsCurrentParamAFloatOrDouble()) {
154 itr_float_and_doubles_++;
155 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700156 if (IsCurrentParamAReference()) {
157 itr_refs_++;
158 }
159 itr_args_++;
160 itr_slots_++;
161}
162
163bool JniCallingConvention::IsCurrentParamAReference() {
164 switch (itr_args_) {
165 case kJniEnv:
166 return false; // JNIEnv*
167 case kObjectOrClass:
168 return true; // jobject or jclass
169 default: {
170 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
171 return IsParamAReference(arg_pos);
172 }
173 }
174}
175
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700176bool JniCallingConvention::IsCurrentParamAFloatOrDouble() {
177 switch (itr_args_) {
178 case kJniEnv:
179 return false; // JNIEnv*
180 case kObjectOrClass:
181 return false; // jobject or jclass
182 default: {
183 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
184 return IsParamAFloatOrDouble(arg_pos);
185 }
186 }
187}
188
Brian Carlstrom7940e442013-07-12 13:46:57 -0700189// Return position of SIRT entry holding reference at the current iterator
190// position
191FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
192 CHECK(IsCurrentParamAReference());
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800193 CHECK_LT(SirtLinkOffset(), SirtNumRefsOffset());
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700194 int result = SirtReferencesOffset().Int32Value() + itr_refs_ * kSirtPointerSize;
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800195 CHECK_GT(result, SirtNumRefsOffset().Int32Value());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700196 return FrameOffset(result);
197}
198
199size_t JniCallingConvention::CurrentParamSize() {
200 if (itr_args_ <= kObjectOrClass) {
201 return kPointerSize; // JNIEnv or jobject/jclass
202 } else {
203 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
204 return ParamSize(arg_pos);
205 }
206}
207
208size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
209 // The first argument is the JNIEnv*.
210 // Static methods have an extra argument which is the jclass.
211 return IsStatic() ? 2 : 1;
212}
213
214} // namespace art