| // 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 "thread.h" |
| |
| namespace art { |
| |
| // Top-level abstraction for different calling conventions |
| class CallingConvention { |
| public: |
| CallingConvention* GetCallingConvention(Method* method); |
| |
| bool IsReturnAReference() const { return method_->IsReturnAReference(); } |
| |
| size_t SizeOfReturnValue() const { return method_->ReturnSize(); } |
| |
| // Register that holds the incoming method argument |
| ManagedRegister MethodRegister(); |
| // Register that holds result of this method |
| ManagedRegister ReturnRegister(); |
| // Register reserved for scratch usage during procedure calls |
| ManagedRegister InterproceduralScratchRegister(); |
| |
| ManagedRegister ThreadRegister(); |
| |
| // 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; |
| } |
| |
| protected: |
| explicit CallingConvention(Method* method) : displacement_(0), |
| 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_refs_; |
| unsigned int itr_slots_; |
| // 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: |
| const Method* method_; |
| }; |
| |
| // Abstraction for managed code's calling conventions |
| class ManagedRuntimeCallingConvention : public CallingConvention { |
| public: |
| explicit ManagedRuntimeCallingConvention(Method* method) : |
| CallingConvention(method) {} |
| |
| size_t FrameSize(); |
| |
| // Iterator interface |
| bool HasNext(); |
| void Next(); |
| bool IsCurrentParamAReference(); |
| bool IsCurrentParamInRegister(); |
| bool IsCurrentParamOnStack(); |
| bool IsCurrentUserArg(); |
| size_t CurrentParamSize(); |
| ManagedRegister CurrentParamRegister(); |
| FrameOffset CurrentParamStackOffset(); |
| |
| DISALLOW_COPY_AND_ASSIGN(ManagedRuntimeCallingConvention); |
| }; |
| |
| // Abstraction for JNI calling conventions |
| // | incoming stack args | <-- Prior SP |
| // | { Return address } | (x86) |
| // | { Return value spill } | (live on return slow paths) |
| // | { Stack Indirect Ref. | |
| // | Table... | |
| // | num. refs./link } | (here to prior SP is frame size) |
| // | { Spill area } | (ARM) |
| // | Method* | <-- Anchor SP written to thread |
| // | { Outgoing stack args | |
| // | ... } | <-- SP at point of call |
| // | Native frame | |
| class JniCallingConvention : public CallingConvention { |
| public: |
| explicit JniCallingConvention(Method* native_method) |
| : CallingConvention(native_method) { |
| ComputeRegsToSpillPreCall(spill_regs_); |
| } |
| |
| // 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. |
| size_t FrameSize(); |
| // Offset within the frame of the return pc |
| size_t ReturnPcOffset(); |
| // Size of outgoing arguments, including alignment |
| size_t OutArgSize(); |
| // Number of references in stack indirect reference table |
| size_t ReferenceCount(); |
| // Size of area used to hold spilled registers |
| size_t SpillAreaSize(); |
| // Location where the return value of a call can be squirreled if another |
| // call is made following the native call |
| FrameOffset ReturnValueSaveLocation(); |
| |
| // Registers that must be spilled (due to clobbering) before the call into |
| // the native routine |
| const std::vector<ManagedRegister>& RegsToSpillPreCall() { |
| return spill_regs_; |
| } |
| |
| // Returns true if the register will be clobbered by an outgoing |
| // argument value. |
| bool IsOutArgRegister(ManagedRegister reg); |
| |
| // Iterator interface |
| bool HasNext(); |
| void Next(); |
| bool IsCurrentParamAReference(); |
| bool IsCurrentParamInRegister(); |
| bool IsCurrentParamOnStack(); |
| size_t CurrentParamSize(); |
| ManagedRegister CurrentParamRegister(); |
| FrameOffset CurrentParamStackOffset(); |
| |
| // Iterator interface extension for JNI |
| FrameOffset CurrentParamSirtEntryOffset(); |
| |
| // Position of SIRT and interior fields |
| FrameOffset SirtOffset() { |
| return FrameOffset(displacement_.Int32Value() + |
| SpillAreaSize() + |
| kPointerSize); // above Method* |
| } |
| FrameOffset SirtNumRefsOffset() { |
| return FrameOffset(SirtOffset().Int32Value() + |
| StackIndirectReferenceTable::NumberOfReferencesOffset()); |
| } |
| FrameOffset SirtLinkOffset() { |
| return FrameOffset(SirtOffset().Int32Value() + |
| StackIndirectReferenceTable::LinkOffset()); |
| } |
| |
| private: |
| // Named iterator positions |
| enum IteratorPos { |
| kJniEnv = 0, |
| kObjectOrClass = 1 |
| }; |
| |
| // Number of stack slots for outgoing arguments, above which the SIRT is |
| // located |
| size_t NumberOfOutgoingStackArgs(); |
| |
| // Compute registers for RegsToSpillPreCall |
| void ComputeRegsToSpillPreCall(std::vector<ManagedRegister>& regs); |
| |
| // Extra registers to spill before the call into native |
| std::vector<ManagedRegister> spill_regs_; |
| |
| static size_t NumberOfExtraArgumentsForJni(const Method* method); |
| DISALLOW_COPY_AND_ASSIGN(JniCallingConvention); |
| }; |
| |
| } // namespace art |
| |
| #endif // ART_SRC_CALLING_CONVENTION_H_ |