blob: e7b9cc8085f586c896b79429a82082217cc4848e [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
Ian Rogers57b86d42012-03-27 16:05:41 -070019#include "oat/jni/arm/calling_convention_arm.h"
20#include "oat/jni/x86/calling_convention_x86.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070021#include "logging.h"
22#include "utils.h"
Ian Rogersb033c752011-07-20 12:22:35 -070023
24namespace art {
25
Carl Shapiroe2d373e2011-07-25 15:20:06 -070026// Offset of Method within the frame
27FrameOffset CallingConvention::MethodStackOffset() {
28 return displacement_;
29}
30
Ian Rogersdf20fe02011-07-20 20:34:16 -070031// Managed runtime calling convention
32
Ian Rogers2c8f6532011-09-02 17:16:34 -070033ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
Ian Rogers169c9a72011-11-13 20:13:17 -080034 bool is_static, bool is_synchronized, const char* shorty, InstructionSet instruction_set) {
Ian Rogers2c8f6532011-09-02 17:16:34 -070035 if (instruction_set == kX86) {
Ian Rogers169c9a72011-11-13 20:13:17 -080036 return new x86::X86ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Ian Rogers2c8f6532011-09-02 17:16:34 -070037 } else {
38 CHECK(instruction_set == kArm || instruction_set == kThumb2);
Ian Rogers169c9a72011-11-13 20:13:17 -080039 return new arm::ArmManagedRuntimeCallingConvention(is_static, is_synchronized, shorty);
Ian Rogers2c8f6532011-09-02 17:16:34 -070040 }
41}
42
Ian Rogersb033c752011-07-20 12:22:35 -070043bool ManagedRuntimeCallingConvention::HasNext() {
Ian Rogers169c9a72011-11-13 20:13:17 -080044 return itr_args_ < NumArgs();
Ian Rogersb033c752011-07-20 12:22:35 -070045}
46
47void ManagedRuntimeCallingConvention::Next() {
48 CHECK(HasNext());
Ian Rogers7a99c112011-09-07 12:48:27 -070049 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args
Ian Rogers169c9a72011-11-13 20:13:17 -080050 IsParamALongOrDouble(itr_args_)) {
Ian Rogersb033c752011-07-20 12:22:35 -070051 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070052 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070053 }
Shih-wei Liao668512a2011-09-01 14:18:34 -070054 if (IsCurrentParamAReference()) {
55 itr_refs_++;
56 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -070057 itr_args_++;
58 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070059}
60
Ian Rogers7a99c112011-09-07 12:48:27 -070061bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
62 // Static methods have no implicit arguments, others implicitly pass this
Ian Rogers169c9a72011-11-13 20:13:17 -080063 return IsStatic() || (itr_args_ != 0);
Ian Rogers7a99c112011-09-07 12:48:27 -070064}
65
66bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
67 return IsCurrentArgExplicit(); // any user parameter may be null
Ian Rogersb033c752011-07-20 12:22:35 -070068}
69
Ian Rogersdf20fe02011-07-20 20:34:16 -070070size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
Ian Rogers169c9a72011-11-13 20:13:17 -080071 return ParamSize(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070072}
73
74bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
Ian Rogers169c9a72011-11-13 20:13:17 -080075 return IsParamAReference(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070076}
77
Ian Rogersdf20fe02011-07-20 20:34:16 -070078// JNI calling convention
Ian Rogersb033c752011-07-20 12:22:35 -070079
Ian Rogers169c9a72011-11-13 20:13:17 -080080JniCallingConvention* JniCallingConvention::Create(bool is_static, bool is_synchronized,
81 const char* shorty,
82 InstructionSet instruction_set) {
Ian Rogers2c8f6532011-09-02 17:16:34 -070083 if (instruction_set == kX86) {
Ian Rogers169c9a72011-11-13 20:13:17 -080084 return new x86::X86JniCallingConvention(is_static, is_synchronized, shorty);
Ian Rogers2c8f6532011-09-02 17:16:34 -070085 } else {
86 CHECK(instruction_set == kArm || instruction_set == kThumb2);
Ian Rogers169c9a72011-11-13 20:13:17 -080087 return new arm::ArmJniCallingConvention(is_static, is_synchronized, shorty);
Ian Rogers2c8f6532011-09-02 17:16:34 -070088 }
89}
90
Ian Rogersdc51b792011-09-22 20:41:37 -070091size_t JniCallingConvention::ReferenceCount() const {
Ian Rogers169c9a72011-11-13 20:13:17 -080092 return NumReferenceArgs() + (IsStatic() ? 1 : 0);
Ian Rogersb033c752011-07-20 12:22:35 -070093}
94
Ian Rogers5a7a74a2011-09-26 16:32:29 -070095FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
Ian Rogers408f79a2011-08-23 18:22:33 -070096 size_t start_of_sirt = SirtLinkOffset().Int32Value() + kPointerSize;
97 size_t references_size = kPointerSize * ReferenceCount(); // size excluding header
98 return FrameOffset(start_of_sirt + references_size);
Ian Rogersdf20fe02011-07-20 20:34:16 -070099}
100
Ian Rogersdc51b792011-09-22 20:41:37 -0700101FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
102 // Segment state is 4 bytes long
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700103 return FrameOffset(SavedLocalReferenceCookieOffset().Int32Value() + 4);
Ian Rogersdc51b792011-09-22 20:41:37 -0700104}
105
Ian Rogersb033c752011-07-20 12:22:35 -0700106bool JniCallingConvention::HasNext() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700107 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -0700108 return true;
109 } else {
Ian Rogers169c9a72011-11-13 20:13:17 -0800110 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
111 return arg_pos < NumArgs();
Ian Rogersb033c752011-07-20 12:22:35 -0700112 }
113}
114
115void JniCallingConvention::Next() {
116 CHECK(HasNext());
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700117 if (itr_args_ > kObjectOrClass) {
Ian Rogers169c9a72011-11-13 20:13:17 -0800118 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
119 if (IsParamALongOrDouble(arg_pos)) {
Ian Rogersb033c752011-07-20 12:22:35 -0700120 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700121 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -0700122 }
123 }
Shih-wei Liao668512a2011-09-01 14:18:34 -0700124 if (IsCurrentParamAReference()) {
125 itr_refs_++;
126 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700127 itr_args_++;
128 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -0700129}
130
131bool JniCallingConvention::IsCurrentParamAReference() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700132 switch (itr_args_) {
Ian Rogersb033c752011-07-20 12:22:35 -0700133 case kJniEnv:
134 return false; // JNIEnv*
135 case kObjectOrClass:
136 return true; // jobject or jclass
137 default: {
Ian Rogers169c9a72011-11-13 20:13:17 -0800138 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
139 return IsParamAReference(arg_pos);
Ian Rogersb033c752011-07-20 12:22:35 -0700140 }
141 }
142}
143
Ian Rogers408f79a2011-08-23 18:22:33 -0700144// Return position of SIRT entry holding reference at the current iterator
145// position
146FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
Ian Rogersb033c752011-07-20 12:22:35 -0700147 CHECK(IsCurrentParamAReference());
Ian Rogers408f79a2011-08-23 18:22:33 -0700148 CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset());
149 // Address of 1st SIRT entry
150 int result = SirtLinkOffset().Int32Value() + kPointerSize;
Shih-wei Liao668512a2011-09-01 14:18:34 -0700151 result += itr_refs_ * kPointerSize;
Ian Rogers408f79a2011-08-23 18:22:33 -0700152 CHECK_GT(result, SirtLinkOffset().Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -0700153 return FrameOffset(result);
154}
155
Ian Rogersdf20fe02011-07-20 20:34:16 -0700156size_t JniCallingConvention::CurrentParamSize() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700157 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -0700158 return kPointerSize; // JNIEnv or jobject/jclass
159 } else {
Ian Rogers169c9a72011-11-13 20:13:17 -0800160 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
161 return ParamSize(arg_pos);
Ian Rogersb033c752011-07-20 12:22:35 -0700162 }
163}
164
Ian Rogers169c9a72011-11-13 20:13:17 -0800165size_t JniCallingConvention::NumberOfExtraArgumentsForJni() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700166 // The first argument is the JNIEnv*.
167 // Static methods have an extra argument which is the jclass.
Ian Rogers169c9a72011-11-13 20:13:17 -0800168 return IsStatic() ? 2 : 1;
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700169}
170
Ian Rogersb033c752011-07-20 12:22:35 -0700171} // namespace art