blob: 3a7cf1ed1ede9105d02fc545a508e3aacebc16f6 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
// Copyright 2011 Google Inc. All Rights Reserved.
#ifndef ART_SRC_CALLING_CONVENTION_H_
#define ART_SRC_CALLING_CONVENTION_H_
#include <vector>
#include "managed_register.h"
#include "object.h"
#include "stack_indirect_reference_table.h"
#include "thread.h"
namespace art {
// Top-level abstraction for different calling conventions
class CallingConvention {
public:
bool IsReturnAReference() const { return method_->IsReturnAReference(); }
size_t SizeOfReturnValue() const { return method_->ReturnSize(); }
// Register that holds result of this method
virtual ManagedRegister ReturnRegister() = 0;
// Register reserved for scratch usage during procedure calls
virtual ManagedRegister InterproceduralScratchRegister() = 0;
// Offset of Method within the frame
FrameOffset MethodStackOffset();
// Iterator interface
// Place iterator at start of arguments. The displacement is applied to
// frame offset methods to account for frames which may be on the stack
// below the one being iterated over.
void ResetIterator(FrameOffset displacement) {
displacement_ = displacement;
itr_slots_ = 0;
itr_args_ = 0;
itr_refs_ = 0;
itr_longs_and_doubles_ = 0;
}
virtual ~CallingConvention() {}
protected:
explicit CallingConvention(const Method* method)
: displacement_(0), method_(const_cast<Method*>(method)) {}
const Method* GetMethod() const { return method_; }
// The slot number for current calling_convention argument.
// Note that each slot is 32-bit. When the current argument is bigger
// than 32 bits, return the first slot number for this argument.
unsigned int itr_slots_;
// The number of references iterated past
unsigned int itr_refs_;
// The argument number along argument list for current argument
unsigned int itr_args_;
// Number of longs and doubles seen along argument list
unsigned int itr_longs_and_doubles_;
// Space for frames below this on the stack
FrameOffset displacement_;
private:
Method* method_;
};
// Abstraction for managed code's calling conventions
// | { Incoming stack args } |
// | { Prior Method* } | <-- Prior SP
// | { Return address } |
// | { Callee saves } |
// | { Spills ... } |
// | { Outgoing stack args } |
// | { Method* } | <-- SP
class ManagedRuntimeCallingConvention : public CallingConvention {
public:
static ManagedRuntimeCallingConvention* Create(const Method* native_method,
InstructionSet instruction_set);
size_t FrameSize();
// Register that holds the incoming method argument
virtual ManagedRegister MethodRegister() = 0;
// Iterator interface
bool HasNext();
void Next();
bool IsCurrentParamAReference();
bool IsCurrentArgExplicit(); // ie a non-implict argument such as this
bool IsCurrentArgPossiblyNull();
size_t CurrentParamSize();
virtual bool IsCurrentParamInRegister() = 0;
virtual bool IsCurrentParamOnStack() = 0;
virtual ManagedRegister CurrentParamRegister() = 0;
virtual FrameOffset CurrentParamStackOffset() = 0;
virtual ~ManagedRuntimeCallingConvention() {}
protected:
explicit ManagedRuntimeCallingConvention(const Method* method) :
CallingConvention(method) {}
};
// Abstraction for JNI calling conventions
// | { Incoming stack args } | <-- Prior SP
// | { Return address } |
// | { Callee saves } | ([1])
// | { Return value spill } | (live on return slow paths)
// | { Local Ref. Table State } |
// | { Stack Indirect Ref. Table |
// | num. refs./link } | (here to prior SP is frame size)
// | { Method* } | <-- Anchor SP written to thread
// | { Outgoing stack args } | <-- SP at point of call
// | Native frame |
//
// [1] We must save all callee saves here to enable any exception throws to restore
// callee saves for frames above this one.
class JniCallingConvention : public CallingConvention {
public:
static JniCallingConvention* Create(const Method* native_method,
InstructionSet instruction_set);
// Size of frame excluding space for outgoing args (its assumed Method* is
// always at the bottom of a frame, but this doesn't work for outgoing
// native args). Includes alignment.
virtual size_t FrameSize() = 0;
// Offset within the frame of the return pc
virtual size_t ReturnPcOffset() = 0;
// Size of outgoing arguments, including alignment
virtual size_t OutArgSize() = 0;
// Number of references in stack indirect reference table
size_t ReferenceCount() const;
// Location where the segment state of the local indirect reference table is saved
FrameOffset SavedLocalReferenceCookieOffset() const;
// Location where the return value of a call can be squirreled if another
// call is made following the native call
FrameOffset ReturnValueSaveLocation() const;
// Callee save registers to spill prior to native code (which may clobber)
virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const = 0;
// Spill mask values
virtual uint32_t CoreSpillMask() const = 0;
virtual uint32_t FpSpillMask() const = 0;
// Returns true if the method register will have been clobbered during argument
// set up
virtual bool IsMethodRegisterClobberedPreCall() = 0;
// An extra scratch register live after the call
virtual ManagedRegister ReturnScratchRegister() const = 0;
// Iterator interface
bool HasNext();
virtual void Next();
bool IsCurrentParamAReference();
size_t CurrentParamSize();
virtual bool IsCurrentParamInRegister() = 0;
virtual bool IsCurrentParamOnStack() = 0;
virtual ManagedRegister CurrentParamRegister() = 0;
virtual FrameOffset CurrentParamStackOffset() = 0;
// Iterator interface extension for JNI
FrameOffset CurrentParamSirtEntryOffset();
// Position of SIRT and interior fields
FrameOffset SirtOffset() const {
return FrameOffset(displacement_.Int32Value() +
kPointerSize); // above Method*
}
FrameOffset SirtNumRefsOffset() const {
return FrameOffset(SirtOffset().Int32Value() +
StackIndirectReferenceTable::NumberOfReferencesOffset());
}
FrameOffset SirtLinkOffset() const {
return FrameOffset(SirtOffset().Int32Value() +
StackIndirectReferenceTable::LinkOffset());
}
virtual ~JniCallingConvention() {}
protected:
// Named iterator positions
enum IteratorPos {
kJniEnv = 0,
kObjectOrClass = 1
};
explicit JniCallingConvention(const Method* native_method) :
CallingConvention(native_method) {}
// Number of stack slots for outgoing arguments, above which the SIRT is
// located
virtual size_t NumberOfOutgoingStackArgs() = 0;
protected:
static size_t NumberOfExtraArgumentsForJni(const Method* method);
};
} // namespace art
#endif // ART_SRC_CALLING_CONVENTION_H_
|