blob: cf03bb82db62285eee110f8cc948e494061259c0 [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:
Ian Rogersb033c752011-07-20 12:22:35 -070016 bool IsReturnAReference() const { return method_->IsReturnAReference(); }
17
Ian Rogersdf20fe02011-07-20 20:34:16 -070018 size_t SizeOfReturnValue() const { return method_->ReturnSize(); }
19
Ian Rogersb033c752011-07-20 12:22:35 -070020 // Register that holds result of this method
Ian Rogers2c8f6532011-09-02 17:16:34 -070021 virtual ManagedRegister ReturnRegister() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070022 // Register reserved for scratch usage during procedure calls
Ian Rogers2c8f6532011-09-02 17:16:34 -070023 virtual ManagedRegister InterproceduralScratchRegister() = 0;
Shih-wei Liao668512a2011-09-01 14:18:34 -070024
Carl Shapiroe2d373e2011-07-25 15:20:06 -070025 // Offset of Method within the frame
26 FrameOffset MethodStackOffset();
27
Ian Rogersb033c752011-07-20 12:22:35 -070028 // Iterator interface
29
30 // Place iterator at start of arguments. The displacement is applied to
31 // frame offset methods to account for frames which may be on the stack
32 // below the one being iterated over.
33 void ResetIterator(FrameOffset displacement) {
34 displacement_ = displacement;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070035 itr_slots_ = 0;
36 itr_args_ = 0;
Shih-wei Liao668512a2011-09-01 14:18:34 -070037 itr_refs_ = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070038 itr_longs_and_doubles_ = 0;
39 }
40
Ian Rogers2c8f6532011-09-02 17:16:34 -070041 virtual ~CallingConvention() {}
42
Ian Rogersb033c752011-07-20 12:22:35 -070043 protected:
44 explicit CallingConvention(Method* method) : displacement_(0),
45 method_(method) {}
Ian Rogers2c8f6532011-09-02 17:16:34 -070046
47 Method* GetMethod() const { return method_; }
Ian Rogersb033c752011-07-20 12:22:35 -070048
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_;
Ian Rogers7a99c112011-09-07 12:48:27 -070053 // The number of references iterated past
54 unsigned int itr_refs_;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070055 // The argument number along argument list for current argument
56 unsigned int itr_args_;
57 // Number of longs and doubles seen along argument list
Ian Rogersb033c752011-07-20 12:22:35 -070058 unsigned int itr_longs_and_doubles_;
59 // Space for frames below this on the stack
60 FrameOffset displacement_;
61
62 private:
Ian Rogers2c8f6532011-09-02 17:16:34 -070063 Method* method_;
Ian Rogersb033c752011-07-20 12:22:35 -070064};
65
66// Abstraction for managed code's calling conventions
Ian Rogersbdb03912011-09-14 00:55:44 -070067// | { Incoming stack args } |
68// | { Prior Method* } | <-- Prior SP
69// | { Return address } |
70// | { Callee saves } |
71// | { Spills ... } |
72// | { Outgoing stack args } |
73// | { Method* } | <-- SP
Ian Rogersb033c752011-07-20 12:22:35 -070074class ManagedRuntimeCallingConvention : public CallingConvention {
75 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -070076 static ManagedRuntimeCallingConvention* Create(Method* native_method,
77 InstructionSet instruction_set);
Ian Rogersb033c752011-07-20 12:22:35 -070078
79 size_t FrameSize();
80
Ian Rogers2c8f6532011-09-02 17:16:34 -070081 // Register that holds the incoming method argument
82 virtual ManagedRegister MethodRegister() = 0;
83
Ian Rogersb033c752011-07-20 12:22:35 -070084 // Iterator interface
85 bool HasNext();
86 void Next();
87 bool IsCurrentParamAReference();
Ian Rogers7a99c112011-09-07 12:48:27 -070088 bool IsCurrentArgExplicit(); // ie a non-implict argument such as this
89 bool IsCurrentArgPossiblyNull();
Ian Rogersdf20fe02011-07-20 20:34:16 -070090 size_t CurrentParamSize();
Ian Rogers2c8f6532011-09-02 17:16:34 -070091 virtual bool IsCurrentParamInRegister() = 0;
92 virtual bool IsCurrentParamOnStack() = 0;
93 virtual ManagedRegister CurrentParamRegister() = 0;
94 virtual FrameOffset CurrentParamStackOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070095
Ian Rogers2c8f6532011-09-02 17:16:34 -070096 virtual ~ManagedRuntimeCallingConvention() {}
97
98 protected:
99 explicit ManagedRuntimeCallingConvention(Method* method) :
Ian Rogersbdb03912011-09-14 00:55:44 -0700100 CallingConvention(method) {}
Ian Rogersb033c752011-07-20 12:22:35 -0700101};
102
103// Abstraction for JNI calling conventions
Ian Rogersbdb03912011-09-14 00:55:44 -0700104// | { Incoming stack args } | <-- Prior SP
105// | { Return address } |
106// | { Callee saves } | ([1])
107// | { Return value spill } | (live on return slow paths)
Ian Rogersdc51b792011-09-22 20:41:37 -0700108// | { Local Ref. Table State } |
Ian Rogersbdb03912011-09-14 00:55:44 -0700109// | { Stack Indirect Ref. Table |
110// | num. refs./link } | (here to prior SP is frame size)
111// | { Method* } | <-- Anchor SP written to thread
112// | { Outgoing stack args } | <-- SP at point of call
113// | Native frame |
114//
115// [1] We must save all callee saves here to enable any exception throws to restore
116// callee saves for frames above this one.
Ian Rogersb033c752011-07-20 12:22:35 -0700117class JniCallingConvention : public CallingConvention {
118 public:
Ian Rogers2c8f6532011-09-02 17:16:34 -0700119 static JniCallingConvention* Create(Method* native_method,
120 InstructionSet instruction_set);
Ian Rogersb033c752011-07-20 12:22:35 -0700121
122 // Size of frame excluding space for outgoing args (its assumed Method* is
123 // always at the bottom of a frame, but this doesn't work for outgoing
124 // native args). Includes alignment.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700125 virtual size_t FrameSize() = 0;
Ian Rogers762400c2011-08-23 12:14:16 -0700126 // Offset within the frame of the return pc
Ian Rogers2c8f6532011-09-02 17:16:34 -0700127 virtual size_t ReturnPcOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700128 // Size of outgoing arguments, including alignment
Ian Rogers2c8f6532011-09-02 17:16:34 -0700129 virtual size_t OutArgSize() = 0;
Ian Rogers408f79a2011-08-23 18:22:33 -0700130 // Number of references in stack indirect reference table
Ian Rogersdc51b792011-09-22 20:41:37 -0700131 size_t ReferenceCount() const;
132 // Location where the segment state of the local indirect reference table is saved
133 FrameOffset LocalReferenceTable_SegmentStatesOffset() const;
Ian Rogersdf20fe02011-07-20 20:34:16 -0700134 // Location where the return value of a call can be squirreled if another
135 // call is made following the native call
Ian Rogersdc51b792011-09-22 20:41:37 -0700136 FrameOffset ReturnValueSaveLocation() const;
Ian Rogersb033c752011-07-20 12:22:35 -0700137
Ian Rogersbdb03912011-09-14 00:55:44 -0700138 // Callee save registers to spill prior to native code (which may clobber)
139 virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const = 0;
140
141 // Spill mask values
142 virtual uint32_t CoreSpillMask() const = 0;
143 virtual uint32_t FpSpillMask() const = 0;
Ian Rogers0d666d82011-08-14 16:03:46 -0700144
Ian Rogers67375ac2011-09-14 00:55:44 -0700145 // Returns true if the method register will have been clobbered during argument
146 // set up
Ian Rogersad42e132011-09-17 20:23:33 -0700147 virtual bool IsMethodRegisterClobberedPreCall() = 0;
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700148
Ian Rogersdc51b792011-09-22 20:41:37 -0700149 // An extra scratch register live after the call
150 virtual ManagedRegister ReturnScratchRegister() const = 0;
151
Ian Rogersb033c752011-07-20 12:22:35 -0700152 // Iterator interface
153 bool HasNext();
Ian Rogers67375ac2011-09-14 00:55:44 -0700154 virtual void Next();
Ian Rogersb033c752011-07-20 12:22:35 -0700155 bool IsCurrentParamAReference();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700156 size_t CurrentParamSize();
Ian Rogers2c8f6532011-09-02 17:16:34 -0700157 virtual bool IsCurrentParamInRegister() = 0;
158 virtual bool IsCurrentParamOnStack() = 0;
159 virtual ManagedRegister CurrentParamRegister() = 0;
160 virtual FrameOffset CurrentParamStackOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700161
162 // Iterator interface extension for JNI
Ian Rogers408f79a2011-08-23 18:22:33 -0700163 FrameOffset CurrentParamSirtEntryOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700164
Ian Rogers408f79a2011-08-23 18:22:33 -0700165 // Position of SIRT and interior fields
Ian Rogersdc51b792011-09-22 20:41:37 -0700166 FrameOffset SirtOffset() const {
Ian Rogersb033c752011-07-20 12:22:35 -0700167 return FrameOffset(displacement_.Int32Value() +
168 kPointerSize); // above Method*
169 }
Ian Rogersdc51b792011-09-22 20:41:37 -0700170 FrameOffset SirtNumRefsOffset() const {
Ian Rogers408f79a2011-08-23 18:22:33 -0700171 return FrameOffset(SirtOffset().Int32Value() +
172 StackIndirectReferenceTable::NumberOfReferencesOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700173 }
Ian Rogersdc51b792011-09-22 20:41:37 -0700174 FrameOffset SirtLinkOffset() const {
Ian Rogers408f79a2011-08-23 18:22:33 -0700175 return FrameOffset(SirtOffset().Int32Value() +
176 StackIndirectReferenceTable::LinkOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700177 }
178
Ian Rogers2c8f6532011-09-02 17:16:34 -0700179 virtual ~JniCallingConvention() {}
180
181 protected:
Ian Rogersb033c752011-07-20 12:22:35 -0700182 // Named iterator positions
183 enum IteratorPos {
184 kJniEnv = 0,
185 kObjectOrClass = 1
186 };
187
Ian Rogers2c8f6532011-09-02 17:16:34 -0700188 explicit JniCallingConvention(Method* native_method) :
189 CallingConvention(native_method) {}
190
Ian Rogers408f79a2011-08-23 18:22:33 -0700191 // Number of stack slots for outgoing arguments, above which the SIRT is
Ian Rogersb033c752011-07-20 12:22:35 -0700192 // located
Ian Rogers2c8f6532011-09-02 17:16:34 -0700193 virtual size_t NumberOfOutgoingStackArgs() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700194
Ian Rogers2c8f6532011-09-02 17:16:34 -0700195 protected:
196 static size_t NumberOfExtraArgumentsForJni(Method* method);
Ian Rogersb033c752011-07-20 12:22:35 -0700197};
198
199} // namespace art
200
201#endif // ART_SRC_CALLING_CONVENTION_H_