blob: 12dab2e8a8c8c68d83225168330bb338e537ae47 [file] [log] [blame]
Ian Rogersb033c752011-07-20 12:22:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
Ian Rogersb033c752011-07-20 12:22:35 -07002
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "calling_convention.h"
4#include "logging.h"
5#include "utils.h"
Ian Rogersb033c752011-07-20 12:22:35 -07006
7namespace art {
8
Carl Shapiroe2d373e2011-07-25 15:20:06 -07009// Offset of Method within the frame
10FrameOffset CallingConvention::MethodStackOffset() {
11 return displacement_;
12}
13
Ian Rogersdf20fe02011-07-20 20:34:16 -070014// Managed runtime calling convention
15
Ian Rogersb033c752011-07-20 12:22:35 -070016size_t ManagedRuntimeCallingConvention::FrameSize() {
Elliott Hughes53b61312011-08-12 18:28:20 -070017 UNIMPLEMENTED(FATAL);
Ian Rogersb033c752011-07-20 12:22:35 -070018 return 0;
19}
20
21bool ManagedRuntimeCallingConvention::HasNext() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070022 return itr_args_ < GetMethod()->NumArgs();
Ian Rogersb033c752011-07-20 12:22:35 -070023}
24
25void ManagedRuntimeCallingConvention::Next() {
26 CHECK(HasNext());
Brian Carlstroma663ea52011-08-19 23:33:41 -070027 if (IsCurrentUserArg() &&
Shih-wei Liao5381cf92011-07-27 00:28:04 -070028 GetMethod()->IsParamALongOrDouble(itr_args_)) {
Ian Rogersb033c752011-07-20 12:22:35 -070029 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070030 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070031 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -070032 itr_args_++;
33 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070034}
35
Shih-wei Liao5381cf92011-07-27 00:28:04 -070036bool ManagedRuntimeCallingConvention::IsCurrentUserArg() {
37 if (GetMethod()->IsStatic()) {
38 return true;
39 }
40 // For a virtual method, "this" should never be NULL.
41 return (itr_args_ != 0);
Ian Rogersb033c752011-07-20 12:22:35 -070042}
43
Ian Rogersdf20fe02011-07-20 20:34:16 -070044size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070045 return GetMethod()->ParamSize(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070046}
47
48bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070049 return GetMethod()->IsParamAReference(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070050}
51
Ian Rogersdf20fe02011-07-20 20:34:16 -070052// JNI calling convention
Ian Rogersb033c752011-07-20 12:22:35 -070053
Ian Rogersb033c752011-07-20 12:22:35 -070054size_t JniCallingConvention::OutArgSize() {
Ian Rogers408f79a2011-08-23 18:22:33 -070055 return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, kStackAlignment);
Ian Rogersb033c752011-07-20 12:22:35 -070056}
57
Ian Rogers408f79a2011-08-23 18:22:33 -070058size_t JniCallingConvention::ReferenceCount() {
Ian Rogersb033c752011-07-20 12:22:35 -070059 const Method* method = GetMethod();
60 return method->NumReferenceArgs() + (method->IsStatic() ? 1 : 0);
61}
62
Ian Rogersdf20fe02011-07-20 20:34:16 -070063FrameOffset JniCallingConvention::ReturnValueSaveLocation() {
Ian Rogers408f79a2011-08-23 18:22:33 -070064 size_t start_of_sirt = SirtLinkOffset().Int32Value() + kPointerSize;
65 size_t references_size = kPointerSize * ReferenceCount(); // size excluding header
66 return FrameOffset(start_of_sirt + references_size);
Ian Rogersdf20fe02011-07-20 20:34:16 -070067}
68
Ian Rogersb033c752011-07-20 12:22:35 -070069bool JniCallingConvention::HasNext() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070070 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -070071 return true;
72 } else {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070073 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersb033c752011-07-20 12:22:35 -070074 return arg_pos < GetMethod()->NumArgs();
75 }
76}
77
78void JniCallingConvention::Next() {
79 CHECK(HasNext());
Shih-wei Liao5381cf92011-07-27 00:28:04 -070080 if (itr_args_ > kObjectOrClass) {
81 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersb033c752011-07-20 12:22:35 -070082 if (GetMethod()->IsParamALongOrDouble(arg_pos)) {
83 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070084 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070085 }
86 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -070087 itr_args_++;
88 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070089}
90
91bool JniCallingConvention::IsCurrentParamAReference() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070092 switch (itr_args_) {
Ian Rogersb033c752011-07-20 12:22:35 -070093 case kJniEnv:
94 return false; // JNIEnv*
95 case kObjectOrClass:
96 return true; // jobject or jclass
97 default: {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070098 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersb033c752011-07-20 12:22:35 -070099 return GetMethod()->IsParamAReference(arg_pos);
100 }
101 }
102}
103
Ian Rogers408f79a2011-08-23 18:22:33 -0700104// Return position of SIRT entry holding reference at the current iterator
105// position
106FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
Ian Rogersb033c752011-07-20 12:22:35 -0700107 CHECK(IsCurrentParamAReference());
Ian Rogers408f79a2011-08-23 18:22:33 -0700108 CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset());
109 // Address of 1st SIRT entry
110 int result = SirtLinkOffset().Int32Value() + kPointerSize;
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700111 if (itr_args_ != kObjectOrClass) {
112 const Method *method = GetMethod();
113 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method);
Ian Rogersb033c752011-07-20 12:22:35 -0700114 int previous_refs = GetMethod()->NumReferenceArgsBefore(arg_pos);
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700115 if (method->IsStatic()) {
Ian Rogersb033c752011-07-20 12:22:35 -0700116 previous_refs++; // account for jclass
117 }
118 result += previous_refs * kPointerSize;
119 }
Ian Rogers408f79a2011-08-23 18:22:33 -0700120 CHECK_GT(result, SirtLinkOffset().Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -0700121 return FrameOffset(result);
122}
123
Ian Rogersdf20fe02011-07-20 20:34:16 -0700124size_t JniCallingConvention::CurrentParamSize() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700125 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -0700126 return kPointerSize; // JNIEnv or jobject/jclass
127 } else {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700128 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700129 return GetMethod()->ParamSize(arg_pos);
Ian Rogersb033c752011-07-20 12:22:35 -0700130 }
131}
132
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700133size_t JniCallingConvention::NumberOfExtraArgumentsForJni(
134 const Method* method) {
135 // The first argument is the JNIEnv*.
136 // Static methods have an extra argument which is the jclass.
137 return (method->IsStatic() ? 2 : 1);
138}
139
Ian Rogersb033c752011-07-20 12:22:35 -0700140} // namespace art