blob: 3a7cf1ed1ede9105d02fc545a508e3aacebc16f6 [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"
Elliott Hughes68e76522011-10-05 13:22:16 -07009#include "stack_indirect_reference_table.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070010#include "thread.h"
Ian Rogersb033c752011-07-20 12:22:35 -070011
12namespace art {
13
14// Top-level abstraction for different calling conventions
15class CallingConvention {
16 public:
Ian Rogersb033c752011-07-20 12:22:35 -070017 bool IsReturnAReference() const { return method_->IsReturnAReference(); }
18
Ian Rogersdf20fe02011-07-20 20:34:16 -070019 size_t SizeOfReturnValue() const { return method_->ReturnSize(); }
20
Ian Rogersb033c752011-07-20 12:22:35 -070021 // Register that holds result of this method
Ian Rogers2c8f6532011-09-02 17:16:34 -070022 virtual ManagedRegister ReturnRegister() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070023 // Register reserved for scratch usage during procedure calls
Ian Rogers2c8f6532011-09-02 17:16:34 -070024 virtual ManagedRegister InterproceduralScratchRegister() = 0;
Shih-wei Liao668512a2011-09-01 14:18:34 -070025
Carl Shapiroe2d373e2011-07-25 15:20:06 -070026 // Offset of Method within the frame
27 FrameOffset MethodStackOffset();
28
Ian Rogersb033c752011-07-20 12:22:35 -070029 // Iterator interface
30
31 // Place iterator at start of arguments. The displacement is applied to
32 // frame offset methods to account for frames which may be on the stack
33 // below the one being iterated over.
34 void ResetIterator(FrameOffset displacement) {
35 displacement_ = displacement;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070036 itr_slots_ = 0;
37 itr_args_ = 0;
Shih-wei Liao668512a2011-09-01 14:18:34 -070038 itr_refs_ = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070039 itr_longs_and_doubles_ = 0;
40 }
41
Ian Rogers2c8f6532011-09-02 17:16:34 -070042 virtual ~CallingConvention() {}
43
Ian Rogersb033c752011-07-20 12:22:35 -070044 protected:
Brian Carlstrom3320cf42011-10-04 14:58:28 -070045 explicit CallingConvention(const Method* method)
46 : displacement_(0), method_(const_cast<Method*>(method)) {}
Ian Rogers2c8f6532011-09-02 17:16:34 -070047
Brian Carlstrom3320cf42011-10-04 14:58:28 -070048 const Method* GetMethod() const { return method_; }
Ian Rogersb033c752011-07-20 12:22:35 -070049
Shih-wei Liao5381cf92011-07-27 00:28:04 -070050 // The slot number for current calling_convention argument.
51 // Note that each slot is 32-bit. When the current argument is bigger
52 // than 32 bits, return the first slot number for this argument.
53 unsigned int itr_slots_;
Ian Rogers7a99c112011-09-07 12:48:27 -070054 // The number of references iterated past
55 unsigned int itr_refs_;
Shih-wei Liao5381cf92011-07-27 00:28:04 -070056 // The argument number along argument list for current argument
57 unsigned int itr_args_;
58 // Number of longs and doubles seen along argument list
Ian Rogersb033c752011-07-20 12:22:35 -070059 unsigned int itr_longs_and_doubles_;
60 // Space for frames below this on the stack
61 FrameOffset displacement_;
62
63 private:
Ian Rogers2c8f6532011-09-02 17:16:34 -070064 Method* method_;
Ian Rogersb033c752011-07-20 12:22:35 -070065};
66
67// Abstraction for managed code's calling conventions
Ian Rogersbdb03912011-09-14 00:55:44 -070068// | { Incoming stack args } |
69// | { Prior Method* } | <-- Prior SP
70// | { Return address } |
71// | { Callee saves } |
72// | { Spills ... } |
73// | { Outgoing stack args } |
74// | { Method* } | <-- SP
Ian Rogersb033c752011-07-20 12:22:35 -070075class ManagedRuntimeCallingConvention : public CallingConvention {
76 public:
Brian Carlstrom3320cf42011-10-04 14:58:28 -070077 static ManagedRuntimeCallingConvention* Create(const Method* native_method,
78 InstructionSet instruction_set);
Ian Rogersb033c752011-07-20 12:22:35 -070079
80 size_t FrameSize();
81
Ian Rogers2c8f6532011-09-02 17:16:34 -070082 // Register that holds the incoming method argument
83 virtual ManagedRegister MethodRegister() = 0;
84
Ian Rogersb033c752011-07-20 12:22:35 -070085 // Iterator interface
86 bool HasNext();
87 void Next();
88 bool IsCurrentParamAReference();
Ian Rogers7a99c112011-09-07 12:48:27 -070089 bool IsCurrentArgExplicit(); // ie a non-implict argument such as this
90 bool IsCurrentArgPossiblyNull();
Ian Rogersdf20fe02011-07-20 20:34:16 -070091 size_t CurrentParamSize();
Ian Rogers2c8f6532011-09-02 17:16:34 -070092 virtual bool IsCurrentParamInRegister() = 0;
93 virtual bool IsCurrentParamOnStack() = 0;
94 virtual ManagedRegister CurrentParamRegister() = 0;
95 virtual FrameOffset CurrentParamStackOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -070096
Ian Rogers2c8f6532011-09-02 17:16:34 -070097 virtual ~ManagedRuntimeCallingConvention() {}
98
99 protected:
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700100 explicit ManagedRuntimeCallingConvention(const Method* method) :
Ian Rogersbdb03912011-09-14 00:55:44 -0700101 CallingConvention(method) {}
Ian Rogersb033c752011-07-20 12:22:35 -0700102};
103
104// Abstraction for JNI calling conventions
Ian Rogersbdb03912011-09-14 00:55:44 -0700105// | { Incoming stack args } | <-- Prior SP
106// | { Return address } |
107// | { Callee saves } | ([1])
108// | { Return value spill } | (live on return slow paths)
Ian Rogersdc51b792011-09-22 20:41:37 -0700109// | { Local Ref. Table State } |
Ian Rogersbdb03912011-09-14 00:55:44 -0700110// | { Stack Indirect Ref. Table |
111// | num. refs./link } | (here to prior SP is frame size)
112// | { Method* } | <-- Anchor SP written to thread
113// | { Outgoing stack args } | <-- SP at point of call
114// | Native frame |
115//
116// [1] We must save all callee saves here to enable any exception throws to restore
117// callee saves for frames above this one.
Ian Rogersb033c752011-07-20 12:22:35 -0700118class JniCallingConvention : public CallingConvention {
119 public:
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700120 static JniCallingConvention* Create(const Method* native_method,
Ian Rogers2c8f6532011-09-02 17:16:34 -0700121 InstructionSet instruction_set);
Ian Rogersb033c752011-07-20 12:22:35 -0700122
123 // Size of frame excluding space for outgoing args (its assumed Method* is
124 // always at the bottom of a frame, but this doesn't work for outgoing
125 // native args). Includes alignment.
Ian Rogers2c8f6532011-09-02 17:16:34 -0700126 virtual size_t FrameSize() = 0;
Ian Rogers762400c2011-08-23 12:14:16 -0700127 // Offset within the frame of the return pc
Ian Rogers2c8f6532011-09-02 17:16:34 -0700128 virtual size_t ReturnPcOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700129 // Size of outgoing arguments, including alignment
Ian Rogers2c8f6532011-09-02 17:16:34 -0700130 virtual size_t OutArgSize() = 0;
Ian Rogers408f79a2011-08-23 18:22:33 -0700131 // Number of references in stack indirect reference table
Ian Rogersdc51b792011-09-22 20:41:37 -0700132 size_t ReferenceCount() const;
133 // Location where the segment state of the local indirect reference table is saved
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700134 FrameOffset SavedLocalReferenceCookieOffset() const;
Ian Rogersdf20fe02011-07-20 20:34:16 -0700135 // Location where the return value of a call can be squirreled if another
136 // call is made following the native call
Ian Rogersdc51b792011-09-22 20:41:37 -0700137 FrameOffset ReturnValueSaveLocation() const;
Ian Rogersb033c752011-07-20 12:22:35 -0700138
Ian Rogersbdb03912011-09-14 00:55:44 -0700139 // Callee save registers to spill prior to native code (which may clobber)
140 virtual const std::vector<ManagedRegister>& CalleeSaveRegisters() const = 0;
141
142 // Spill mask values
143 virtual uint32_t CoreSpillMask() const = 0;
144 virtual uint32_t FpSpillMask() const = 0;
Ian Rogers0d666d82011-08-14 16:03:46 -0700145
Ian Rogers67375ac2011-09-14 00:55:44 -0700146 // Returns true if the method register will have been clobbered during argument
147 // set up
Ian Rogersad42e132011-09-17 20:23:33 -0700148 virtual bool IsMethodRegisterClobberedPreCall() = 0;
Carl Shapiroe2d373e2011-07-25 15:20:06 -0700149
Ian Rogersdc51b792011-09-22 20:41:37 -0700150 // An extra scratch register live after the call
151 virtual ManagedRegister ReturnScratchRegister() const = 0;
152
Ian Rogersb033c752011-07-20 12:22:35 -0700153 // Iterator interface
154 bool HasNext();
Ian Rogers67375ac2011-09-14 00:55:44 -0700155 virtual void Next();
Ian Rogersb033c752011-07-20 12:22:35 -0700156 bool IsCurrentParamAReference();
Ian Rogersdf20fe02011-07-20 20:34:16 -0700157 size_t CurrentParamSize();
Ian Rogers2c8f6532011-09-02 17:16:34 -0700158 virtual bool IsCurrentParamInRegister() = 0;
159 virtual bool IsCurrentParamOnStack() = 0;
160 virtual ManagedRegister CurrentParamRegister() = 0;
161 virtual FrameOffset CurrentParamStackOffset() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700162
163 // Iterator interface extension for JNI
Ian Rogers408f79a2011-08-23 18:22:33 -0700164 FrameOffset CurrentParamSirtEntryOffset();
Ian Rogersb033c752011-07-20 12:22:35 -0700165
Ian Rogers408f79a2011-08-23 18:22:33 -0700166 // Position of SIRT and interior fields
Ian Rogersdc51b792011-09-22 20:41:37 -0700167 FrameOffset SirtOffset() const {
Ian Rogersb033c752011-07-20 12:22:35 -0700168 return FrameOffset(displacement_.Int32Value() +
169 kPointerSize); // above Method*
170 }
Ian Rogersdc51b792011-09-22 20:41:37 -0700171 FrameOffset SirtNumRefsOffset() const {
Ian Rogers408f79a2011-08-23 18:22:33 -0700172 return FrameOffset(SirtOffset().Int32Value() +
173 StackIndirectReferenceTable::NumberOfReferencesOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700174 }
Ian Rogersdc51b792011-09-22 20:41:37 -0700175 FrameOffset SirtLinkOffset() const {
Ian Rogers408f79a2011-08-23 18:22:33 -0700176 return FrameOffset(SirtOffset().Int32Value() +
177 StackIndirectReferenceTable::LinkOffset());
Ian Rogersb033c752011-07-20 12:22:35 -0700178 }
179
Ian Rogers2c8f6532011-09-02 17:16:34 -0700180 virtual ~JniCallingConvention() {}
181
182 protected:
Ian Rogersb033c752011-07-20 12:22:35 -0700183 // Named iterator positions
184 enum IteratorPos {
185 kJniEnv = 0,
186 kObjectOrClass = 1
187 };
188
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700189 explicit JniCallingConvention(const Method* native_method) :
Ian Rogers2c8f6532011-09-02 17:16:34 -0700190 CallingConvention(native_method) {}
191
Ian Rogers408f79a2011-08-23 18:22:33 -0700192 // Number of stack slots for outgoing arguments, above which the SIRT is
Ian Rogersb033c752011-07-20 12:22:35 -0700193 // located
Ian Rogers2c8f6532011-09-02 17:16:34 -0700194 virtual size_t NumberOfOutgoingStackArgs() = 0;
Ian Rogersb033c752011-07-20 12:22:35 -0700195
Ian Rogers2c8f6532011-09-02 17:16:34 -0700196 protected:
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700197 static size_t NumberOfExtraArgumentsForJni(const Method* method);
Ian Rogersb033c752011-07-20 12:22:35 -0700198};
199
200} // namespace art
201
202#endif // ART_SRC_CALLING_CONVENTION_H_