blob: 5856df4bc1815985ff741dcf6bd185b6302961c1 [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"
24#include "utils.h"
25
26namespace art {
27
28// Offset of Method within the frame
29FrameOffset CallingConvention::MethodStackOffset() {
30 return displacement_;
31}
32
33// Managed runtime calling convention
34
35ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
36 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
37 switch (instruction_set) {
38 case kArm:
39 case kThumb2:
40 return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Stuart Monteithb95a5342014-03-12 13:32:32 +000041 case kArm64:
42 return new arm64::Arm64ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070043 case kMips:
44 return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
45 case kX86:
46 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
47 default:
48 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
49 return NULL;
50 }
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 }
64 if (IsCurrentParamAReference()) {
65 itr_refs_++;
66 }
67 itr_args_++;
68 itr_slots_++;
69}
70
71bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
72 // Static methods have no implicit arguments, others implicitly pass this
73 return IsStatic() || (itr_args_ != 0);
74}
75
76bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
77 return IsCurrentArgExplicit(); // any user parameter may be null
78}
79
80size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
81 return ParamSize(itr_args_);
82}
83
84bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
85 return IsParamAReference(itr_args_);
86}
87
88// JNI calling convention
89
90JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
91 const char* shorty,
92 InstructionSet instruction_set) {
93 switch (instruction_set) {
94 case kArm:
95 case kThumb2:
96 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
Stuart Monteithb95a5342014-03-12 13:32:32 +000097 case kArm64:
98 return new arm64::Arm64JniCallingConvention(is_static, is_synchronized, shorty);
Brian Carlstrom7940e442013-07-12 13:46:57 -070099 case kMips:
100 return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
101 case kX86:
102 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
103 default:
104 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
105 return NULL;
106 }
107}
108
109size_t JniCallingConvention::ReferenceCount() const {
110 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
111}
112
113FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800114 size_t start_of_sirt = SirtNumRefsOffset().Int32Value() + kPointerSize;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700115 size_t references_size = kPointerSize * ReferenceCount(); // size excluding header
116 return FrameOffset(start_of_sirt + references_size);
117}
118
119FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
120 // Segment state is 4 bytes long
121 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
122}
123
124bool JniCallingConvention::HasNext() {
125 if (itr_args_ <= kObjectOrClass) {
126 return true;
127 } else {
128 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
129 return arg_pos < NumArgs();
130 }
131}
132
133void JniCallingConvention::Next() {
134 CHECK(HasNext());
135 if (itr_args_ > kObjectOrClass) {
136 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
137 if (IsParamALongOrDouble(arg_pos)) {
138 itr_longs_and_doubles_++;
139 itr_slots_++;
140 }
141 }
142 if (IsCurrentParamAReference()) {
143 itr_refs_++;
144 }
145 itr_args_++;
146 itr_slots_++;
147}
148
149bool JniCallingConvention::IsCurrentParamAReference() {
150 switch (itr_args_) {
151 case kJniEnv:
152 return false; // JNIEnv*
153 case kObjectOrClass:
154 return true; // jobject or jclass
155 default: {
156 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
157 return IsParamAReference(arg_pos);
158 }
159 }
160}
161
162// Return position of SIRT entry holding reference at the current iterator
163// position
164FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
165 CHECK(IsCurrentParamAReference());
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800166 CHECK_LT(SirtLinkOffset(), SirtNumRefsOffset());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700167 // Address of 1st SIRT entry
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800168 int result = SirtNumRefsOffset().Int32Value() + kPointerSize;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700169 result += itr_refs_ * kPointerSize;
Andreas Gampebf6b92a2014-03-05 16:11:04 -0800170 CHECK_GT(result, SirtNumRefsOffset().Int32Value());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700171 return FrameOffset(result);
172}
173
174size_t JniCallingConvention::CurrentParamSize() {
175 if (itr_args_ <= kObjectOrClass) {
176 return kPointerSize; // JNIEnv or jobject/jclass
177 } else {
178 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
179 return ParamSize(arg_pos);
180 }
181}
182
183size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
184 // The first argument is the JNIEnv*.
185 // Static methods have an extra argument which is the jclass.
186 return IsStatic() ? 2 : 1;
187}
188
189} // namespace art