blob: 3b773d6cc8c4253e12833cb8a673c4adbb43ed11 [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
3#ifndef ART_SRC_CALLING_CONVENTION_H_
4#define ART_SRC_CALLING_CONVENTION_H_
5
Ian Rogers0d666d82011-08-14 16:03:46 -07006#include <vector>
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07007#include "managed_register.h"
8#include "object.h"
9#include "thread.h"
Ian Rogersb033c752011-07-20 12:22:35 -070010
11namespace art {
12
13// Top-level abstraction for different calling conventions
14class CallingConvention {
15 public:
16 CallingConvention* GetCallingConvention(Method* method);
17
18 bool IsReturnAReference() const { return method_->IsReturnAReference(); }
19
Ian Rogersdf20fe02011-07-20 20:34:16 -070020 size_t SizeOfReturnValue() const { return method_->ReturnSize(); }
21
Ian Rogersb033c752011-07-20 12:22:35 -070022 // Register that holds the incoming method argument
23 ManagedRegister MethodRegister();
24 // Register that holds result of this method
25 ManagedRegister ReturnRegister();
26 // Register reserved for scratch usage during procedure calls
27 ManagedRegister InterproceduralScratchRegister();
28
Shih-wei Liao668512a2011-09-01 14:18:34 -070029 ManagedRegister ThreadRegister();
30
Carl Shapiroe2d373e2011-07-25 15:20:06 -070031 // Offset of Method within the frame
32 FrameOffset MethodStackOffset();
33
Ian Rogersb033c752011-07-20 12:22:35 -070034 // Iterator interface
35
36 // Place iterator at start of arguments. The displacement is applied to
37 // frame offset methods to account for frames which may be on the stack
38 // below the one being iterated over.
39 void ResetIterator(FrameOffset displacement) {
40 displacement_ = displacement;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070041 itr_slots_ = 0;
42 itr_args_ = 0;
Shih-wei Liao668512a2011-09-01 14:18:34 -070043 itr_refs_ = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070044 itr_longs_and_doubles_ = 0;
45 }
46
47 protected:
48 explicit CallingConvention(Method* method) : displacement_(0),
49 method_(method) {}
50 const Method* GetMethod() const { return method_; }
51
Shih-wei Liao5381cf92011-07-27 00:28:04 -070052 // The slot number for current calling_convention argument.
53 // Note that each slot is 32-bit. When the current argument is bigger
54 // than 32 bits, return the first slot number for this argument.
55 unsigned int itr_slots_;
Ian Rogers7a99c112011-09-07 12:48:27 -070056 // The number of references iterated past
57 unsigned int itr_refs_;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070058 // The argument number along argument list for current argument
59 unsigned int itr_args_;
60 // Number of longs and doubles seen along argument list
Ian Rogersb033c752011-07-20 12:22:35 -070061 unsigned int itr_longs_and_doubles_;
62 // Space for frames below this on the stack
63 FrameOffset displacement_;
64
65 private:
66 const Method* method_;
67};
68
69// Abstraction for managed code's calling conventions
70class ManagedRuntimeCallingConvention : public CallingConvention {
71 public:
72 explicit ManagedRuntimeCallingConvention(Method* method) :
73 CallingConvention(method) {}
74
75 size_t FrameSize();
76
77 // Iterator interface
78 bool HasNext();
79 void Next();
80 bool IsCurrentParamAReference();
81 bool IsCurrentParamInRegister();
82 bool IsCurrentParamOnStack();
Ian Rogers7a99c112011-09-07 12:48:27 -070083 bool IsCurrentArgExplicit(); // ie a non-implict argument such as this
84 bool IsCurrentArgPossiblyNull();
Ian Rogersdf20fe02011-07-20 20:34:16 -070085 size_t CurrentParamSize();
Ian Rogersb033c752011-07-20 12:22:35 -070086 ManagedRegister CurrentParamRegister();
87 FrameOffset CurrentParamStackOffset();
88
89 DISALLOW_COPY_AND_ASSIGN(ManagedRuntimeCallingConvention);
90};
91
92// Abstraction for JNI calling conventions
93// | incoming stack args | <-- Prior SP
Ian Rogers0d666d82011-08-14 16:03:46 -070094// | { Return address } | (x86)
Ian Rogersdf20fe02011-07-20 20:34:16 -070095// | { Return value spill } | (live on return slow paths)
Ian Rogers408f79a2011-08-23 18:22:33 -070096// | { Stack Indirect Ref. |
97// | Table... |
Ian Rogersdf20fe02011-07-20 20:34:16 -070098// | num. refs./link } | (here to prior SP is frame size)
Ian Rogers0d666d82011-08-14 16:03:46 -070099// | { Spill area } | (ARM)
Ian Rogersb033c752011-07-20 12:22:35 -0700100// | Method* | <-- Anchor SP written to thread
101// | { Outgoing stack args |
102// | ... } | <-- SP at point of call
103// | Native frame |
104class JniCallingConvention : public CallingConvention {
105 public:
Elliott Hughes90a33692011-08-30 13:27:07 -0700106 explicit JniCallingConvention(Method* native_method)
107 : CallingConvention(native_method) {
108 ComputeRegsToSpillPreCall(spill_regs_);
109 }
Ian Rogersb033c752011-07-20 12:22:35 -0700110
111 // Size of frame excluding space for outgoing args (its assumed Method* is
112 // always at the bottom of a frame, but this doesn't work for outgoing
113 // native args). Includes alignment.
114 size_t FrameSize();
Ian Rogers762400c2011-08-23 12:14:16 -0700115 // Offset within the frame of the return pc
116 size_t ReturnPcOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700117 // Size of outgoing arguments, including alignment
118 size_t OutArgSize();
Ian Rogers408f79a2011-08-23 18:22:33 -0700119 // Number of references in stack indirect reference table
120 size_t ReferenceCount();
Ian Rogers0d666d82011-08-14 16:03:46 -0700121 // Size of area used to hold spilled registers
122 size_t SpillAreaSize();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700123 // Location where the return value of a call can be squirreled if another
124 // call is made following the native call
125 FrameOffset ReturnValueSaveLocation();
Ian Rogersb033c752011-07-20 12:22:35 -0700126
Ian Rogers0d666d82011-08-14 16:03:46 -0700127 // Registers that must be spilled (due to clobbering) before the call into
128 // the native routine
129 const std::vector<ManagedRegister>& RegsToSpillPreCall() {
Elliott Hughes90a33692011-08-30 13:27:07 -0700130 return spill_regs_;
Ian Rogers0d666d82011-08-14 16:03:46 -0700131 }
132
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700133 // Returns true if the register will be clobbered by an outgoing
134 // argument value.
135 bool IsOutArgRegister(ManagedRegister reg);
136
Ian Rogersb033c752011-07-20 12:22:35 -0700137 // Iterator interface
138 bool HasNext();
139 void Next();
140 bool IsCurrentParamAReference();
141 bool IsCurrentParamInRegister();
142 bool IsCurrentParamOnStack();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700143 size_t CurrentParamSize();
Ian Rogersb033c752011-07-20 12:22:35 -0700144 ManagedRegister CurrentParamRegister();
145 FrameOffset CurrentParamStackOffset();
146
147 // Iterator interface extension for JNI
Ian Rogers408f79a2011-08-23 18:22:33 -0700148 FrameOffset CurrentParamSirtEntryOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700149
Ian Rogers408f79a2011-08-23 18:22:33 -0700150 // Position of SIRT and interior fields
151 FrameOffset SirtOffset() {
Ian Rogersb033c752011-07-20 12:22:35 -0700152 return FrameOffset(displacement_.Int32Value() +
Ian Rogers0d666d82011-08-14 16:03:46 -0700153 SpillAreaSize() +
Ian Rogersb033c752011-07-20 12:22:35 -0700154 kPointerSize); // above Method*
155 }
Ian Rogers408f79a2011-08-23 18:22:33 -0700156 FrameOffset SirtNumRefsOffset() {
157 return FrameOffset(SirtOffset().Int32Value() +
158 StackIndirectReferenceTable::NumberOfReferencesOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700159 }
Ian Rogers408f79a2011-08-23 18:22:33 -0700160 FrameOffset SirtLinkOffset() {
161 return FrameOffset(SirtOffset().Int32Value() +
162 StackIndirectReferenceTable::LinkOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700163 }
164
165 private:
166 // Named iterator positions
167 enum IteratorPos {
168 kJniEnv = 0,
169 kObjectOrClass = 1
170 };
171
Ian Rogers408f79a2011-08-23 18:22:33 -0700172 // Number of stack slots for outgoing arguments, above which the SIRT is
Ian Rogersb033c752011-07-20 12:22:35 -0700173 // located
174 size_t NumberOfOutgoingStackArgs();
175
Ian Rogers0d666d82011-08-14 16:03:46 -0700176 // Compute registers for RegsToSpillPreCall
Elliott Hughes90a33692011-08-30 13:27:07 -0700177 void ComputeRegsToSpillPreCall(std::vector<ManagedRegister>& regs);
Ian Rogers0d666d82011-08-14 16:03:46 -0700178
179 // Extra registers to spill before the call into native
Elliott Hughes90a33692011-08-30 13:27:07 -0700180 std::vector<ManagedRegister> spill_regs_;
Ian Rogers0d666d82011-08-14 16:03:46 -0700181
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700182 static size_t NumberOfExtraArgumentsForJni(const Method* method);
Ian Rogersb033c752011-07-20 12:22:35 -0700183 DISALLOW_COPY_AND_ASSIGN(JniCallingConvention);
184};
185
186} // namespace art
187
188#endif // ART_SRC_CALLING_CONVENTION_H_