blob: 7e59fd5df01218048d0079aca0da7927c794e114 [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
Carl Shapiroe2d373e2011-07-25 15:20:06 -070029 // Offset of Method within the frame
30 FrameOffset MethodStackOffset();
31
Ian Rogersb033c752011-07-20 12:22:35 -070032 // Iterator interface
33
34 // Place iterator at start of arguments. The displacement is applied to
35 // frame offset methods to account for frames which may be on the stack
36 // below the one being iterated over.
37 void ResetIterator(FrameOffset displacement) {
38 displacement_ = displacement;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070039 itr_slots_ = 0;
40 itr_args_ = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070041 itr_longs_and_doubles_ = 0;
42 }
43
44 protected:
45 explicit CallingConvention(Method* method) : displacement_(0),
46 method_(method) {}
47 const Method* GetMethod() const { return method_; }
48
Shih-wei Liao5381cf92011-07-27 00:28:04 -070049 // The slot number for current calling_convention argument.
50 // Note that each slot is 32-bit. When the current argument is bigger
51 // than 32 bits, return the first slot number for this argument.
52 unsigned int itr_slots_;
53 // The argument number along argument list for current argument
54 unsigned int itr_args_;
55 // Number of longs and doubles seen along argument list
Ian Rogersb033c752011-07-20 12:22:35 -070056 unsigned int itr_longs_and_doubles_;
57 // Space for frames below this on the stack
58 FrameOffset displacement_;
59
60 private:
61 const Method* method_;
62};
63
64// Abstraction for managed code's calling conventions
65class ManagedRuntimeCallingConvention : public CallingConvention {
66 public:
67 explicit ManagedRuntimeCallingConvention(Method* method) :
68 CallingConvention(method) {}
69
70 size_t FrameSize();
71
72 // Iterator interface
73 bool HasNext();
74 void Next();
75 bool IsCurrentParamAReference();
76 bool IsCurrentParamInRegister();
77 bool IsCurrentParamOnStack();
Shih-wei Liao5381cf92011-07-27 00:28:04 -070078 bool IsCurrentUserArg();
Ian Rogersdf20fe02011-07-20 20:34:16 -070079 size_t CurrentParamSize();
Ian Rogersb033c752011-07-20 12:22:35 -070080 ManagedRegister CurrentParamRegister();
81 FrameOffset CurrentParamStackOffset();
82
83 DISALLOW_COPY_AND_ASSIGN(ManagedRuntimeCallingConvention);
84};
85
86// Abstraction for JNI calling conventions
87// | incoming stack args | <-- Prior SP
Ian Rogers0d666d82011-08-14 16:03:46 -070088// | { Return address } | (x86)
Ian Rogersdf20fe02011-07-20 20:34:16 -070089// | { Return value spill } | (live on return slow paths)
Ian Rogers408f79a2011-08-23 18:22:33 -070090// | { Stack Indirect Ref. |
91// | Table... |
Ian Rogersdf20fe02011-07-20 20:34:16 -070092// | num. refs./link } | (here to prior SP is frame size)
Ian Rogers0d666d82011-08-14 16:03:46 -070093// | { Spill area } | (ARM)
Ian Rogersb033c752011-07-20 12:22:35 -070094// | Method* | <-- Anchor SP written to thread
95// | { Outgoing stack args |
96// | ... } | <-- SP at point of call
97// | Native frame |
98class JniCallingConvention : public CallingConvention {
99 public:
100 explicit JniCallingConvention(Method* native_method) :
Ian Rogers0d666d82011-08-14 16:03:46 -0700101 CallingConvention(native_method),
102 spill_regs_(ComputeRegsToSpillPreCall()) {}
Ian Rogersb033c752011-07-20 12:22:35 -0700103
104 // Size of frame excluding space for outgoing args (its assumed Method* is
105 // always at the bottom of a frame, but this doesn't work for outgoing
106 // native args). Includes alignment.
107 size_t FrameSize();
Ian Rogers762400c2011-08-23 12:14:16 -0700108 // Offset within the frame of the return pc
109 size_t ReturnPcOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700110 // Size of outgoing arguments, including alignment
111 size_t OutArgSize();
Ian Rogers408f79a2011-08-23 18:22:33 -0700112 // Number of references in stack indirect reference table
113 size_t ReferenceCount();
Ian Rogers0d666d82011-08-14 16:03:46 -0700114 // Size of area used to hold spilled registers
115 size_t SpillAreaSize();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700116 // Location where the return value of a call can be squirreled if another
117 // call is made following the native call
118 FrameOffset ReturnValueSaveLocation();
Ian Rogersb033c752011-07-20 12:22:35 -0700119
Ian Rogers0d666d82011-08-14 16:03:46 -0700120 // Registers that must be spilled (due to clobbering) before the call into
121 // the native routine
122 const std::vector<ManagedRegister>& RegsToSpillPreCall() {
123 return *spill_regs_.get();
124 }
125
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700126 // Returns true if the register will be clobbered by an outgoing
127 // argument value.
128 bool IsOutArgRegister(ManagedRegister reg);
129
Ian Rogersb033c752011-07-20 12:22:35 -0700130 // Iterator interface
131 bool HasNext();
132 void Next();
133 bool IsCurrentParamAReference();
134 bool IsCurrentParamInRegister();
135 bool IsCurrentParamOnStack();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700136 size_t CurrentParamSize();
Ian Rogersb033c752011-07-20 12:22:35 -0700137 ManagedRegister CurrentParamRegister();
138 FrameOffset CurrentParamStackOffset();
139
140 // Iterator interface extension for JNI
Ian Rogers408f79a2011-08-23 18:22:33 -0700141 FrameOffset CurrentParamSirtEntryOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700142
Ian Rogers408f79a2011-08-23 18:22:33 -0700143 // Position of SIRT and interior fields
144 FrameOffset SirtOffset() {
Ian Rogersb033c752011-07-20 12:22:35 -0700145 return FrameOffset(displacement_.Int32Value() +
Ian Rogers0d666d82011-08-14 16:03:46 -0700146 SpillAreaSize() +
Ian Rogersb033c752011-07-20 12:22:35 -0700147 kPointerSize); // above Method*
148 }
Ian Rogers408f79a2011-08-23 18:22:33 -0700149 FrameOffset SirtNumRefsOffset() {
150 return FrameOffset(SirtOffset().Int32Value() +
151 StackIndirectReferenceTable::NumberOfReferencesOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700152 }
Ian Rogers408f79a2011-08-23 18:22:33 -0700153 FrameOffset SirtLinkOffset() {
154 return FrameOffset(SirtOffset().Int32Value() +
155 StackIndirectReferenceTable::LinkOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700156 }
157
158 private:
159 // Named iterator positions
160 enum IteratorPos {
161 kJniEnv = 0,
162 kObjectOrClass = 1
163 };
164
Ian Rogers408f79a2011-08-23 18:22:33 -0700165 // Number of stack slots for outgoing arguments, above which the SIRT is
Ian Rogersb033c752011-07-20 12:22:35 -0700166 // located
167 size_t NumberOfOutgoingStackArgs();
168
Ian Rogers0d666d82011-08-14 16:03:46 -0700169 // Compute registers for RegsToSpillPreCall
170 std::vector<ManagedRegister>* ComputeRegsToSpillPreCall();
171
172 // Extra registers to spill before the call into native
173 const scoped_ptr<std::vector<ManagedRegister> > spill_regs_;
174
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700175 static size_t NumberOfExtraArgumentsForJni(const Method* method);
Ian Rogersb033c752011-07-20 12:22:35 -0700176 DISALLOW_COPY_AND_ASSIGN(JniCallingConvention);
177};
178
179} // namespace art
180
181#endif // ART_SRC_CALLING_CONVENTION_H_