blob: 49b43485532f61e0d4998ab2db04248e51748835 [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"
Ian Rogers2c8f6532011-09-02 17:16:34 -07004
5#include "calling_convention_arm.h"
6#include "calling_convention_x86.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07007#include "logging.h"
8#include "utils.h"
Ian Rogersb033c752011-07-20 12:22:35 -07009
10namespace art {
11
Carl Shapiroe2d373e2011-07-25 15:20:06 -070012// Offset of Method within the frame
13FrameOffset CallingConvention::MethodStackOffset() {
14 return displacement_;
15}
16
Ian Rogersdf20fe02011-07-20 20:34:16 -070017// Managed runtime calling convention
18
Ian Rogers2c8f6532011-09-02 17:16:34 -070019ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
20 Method* native_method, InstructionSet instruction_set) {
21 if (instruction_set == kX86) {
22 return new x86::X86ManagedRuntimeCallingConvention(native_method);
23 } else {
24 CHECK(instruction_set == kArm || instruction_set == kThumb2);
25 return new arm::ArmManagedRuntimeCallingConvention(native_method);
26 }
27}
28
Ian Rogersb033c752011-07-20 12:22:35 -070029size_t ManagedRuntimeCallingConvention::FrameSize() {
Ian Rogers2c8f6532011-09-02 17:16:34 -070030 return GetMethod()->GetFrameSizeInBytes();
Ian Rogersb033c752011-07-20 12:22:35 -070031}
32
33bool ManagedRuntimeCallingConvention::HasNext() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070034 return itr_args_ < GetMethod()->NumArgs();
Ian Rogersb033c752011-07-20 12:22:35 -070035}
36
37void ManagedRuntimeCallingConvention::Next() {
38 CHECK(HasNext());
Ian Rogers7a99c112011-09-07 12:48:27 -070039 if (IsCurrentArgExplicit() && // don't query parameter type of implicit args
Shih-wei Liao5381cf92011-07-27 00:28:04 -070040 GetMethod()->IsParamALongOrDouble(itr_args_)) {
Ian Rogersb033c752011-07-20 12:22:35 -070041 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070042 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070043 }
Shih-wei Liao668512a2011-09-01 14:18:34 -070044 if (IsCurrentParamAReference()) {
45 itr_refs_++;
46 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -070047 itr_args_++;
48 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -070049}
50
Ian Rogers7a99c112011-09-07 12:48:27 -070051bool ManagedRuntimeCallingConvention::IsCurrentArgExplicit() {
52 // Static methods have no implicit arguments, others implicitly pass this
53 return GetMethod()->IsStatic() || (itr_args_ != 0);
54}
55
56bool ManagedRuntimeCallingConvention::IsCurrentArgPossiblyNull() {
57 return IsCurrentArgExplicit(); // any user parameter may be null
Ian Rogersb033c752011-07-20 12:22:35 -070058}
59
Ian Rogersdf20fe02011-07-20 20:34:16 -070060size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070061 return GetMethod()->ParamSize(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070062}
63
64bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070065 return GetMethod()->IsParamAReference(itr_args_);
Ian Rogersb033c752011-07-20 12:22:35 -070066}
67
Ian Rogersdf20fe02011-07-20 20:34:16 -070068// JNI calling convention
Ian Rogersb033c752011-07-20 12:22:35 -070069
Ian Rogers2c8f6532011-09-02 17:16:34 -070070JniCallingConvention* JniCallingConvention::Create(Method* native_method,
71 InstructionSet instruction_set) {
72 if (instruction_set == kX86) {
73 return new x86::X86JniCallingConvention(native_method);
74 } else {
75 CHECK(instruction_set == kArm || instruction_set == kThumb2);
76 return new arm::ArmJniCallingConvention(native_method);
77 }
78}
79
Ian Rogers408f79a2011-08-23 18:22:33 -070080size_t JniCallingConvention::ReferenceCount() {
Ian Rogersb033c752011-07-20 12:22:35 -070081 const Method* method = GetMethod();
82 return method->NumReferenceArgs() + (method->IsStatic() ? 1 : 0);
83}
84
Ian Rogersdf20fe02011-07-20 20:34:16 -070085FrameOffset JniCallingConvention::ReturnValueSaveLocation() {
Ian Rogers408f79a2011-08-23 18:22:33 -070086 size_t start_of_sirt = SirtLinkOffset().Int32Value() + kPointerSize;
87 size_t references_size = kPointerSize * ReferenceCount(); // size excluding header
88 return FrameOffset(start_of_sirt + references_size);
Ian Rogersdf20fe02011-07-20 20:34:16 -070089}
90
Ian Rogersb033c752011-07-20 12:22:35 -070091bool JniCallingConvention::HasNext() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070092 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -070093 return true;
94 } else {
Shih-wei Liao5381cf92011-07-27 00:28:04 -070095 unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersb033c752011-07-20 12:22:35 -070096 return arg_pos < GetMethod()->NumArgs();
97 }
98}
99
100void JniCallingConvention::Next() {
101 CHECK(HasNext());
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700102 if (itr_args_ > kObjectOrClass) {
103 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersb033c752011-07-20 12:22:35 -0700104 if (GetMethod()->IsParamALongOrDouble(arg_pos)) {
105 itr_longs_and_doubles_++;
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700106 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -0700107 }
108 }
Shih-wei Liao668512a2011-09-01 14:18:34 -0700109 if (IsCurrentParamAReference()) {
110 itr_refs_++;
111 }
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700112 itr_args_++;
113 itr_slots_++;
Ian Rogersb033c752011-07-20 12:22:35 -0700114}
115
116bool JniCallingConvention::IsCurrentParamAReference() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700117 switch (itr_args_) {
Ian Rogersb033c752011-07-20 12:22:35 -0700118 case kJniEnv:
119 return false; // JNIEnv*
120 case kObjectOrClass:
121 return true; // jobject or jclass
122 default: {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700123 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersb033c752011-07-20 12:22:35 -0700124 return GetMethod()->IsParamAReference(arg_pos);
125 }
126 }
127}
128
Ian Rogers408f79a2011-08-23 18:22:33 -0700129// Return position of SIRT entry holding reference at the current iterator
130// position
131FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
Ian Rogersb033c752011-07-20 12:22:35 -0700132 CHECK(IsCurrentParamAReference());
Ian Rogers408f79a2011-08-23 18:22:33 -0700133 CHECK_GT(SirtLinkOffset(), SirtNumRefsOffset());
134 // Address of 1st SIRT entry
135 int result = SirtLinkOffset().Int32Value() + kPointerSize;
Shih-wei Liao668512a2011-09-01 14:18:34 -0700136 result += itr_refs_ * kPointerSize;
Ian Rogers408f79a2011-08-23 18:22:33 -0700137 CHECK_GT(result, SirtLinkOffset().Int32Value());
Ian Rogersb033c752011-07-20 12:22:35 -0700138 return FrameOffset(result);
139}
140
Ian Rogersdf20fe02011-07-20 20:34:16 -0700141size_t JniCallingConvention::CurrentParamSize() {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700142 if (itr_args_ <= kObjectOrClass) {
Ian Rogersb033c752011-07-20 12:22:35 -0700143 return kPointerSize; // JNIEnv or jobject/jclass
144 } else {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700145 int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
Ian Rogersdf20fe02011-07-20 20:34:16 -0700146 return GetMethod()->ParamSize(arg_pos);
Ian Rogersb033c752011-07-20 12:22:35 -0700147 }
148}
149
Ian Rogers2c8f6532011-09-02 17:16:34 -0700150size_t JniCallingConvention::NumberOfExtraArgumentsForJni(Method* method) {
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700151 // The first argument is the JNIEnv*.
152 // Static methods have an extra argument which is the jclass.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700153 return method->IsStatic() ? 2 : 1;
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700154}
155
Ian Rogersb033c752011-07-20 12:22:35 -0700156} // namespace art