diff options
author | 2013-07-12 13:46:57 -0700 | |
---|---|---|
committer | 2013-07-12 17:49:01 -0700 | |
commit | 7940e44f4517de5e2634a7e07d58d0fb26160513 (patch) | |
tree | ac90242d96229a6942f6e24ab137bc1f8f2e0025 /compiler/jni/quick/calling_convention.h | |
parent | 5cd9e3b122f276f610980cbaf0d2ad6ed4cd9088 (diff) |
Create separate Android.mk for main build targets
The runtime, compiler, dex2oat, and oatdump now are in seperate trees
to prevent dependency creep. They can now be individually built
without rebuilding the rest of the art projects. dalvikvm and jdwpspy
were already this way. Builds in the art directory should behave as
before, building everything including tests.
Change-Id: Ic6b1151e5ed0f823c3dd301afd2b13eb2d8feb81
Diffstat (limited to 'compiler/jni/quick/calling_convention.h')
-rw-r--r-- | compiler/jni/quick/calling_convention.h | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h new file mode 100644 index 0000000000..121d1f80ae --- /dev/null +++ b/compiler/jni/quick/calling_convention.h @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_SRC_OAT_JNI_CALLING_CONVENTION_H_ +#define ART_SRC_OAT_JNI_CALLING_CONVENTION_H_ + +#include <vector> +#include "oat/utils/managed_register.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 shorty_[0] == 'L'; } + + Primitive::Type GetReturnType() const { + return Primitive::GetType(shorty_[0]); + } + + size_t SizeOfReturnValue() const { + size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[0])); + if (result >= 1 && result < 4) { + result = 4; + } + return result; + } + + // Register that holds result of this method invocation. + 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: + CallingConvention(bool is_static, bool is_synchronized, const char* shorty) + : displacement_(0), is_static_(is_static), is_synchronized_(is_synchronized), + shorty_(shorty) { + num_args_ = (is_static ? 0 : 1) + strlen(shorty) - 1; + num_ref_args_ = is_static ? 0 : 1; // The implicit this pointer. + num_long_or_double_args_ = 0; + for (size_t i = 1; i < strlen(shorty); i++) { + char ch = shorty_[i]; + if (ch == 'L') { + num_ref_args_++; + } else if ((ch == 'D') || (ch == 'J')) { + num_long_or_double_args_++; + } + } + } + + bool IsStatic() const { + return is_static_; + } + bool IsSynchronized() const { + return is_synchronized_; + } + bool IsParamALongOrDouble(unsigned int param) const { + DCHECK_LT(param, NumArgs()); + if (IsStatic()) { + param++; // 0th argument must skip return value at start of the shorty + } else if (param == 0) { + return false; // this argument + } + char ch = shorty_[param]; + return (ch == 'J' || ch == 'D'); + } + bool IsParamAReference(unsigned int param) const { + DCHECK_LT(param, NumArgs()); + if (IsStatic()) { + param++; // 0th argument must skip return value at start of the shorty + } else if (param == 0) { + return true; // this argument + } + return shorty_[param] == 'L'; + } + size_t NumArgs() const { + return num_args_; + } + size_t NumLongOrDoubleArgs() const { + return num_long_or_double_args_; + } + size_t NumReferenceArgs() const { + return num_ref_args_; + } + size_t ParamSize(unsigned int param) const { + DCHECK_LT(param, NumArgs()); + if (IsStatic()) { + param++; // 0th argument must skip return value at start of the shorty + } else if (param == 0) { + return kPointerSize; // this argument + } + size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[param])); + if (result >= 1 && result < 4) { + result = 4; + } + return result; + } + const char* GetShorty() const { + return shorty_.c_str(); + } + // 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: + const bool is_static_; + const bool is_synchronized_; + std::string shorty_; + size_t num_args_; + size_t num_ref_args_; + size_t num_long_or_double_args_; +}; + +// 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(bool is_static, bool is_synchronized, + const char* shorty, + InstructionSet instruction_set); + + // 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() {} + + // Registers to spill to caller's out registers on entry. + virtual const std::vector<ManagedRegister>& EntrySpills() = 0; + + protected: + ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty) + : CallingConvention(is_static, is_synchronized, shorty) {} +}; + +// 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(bool is_static, bool is_synchronized, const char* shorty, + 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; + // 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; + // Register that holds result if it is integer. + virtual ManagedRegister IntReturnRegister() = 0; + + // 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; + + // 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(bool is_static, bool is_synchronized, const char* shorty) + : CallingConvention(is_static, is_synchronized, shorty) {} + + // Number of stack slots for outgoing arguments, above which the SIRT is + // located + virtual size_t NumberOfOutgoingStackArgs() = 0; + + protected: + size_t NumberOfExtraArgumentsForJni(); +}; + +} // namespace art + +#endif // ART_SRC_OAT_JNI_CALLING_CONVENTION_H_ |