1 /*
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"
21 #include "jni/quick/mips/calling_convention_mips.h"
22 #include "jni/quick/x86/calling_convention_x86.h"
23 #include "utils.h"
24
25 namespace art {
26
27 // Offset of Method within the frame
MethodStackOffset()28 FrameOffset CallingConvention::MethodStackOffset() {
29 return displacement_;
30 }
31
32 // Managed runtime calling convention
33
Create(bool is_static,bool is_synchronized,const char * shorty,InstructionSet instruction_set)34 ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
35 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
36 switch (instruction_set) {
37 case kArm:
38 case kThumb2:
39 return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
40 case kMips:
41 return new mips::MipsManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
42 case kX86:
43 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
44 default:
45 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
46 return NULL;
47 }
48 }
49
HasNext()50 bool ManagedRuntimeCallingConvention::HasNext() {
51 return itr_args_ < NumArgs();
52 }
53
Next()54 void ManagedRuntimeCallingConvention::Next() {
55 CHECK(HasNext());
56 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args
57 IsParamALongOrDouble(itr_args_)) {
58 itr_longs_and_doubles_++;
59 itr_slots_++;
60 }
61 if (IsCurrentParamAReference()) {
62 itr_refs_++;
63 }
64 itr_args_++;
65 itr_slots_++;
66 }
67
IsCurrentArgExplicit()68 bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
69 // Static methods have no implicit arguments, others implicitly pass this
70 return IsStatic() || (itr_args_ != 0);
71 }
72
IsCurrentArgPossiblyNull()73 bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
74 return IsCurrentArgExplicit(); // any user parameter may be null
75 }
76
CurrentParamSize()77 size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
78 return ParamSize(itr_args_);
79 }
80
IsCurrentParamAReference()81 bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
82 return IsParamAReference(itr_args_);
83 }
84
85 // JNI calling convention
86
Create(bool is_static,bool is_synchronized,const char * shorty,InstructionSet instruction_set)87 JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
88 const char* shorty,
89 InstructionSet instruction_set) {
90 switch (instruction_set) {
91 case kArm:
92 case kThumb2:
93 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
94 case kMips:
95 return new mips::MipsJniCallingConvention(is_static, is_synchronized, shorty);
96 case kX86:
97 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
98 default:
99 LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
100 return NULL;
101 }
102 }
103
ReferenceCount() const104 size_t JniCallingConvention::ReferenceCount() const {
105 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
106 }
107
SavedLocalReferenceCookieOffset() const108 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
109 size_t start_of_sirt = SirtLinkOffset().Int32Value() + kPointerSize;
110 size_t references_size = kPointerSize * ReferenceCount(); // size excluding header
111 return FrameOffset(start_of_sirt + references_size);
112 }
113
ReturnValueSaveLocation() const114 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
115 // Segment state is 4 bytes long
116 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
117 }
118
HasNext()119 bool JniCallingConvention::HasNext() {
120 if (itr_args_ <= kObjectOrClass) {
121 return true;
122 } else {
123 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
124 return arg_pos < NumArgs();
125 }
126 }
127
Next()128 void JniCallingConvention::Next() {
129 CHECK(HasNext());
130 if (itr_args_ > kObjectOrClass) {
131 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
132 if (IsParamALongOrDouble(arg_pos)) {
133 itr_longs_and_doubles_++;
134 itr_slots_++;
135 }
136 }
137 if (IsCurrentParamAReference()) {
138 itr_refs_++;
139 }
140 itr_args_++;
141 itr_slots_++;
142 }
143
IsCurrentParamAReference()144 bool JniCallingConvention::IsCurrentParamAReference() {
145 switch (itr_args_) {
146 case kJniEnv:
147 return false; // JNIEnv*
148 case kObjectOrClass:
149 return true; // jobject or jclass
150 default: {
151 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
152 return IsParamAReference(arg_pos);
153 }
154 }
155 }
156
157 // Return position of SIRT entry holding reference at the current iterator
158 // position
CurrentParamSirtEntryOffset()159 FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
160 CHECK(IsCurrentParamAReference());
161 CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset());
162 // Address of 1st SIRT entry
163 int result = SirtLinkOffset().Int32Value() + kPointerSize;
164 result += itr_refs_ * kPointerSize;
165 CHECK_GT(result, SirtLinkOffset().Int32Value());
166 return FrameOffset(result);
167 }
168
CurrentParamSize()169 size_t JniCallingConvention::CurrentParamSize() {
170 if (itr_args_ <= kObjectOrClass) {
171 return kPointerSize; // JNIEnv or jobject/jclass
172 } else {
173 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
174 return ParamSize(arg_pos);
175 }
176 }
177
NumberOfExtraArgumentsForJni()178 size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
179 // The first argument is the JNIEnv*.
180 // Static methods have an extra argument which is the jclass.
181 return IsStatic() ? 2 : 1;
182 }
183
184 } // namespace art
185