blob: e21b317a55f1b324f4b274590c5cbe83c459aac4 [file] [log] [blame]
Ian Rogersb033c752011-07-20 12:22:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2// Author: irogers@google.com (Ian Rogers)
3
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07004#include "calling_convention.h"
5#include "logging.h"
6#include "utils.h"
Ian Rogersb033c752011-07-20 12:22:35 -07007
8namespace art {
9
Carl Shapiroe2d373e2011-07-25 15:20:06 -070010// Offset of Method within the frame
11FrameOffset CallingConvention::MethodStackOffset() {
12 return displacement_;
13}
14
Ian Rogersdf20fe02011-07-20 20:34:16 -070015// Managed runtime calling convention
16
Ian Rogersb033c752011-07-20 12:22:35 -070017size_t ManagedRuntimeCallingConvention::FrameSize() {
Elliott Hughes53b61312011-08-12 18:28:20 -070018 UNIMPLEMENTED(FATAL);
Ian Rogersb033c752011-07-20 12:22:35 -070019 return 0;
20}
21
22bool ManagedRuntimeCallingConvention::HasNext() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070023 return itr_args_ < GetMethod()->NumArgs();
Ian Rogersb033c752011-07-20 12:22:35 -070024}
25
26void ManagedRuntimeCallingConvention::Next() {
27 CHECK(HasNext());
Shih-wei Liao5381cf92011-07-27 00:28:04 -070028 if (IsCurrentUserArg() &&
29 GetMethod()->IsParamALongOrDouble(itr_args_)) {
Ian Rogersb033c752011-07-20 12:22:35 -070030 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070031 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070032 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -070033 itr_args_++;
34 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070035}
36
Shih-wei Liao5381cf92011-07-27 00:28:04 -070037bool ManagedRuntimeCallingConvention::IsCurrentUserArg() {
38 if (GetMethod()->IsStatic()) {
39 return true;
40 }
41 // For a virtual method, "this" should never be NULL.
42 return (itr_args_ != 0);
Ian Rogersb033c752011-07-20 12:22:35 -070043}
44
Ian Rogersdf20fe02011-07-20 20:34:16 -070045size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070046 return GetMethod()->ParamSize(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070047}
48
49bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070050 return GetMethod()->IsParamAReference(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070051}
52
Ian Rogersdf20fe02011-07-20 20:34:16 -070053// JNI calling convention
Ian Rogersb033c752011-07-20 12:22:35 -070054
55size_t JniCallingConvention::FrameSize() {
56 // Return address and Method*
57 size_t frame_data_size = 2 * kPointerSize;
58 // Handles plus 2 words for SHB header
59 size_t handle_area_size = (HandleCount() + 2) * kPointerSize;
Ian Rogersdf20fe02011-07-20 20:34:16 -070060 return RoundUp(frame_data_size + handle_area_size + SizeOfReturnValue(), 16);
Ian Rogersb033c752011-07-20 12:22:35 -070061}
62
63size_t JniCallingConvention::OutArgSize() {
64 return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, 16);
65}
66
67size_t JniCallingConvention::HandleCount() {
68 const Method* method = GetMethod();
69 return method->NumReferenceArgs() + (method->IsStatic() ? 1 : 0);
70}
71
Ian Rogersdf20fe02011-07-20 20:34:16 -070072FrameOffset JniCallingConvention::ReturnValueSaveLocation() {
73 size_t start_of_shb = ShbLinkOffset().Int32Value() + kPointerSize;
74 size_t handle_size = kPointerSize * HandleCount(); // size excluding header
75 return FrameOffset(start_of_shb + handle_size);
76}
77
Ian Rogersb033c752011-07-20 12:22:35 -070078bool JniCallingConvention::HasNext() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070079 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -070080 return true;
81 } else {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070082 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersb033c752011-07-20 12:22:35 -070083 return arg_pos < GetMethod()->NumArgs();
84 }
85}
86
87void JniCallingConvention::Next() {
88 CHECK(HasNext());
Shih-wei Liao5381cf92011-07-27 00:28:04 -070089 if (itr_args_ > kObjectOrClass) {
90 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersb033c752011-07-20 12:22:35 -070091 if (GetMethod()->IsParamALongOrDouble(arg_pos)) {
92 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070093 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070094 }
95 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -070096 itr_args_++;
97 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070098}
99
100bool JniCallingConvention::IsCurrentParamAReference() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700101 switch (itr_args_) {
Ian Rogersb033c752011-07-20 12:22:35 -0700102 case kJniEnv:
103 return false; // JNIEnv*
104 case kObjectOrClass:
105 return true; // jobject or jclass
106 default: {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700107 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersb033c752011-07-20 12:22:35 -0700108 return GetMethod()->IsParamAReference(arg_pos);
109 }
110 }
111}
112
113// Return position of handle holding reference at the current iterator position
114FrameOffset JniCallingConvention::CurrentParamHandleOffset() {
115 CHECK(IsCurrentParamAReference());
116 CHECK_GT(ShbLinkOffset(), ShbNumRefsOffset());
117 // Address of 1st handle
118 int result = ShbLinkOffset().Int32Value() + kPointerSize;
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700119 if (itr_args_ != kObjectOrClass) {
120 const Method *method = GetMethod();
121 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method);
Ian Rogersb033c752011-07-20 12:22:35 -0700122 int previous_refs = GetMethod()->NumReferenceArgsBefore(arg_pos);
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700123 if (method->IsStatic()) {
Ian Rogersb033c752011-07-20 12:22:35 -0700124 previous_refs++; // account for jclass
125 }
126 result += previous_refs * kPointerSize;
127 }
128 CHECK_GT(result, ShbLinkOffset().Int32Value());
129 return FrameOffset(result);
130}
131
Ian Rogersdf20fe02011-07-20 20:34:16 -0700132size_t JniCallingConvention::CurrentParamSize() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700133 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -0700134 return kPointerSize; // JNIEnv or jobject/jclass
135 } else {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700136 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700137 return GetMethod()->ParamSize(arg_pos);
Ian Rogersb033c752011-07-20 12:22:35 -0700138 }
139}
140
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700141size_t JniCallingConvention::NumberOfExtraArgumentsForJni(
142 const Method* method) {
143 // The first argument is the JNIEnv*.
144 // Static methods have an extra argument which is the jclass.
145 return (method->IsStatic() ? 2 : 1);
146}
147
Ian Rogersb033c752011-07-20 12:22:35 -0700148} // namespace art