blob: 8efdcdaab2649058063d541835778a96f05adb56 [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
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);
41 case kX86:
42 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070043 case kX86_64:
44 return new x86_64::X86_64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070045 default:
46 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
47 return NULL;
48 }
49}
50
51bool ManagedRuntimeCallingConvention::HasNext() {
52 return itr_args_ < NumArgs();
53}
54
55void ManagedRuntimeCallingConvention::Next() {
56 CHECK(HasNext());
57 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args
58 IsParamALongOrDouble(itr_args_)) {
59 itr_longs_and_doubles_++;
60 itr_slots_++;
61 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070062 if (IsParamAFloatOrDouble(itr_args_)) {
63 itr_float_and_doubles_++;
64 }
Brian Carlstrom7940e442013-07-12 13:46:57 -070065 if (IsCurrentParamAReference()) {
66 itr_refs_++;
67 }
68 itr_args_++;
69 itr_slots_++;
70}
71
72bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
73 // Static methods have no implicit arguments, others implicitly pass this
74 return IsStatic() || (itr_args_ != 0);
75}
76
77bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
78 return IsCurrentArgExplicit(); // any user parameter may be null
79}
80
81size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
82 return ParamSize(itr_args_);
83}
84
85bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
86 return IsParamAReference(itr_args_);
87}
88
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070089bool ManagedRuntimeCallingConvention::IsCurrentParamAFloatOrDouble() {
90 return IsParamAFloatOrDouble(itr_args_);
91}
92
Brian Carlstrom7940e442013-07-12 13:46:57 -070093// JNI calling convention
94
95JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
96 const char* shorty,
97 InstructionSet instruction_set) {
98 switch (instruction_set) {
99 case kArm:
100 case kThumb2:
101 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
Stuart Monteithb95a5342014-03-12 13:32:32 +0000102 case kArm64:
103 return new arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700104 case kMips:
105 return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
106 case kX86:
107 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700108 case kX86_64:
109 return new x86_64::X86_64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700110 default:
111 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
112 return NULL;
113 }
114}
115
116size_t JniCallingConvention::ReferenceCount() const {
117 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
118}
119
120FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
Ian Rogers790a6b72014-04-01 10:36:00 -0700121 size_t references_size = sirt_pointer_size_ * ReferenceCount(); // size excluding header
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700122 return FrameOffset(SirtReferencesOffset().Int32Value() + references_size);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700123}
124
125FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
126 // Segment state is 4 bytes long
127 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
128}
129
130bool JniCallingConvention::HasNext() {
131 if (itr_args_ <= kObjectOrClass) {
132 return true;
133 } else {
134 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
135 return arg_pos < NumArgs();
136 }
137}
138
139void JniCallingConvention::Next() {
140 CHECK(HasNext());
141 if (itr_args_ > kObjectOrClass) {
142 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
143 if (IsParamALongOrDouble(arg_pos)) {
144 itr_longs_and_doubles_++;
145 itr_slots_++;
146 }
147 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700148 if (IsCurrentParamAFloatOrDouble()) {
149 itr_float_and_doubles_++;
150 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700151 if (IsCurrentParamAReference()) {
152 itr_refs_++;
153 }
154 itr_args_++;
155 itr_slots_++;
156}
157
158bool JniCallingConvention::IsCurrentParamAReference() {
159 switch (itr_args_) {
160 case kJniEnv:
161 return false; // JNIEnv*
162 case kObjectOrClass:
163 return true; // jobject or jclass
164 default: {
165 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
166 return IsParamAReference(arg_pos);
167 }
168 }
169}
170
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700171bool JniCallingConvention::IsCurrentParamAFloatOrDouble() {
172 switch (itr_args_) {
173 case kJniEnv:
174 return false; // JNIEnv*
175 case kObjectOrClass:
176 return false; // jobject or jclass
177 default: {
178 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
179 return IsParamAFloatOrDouble(arg_pos);
180 }
181 }
182}
183
Brian Carlstrom7940e442013-07-12 13:46:57 -0700184// Return position of SIRT entry holding reference at the current iterator
185// position
186FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
187 CHECK(IsCurrentParamAReference());
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800188 CHECK_LT(SirtLinkOffset(), SirtNumRefsOffset());
Ian Rogers790a6b72014-04-01 10:36:00 -0700189 int result = SirtReferencesOffset().Int32Value() + itr_refs_ * sirt_pointer_size_;
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800190 CHECK_GT(result, SirtNumRefsOffset().Int32Value());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700191 return FrameOffset(result);
192}
193
194size_t JniCallingConvention::CurrentParamSize() {
195 if (itr_args_ <= kObjectOrClass) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700196 return frame_pointer_size_; // JNIEnv or jobject/jclass
Brian Carlstrom7940e442013-07-12 13:46:57 -0700197 } else {
198 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
199 return ParamSize(arg_pos);
200 }
201}
202
203size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
204 // The first argument is the JNIEnv*.
205 // Static methods have an extra argument which is the jclass.
206 return IsStatic() ? 2 : 1;
207}
208
209} // namespace art