blob: 44ce93f5ad98faf3564ae08eae26d3d6f68c7894 [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.
Shih-wei Liao668512a2011-09-01 14:18:34 -070055 unsigned int itr_refs_;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070056 unsigned int itr_slots_;
57 // The argument number along argument list for current argument
58 unsigned int itr_args_;
59 // Number of longs and doubles seen along argument list
Ian Rogersb033c752011-07-20 12:22:35 -070060 unsigned int itr_longs_and_doubles_;
61 // Space for frames below this on the stack
62 FrameOffset displacement_;
63
64 private:
65 const Method* method_;
66};
67
68// Abstraction for managed code's calling conventions
69class ManagedRuntimeCallingConvention : public CallingConvention {
70 public:
71 explicit ManagedRuntimeCallingConvention(Method* method) :
72 CallingConvention(method) {}
73
74 size_t FrameSize();
75
76 // Iterator interface
77 bool HasNext();
78 void Next();
79 bool IsCurrentParamAReference();
80 bool IsCurrentParamInRegister();
81 bool IsCurrentParamOnStack();
Shih-wei Liao5381cf92011-07-27 00:28:04 -070082 bool IsCurrentUserArg();
Ian Rogersdf20fe02011-07-20 20:34:16 -070083 size_t CurrentParamSize();
Ian Rogersb033c752011-07-20 12:22:35 -070084 ManagedRegister CurrentParamRegister();
85 FrameOffset CurrentParamStackOffset();
86
87 DISALLOW_COPY_AND_ASSIGN(ManagedRuntimeCallingConvention);
88};
89
90// Abstraction for JNI calling conventions
91// | incoming stack args | <-- Prior SP
Ian Rogers0d666d82011-08-14 16:03:46 -070092// | { Return address } | (x86)
Ian Rogersdf20fe02011-07-20 20:34:16 -070093// | { Return value spill } | (live on return slow paths)
Ian Rogers408f79a2011-08-23 18:22:33 -070094// | { Stack Indirect Ref. |
95// | Table... |
Ian Rogersdf20fe02011-07-20 20:34:16 -070096// | num. refs./link } | (here to prior SP is frame size)
Ian Rogers0d666d82011-08-14 16:03:46 -070097// | { Spill area } | (ARM)
Ian Rogersb033c752011-07-20 12:22:35 -070098// | Method* | <-- Anchor SP written to thread
99// | { Outgoing stack args |
100// | ... } | <-- SP at point of call
101// | Native frame |
102class JniCallingConvention : public CallingConvention {
103 public:
Elliott Hughes90a33692011-08-30 13:27:07 -0700104 explicit JniCallingConvention(Method* native_method)
105 : CallingConvention(native_method) {
106 ComputeRegsToSpillPreCall(spill_regs_);
107 }
Ian Rogersb033c752011-07-20 12:22:35 -0700108
109 // Size of frame excluding space for outgoing args (its assumed Method* is
110 // always at the bottom of a frame, but this doesn't work for outgoing
111 // native args). Includes alignment.
112 size_t FrameSize();
Ian Rogers762400c2011-08-23 12:14:16 -0700113 // Offset within the frame of the return pc
114 size_t ReturnPcOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700115 // Size of outgoing arguments, including alignment
116 size_t OutArgSize();
Ian Rogers408f79a2011-08-23 18:22:33 -0700117 // Number of references in stack indirect reference table
118 size_t ReferenceCount();
Ian Rogers0d666d82011-08-14 16:03:46 -0700119 // Size of area used to hold spilled registers
120 size_t SpillAreaSize();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700121 // Location where the return value of a call can be squirreled if another
122 // call is made following the native call
123 FrameOffset ReturnValueSaveLocation();
Ian Rogersb033c752011-07-20 12:22:35 -0700124
Ian Rogers0d666d82011-08-14 16:03:46 -0700125 // Registers that must be spilled (due to clobbering) before the call into
126 // the native routine
127 const std::vector<ManagedRegister>& RegsToSpillPreCall() {
Elliott Hughes90a33692011-08-30 13:27:07 -0700128 return spill_regs_;
Ian Rogers0d666d82011-08-14 16:03:46 -0700129 }
130
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700131 // Returns true if the register will be clobbered by an outgoing
132 // argument value.
133 bool IsOutArgRegister(ManagedRegister reg);
134
Ian Rogersb033c752011-07-20 12:22:35 -0700135 // Iterator interface
136 bool HasNext();
137 void Next();
138 bool IsCurrentParamAReference();
139 bool IsCurrentParamInRegister();
140 bool IsCurrentParamOnStack();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700141 size_t CurrentParamSize();
Ian Rogersb033c752011-07-20 12:22:35 -0700142 ManagedRegister CurrentParamRegister();
143 FrameOffset CurrentParamStackOffset();
144
145 // Iterator interface extension for JNI
Ian Rogers408f79a2011-08-23 18:22:33 -0700146 FrameOffset CurrentParamSirtEntryOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700147
Ian Rogers408f79a2011-08-23 18:22:33 -0700148 // Position of SIRT and interior fields
149 FrameOffset SirtOffset() {
Ian Rogersb033c752011-07-20 12:22:35 -0700150 return FrameOffset(displacement_.Int32Value() +
Ian Rogers0d666d82011-08-14 16:03:46 -0700151 SpillAreaSize() +
Ian Rogersb033c752011-07-20 12:22:35 -0700152 kPointerSize); // above Method*
153 }
Ian Rogers408f79a2011-08-23 18:22:33 -0700154 FrameOffset SirtNumRefsOffset() {
155 return FrameOffset(SirtOffset().Int32Value() +
156 StackIndirectReferenceTable::NumberOfReferencesOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700157 }
Ian Rogers408f79a2011-08-23 18:22:33 -0700158 FrameOffset SirtLinkOffset() {
159 return FrameOffset(SirtOffset().Int32Value() +
160 StackIndirectReferenceTable::LinkOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700161 }
162
163 private:
164 // Named iterator positions
165 enum IteratorPos {
166 kJniEnv = 0,
167 kObjectOrClass = 1
168 };
169
Ian Rogers408f79a2011-08-23 18:22:33 -0700170 // Number of stack slots for outgoing arguments, above which the SIRT is
Ian Rogersb033c752011-07-20 12:22:35 -0700171 // located
172 size_t NumberOfOutgoingStackArgs();
173
Ian Rogers0d666d82011-08-14 16:03:46 -0700174 // Compute registers for RegsToSpillPreCall
Elliott Hughes90a33692011-08-30 13:27:07 -0700175 void ComputeRegsToSpillPreCall(std::vector<ManagedRegister>& regs);
Ian Rogers0d666d82011-08-14 16:03:46 -0700176
177 // Extra registers to spill before the call into native
Elliott Hughes90a33692011-08-30 13:27:07 -0700178 std::vector<ManagedRegister> spill_regs_;
Ian Rogers0d666d82011-08-14 16:03:46 -0700179
Shih-wei Liao5381cf92011-07-27 00:28:04 -0700180 static size_t NumberOfExtraArgumentsForJni(const Method* method);
Ian Rogersb033c752011-07-20 12:22:35 -0700181 DISALLOW_COPY_AND_ASSIGN(JniCallingConvention);
182};
183
184} // namespace art
185
186#endif // ART_SRC_CALLING_CONVENTION_H_