// Copyright 2011 Google Inc. All Rights Reserved. // Author: irogers@google.com (Ian Rogers) #ifndef ART_SRC_CALLING_CONVENTION_H_ #define ART_SRC_CALLING_CONVENTION_H_ #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(); // 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_position_ = 0; itr_longs_and_doubles_ = 0; } protected: explicit CallingConvention(Method* method) : displacement_(0), method_(method) {} const Method* GetMethod() const { return method_; } // position along argument list unsigned int itr_position_; // 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 IsCurrentParamPossiblyNull(); size_t CurrentParamSize(); ManagedRegister CurrentParamRegister(); FrameOffset CurrentParamStackOffset(); DISALLOW_COPY_AND_ASSIGN(ManagedRuntimeCallingConvention); }; // Abstraction for JNI calling conventions // | incoming stack args | <-- Prior SP // | { Spilled registers | // | & return address } | // | { Return value spill } | (live on return slow paths) // | { Stack Handle Block | // | ... | // | 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 | class JniCallingConvention : public CallingConvention { public: explicit JniCallingConvention(Method* native_method) : CallingConvention(native_method) {} // 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(); // Size of outgoing arguments, including alignment size_t OutArgSize(); // Number of handles in stack handle block size_t HandleCount(); // Location where the return value of a call can be squirreled if another // call is made following the native call FrameOffset ReturnValueSaveLocation(); // 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 CurrentParamHandleOffset(); // Position of stack handle block and interior fields FrameOffset ShbOffset() { return FrameOffset(displacement_.Int32Value() + kPointerSize); // above Method* } FrameOffset ShbNumRefsOffset() { return FrameOffset(ShbOffset().Int32Value() + StackHandleBlock::NumberOfReferencesOffset()); } FrameOffset ShbLinkOffset() { return FrameOffset(ShbOffset().Int32Value() + StackHandleBlock::LinkOffset()); } private: // Named iterator positions enum IteratorPos { kJniEnv = 0, kObjectOrClass = 1 }; // Number of stack slots for outgoing arguments, above which handles are // located size_t NumberOfOutgoingStackArgs(); DISALLOW_COPY_AND_ASSIGN(JniCallingConvention); }; } // namespace art #endif // ART_SRC_CALLING_CONVENTION_H_