blob: 512483edab7a39efd6c73715ef6bdc887b4caac1 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Ian Rogersb033c752011-07-20 12:22:35 -070016
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070017#include "calling_convention.h"
Ian Rogers2c8f6532011-09-02 17:16:34 -070018
Elliott Hughes07ed66b2012-12-12 18:34:25 -080019#include "base/logging.h"
Ian Rogers02113782013-03-04 12:12:48 -080020#include "compiler/jni/quick/arm/calling_convention_arm.h"
21#include "compiler/jni/quick/mips/calling_convention_mips.h"
22#include "compiler/jni/quick/x86/calling_convention_x86.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070023#include "utils.h"
Ian Rogersb033c752011-07-20 12:22:35 -070024
25namespace art {
26
Carl Shapiroe2d373e2011-07-25 15:20:06 -070027// Offset of Method within the frame
28FrameOffset CallingConvention::MethodStackOffset() {
29 return displacement_;
30}
31
Ian Rogersdf20fe02011-07-20 20:34:16 -070032// Managed runtime calling convention
33
Ian Rogers2c8f6532011-09-02 17:16:34 -070034ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
Ian Rogers169c9a72011-11-13 20:13:17 -080035 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
jeffhao7fbee072012-08-24 17:56:54 -070036 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;
Ian Rogers2c8f6532011-09-02 17:16:34 -070047 }
48}
49
Ian Rogersb033c752011-07-20 12:22:35 -070050bool ManagedRuntimeCallingConvention::HasNext() {
Ian Rogers169c9a72011-11-13 20:13:17 -080051 return itr_args_ < NumArgs();
Ian Rogersb033c752011-07-20 12:22:35 -070052}
53
54void ManagedRuntimeCallingConvention::Next() {
55 CHECK(HasNext());
Ian Rogers7a99c112011-09-07 12:48:27 -070056 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args
Ian Rogers169c9a72011-11-13 20:13:17 -080057 IsParamALongOrDouble(itr_args_)) {
Ian Rogersb033c752011-07-20 12:22:35 -070058 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070059 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070060 }
Shih-wei Liao668512a2011-09-01 14:18:34 -070061 if (IsCurrentParamAReference()) {
62 itr_refs_++;
63 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -070064 itr_args_++;
65 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070066}
67
Ian Rogers7a99c112011-09-07 12:48:27 -070068bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
69 // Static methods have no implicit arguments, others implicitly pass this
Ian Rogers169c9a72011-11-13 20:13:17 -080070 return IsStatic() || (itr_args_ != 0);
Ian Rogers7a99c112011-09-07 12:48:27 -070071}
72
73bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
74 return IsCurrentArgExplicit(); // any user parameter may be null
Ian Rogersb033c752011-07-20 12:22:35 -070075}
76
Ian Rogersdf20fe02011-07-20 20:34:16 -070077size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
Ian Rogers169c9a72011-11-13 20:13:17 -080078 return ParamSize(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070079}
80
81bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
Ian Rogers169c9a72011-11-13 20:13:17 -080082 return IsParamAReference(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070083}
84
Ian Rogersdf20fe02011-07-20 20:34:16 -070085// JNI calling convention
Ian Rogersb033c752011-07-20 12:22:35 -070086
Ian Rogers169c9a72011-11-13 20:13:17 -080087JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
88 const char* shorty,
89 InstructionSet instruction_set) {
jeffhao7fbee072012-08-24 17:56:54 -070090 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;
Ian Rogers2c8f6532011-09-02 17:16:34 -0700101 }
102}
103
Ian Rogersdc51b792011-09-22 20:41:37 -0700104size_t JniCallingConvention::ReferenceCount() const {
Ian Rogers169c9a72011-11-13 20:13:17 -0800105 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
Ian Rogersb033c752011-07-20 12:22:35 -0700106}
107
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700108FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
Ian Rogers408f79a2011-08-23 18:22:33 -0700109 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);
Ian Rogersdf20fe02011-07-20 20:34:16 -0700112}
113
Ian Rogersdc51b792011-09-22 20:41:37 -0700114FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
115 // Segment state is 4 bytes long
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700116 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
Ian Rogersdc51b792011-09-22 20:41:37 -0700117}
118
Ian Rogersb033c752011-07-20 12:22:35 -0700119bool JniCallingConvention::HasNext() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700120 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -0700121 return true;
122 } else {
Ian Rogers169c9a72011-11-13 20:13:17 -0800123 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
124 return arg_pos < NumArgs();
Ian Rogersb033c752011-07-20 12:22:35 -0700125 }
126}
127
128void JniCallingConvention::Next() {
129 CHECK(HasNext());
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700130 if (itr_args_ > kObjectOrClass) {
Ian Rogers169c9a72011-11-13 20:13:17 -0800131 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
132 if (IsParamALongOrDouble(arg_pos)) {
Ian Rogersb033c752011-07-20 12:22:35 -0700133 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700134 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -0700135 }
136 }
Shih-wei Liao668512a2011-09-01 14:18:34 -0700137 if (IsCurrentParamAReference()) {
138 itr_refs_++;
139 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700140 itr_args_++;
141 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -0700142}
143
144bool JniCallingConvention::IsCurrentParamAReference() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700145 switch (itr_args_) {
Ian Rogersb033c752011-07-20 12:22:35 -0700146 case kJniEnv:
147 return false; // JNIEnv*
148 case kObjectOrClass:
149 return true; // jobject or jclass
150 default: {
Ian Rogers169c9a72011-11-13 20:13:17 -0800151 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
152 return IsParamAReference(arg_pos);
Ian Rogersb033c752011-07-20 12:22:35 -0700153 }
154 }
155}
156
Ian Rogers408f79a2011-08-23 18:22:33 -0700157// Return position of SIRT entry holding reference at the current iterator
158// position
159FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
Ian Rogersb033c752011-07-20 12:22:35 -0700160 CHECK(IsCurrentParamAReference());
Ian Rogers408f79a2011-08-23 18:22:33 -0700161 CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset());
162 // Address of 1st SIRT entry
163 int result = SirtLinkOffset().Int32Value() + kPointerSize;
Shih-wei Liao668512a2011-09-01 14:18:34 -0700164 result += itr_refs_ * kPointerSize;
Ian Rogers408f79a2011-08-23 18:22:33 -0700165 CHECK_GT(result, SirtLinkOffset().Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -0700166 return FrameOffset(result);
167}
168
Ian Rogersdf20fe02011-07-20 20:34:16 -0700169size_t JniCallingConvention::CurrentParamSize() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700170 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -0700171 return kPointerSize; // JNIEnv or jobject/jclass
172 } else {
Ian Rogers169c9a72011-11-13 20:13:17 -0800173 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
174 return ParamSize(arg_pos);
Ian Rogersb033c752011-07-20 12:22:35 -0700175 }
176}
177
Ian Rogers169c9a72011-11-13 20:13:17 -0800178size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700179 // The first argument is the JNIEnv*.
180 // Static methods have an extra argument which is the jclass.
Ian Rogers169c9a72011-11-13 20:13:17 -0800181 return IsStatic() ? 2 : 1;
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700182}
183
Ian Rogersb033c752011-07-20 12:22:35 -0700184} // namespace art