| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- #if defined(ASMJS_PLAT) || defined(ENABLE_WASM)
- namespace WAsmJs
- {
- static const int DOUBLE_SLOTS_SPACE = (sizeof(double) / sizeof(Js::Var)); // 2 in x86 and 1 in x64
- static const double FLOAT_SLOTS_SPACE = (sizeof(float) / (double)sizeof(Js::Var)); // 1 in x86 and 0.5 in x64
- static const double INT_SLOTS_SPACE = (sizeof(int) / (double)sizeof(Js::Var)); // 1 in x86 and 0.5 in x64
- static const double SIMD_SLOTS_SPACE = (sizeof(SIMDValue) / sizeof(Js::Var)); // 4 in x86 and 2 in x64
- #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
- void TraceAsmJsArgsIn(Js::Var function, int n, ...);
- #endif
- typedef Js::RegSlot RegSlot;
- uint32 ConvertOffset(uint32 ptr, uint32 fromSize, uint32 toSize);
- template<typename ToType> uint32 ConvertOffset(uint32 ptr, uint32 fromSize)
- {
- return ConvertOffset(ptr, fromSize, sizeof(ToType));
- }
- template<typename FromType, typename ToType> uint32 ConvertOffset(uint32 ptr)
- {
- return ConvertOffset(ptr, sizeof(FromType), sizeof(ToType));
- }
- template<typename T> uint32 ConvertToJsVarOffset(uint32 ptr)
- {
- return ConvertOffset<T, Js::Var>(ptr);
- }
- template<typename T> uint32 ConvertFromJsVarOffset(uint32 ptr)
- {
- return ConvertOffset<Js::Var, T>(ptr);
- }
- struct EmitInfoBase
- {
- EmitInfoBase(RegSlot location_) : location(location_) {}
- EmitInfoBase() : location(Js::Constants::NoRegister) {}
- RegSlot location;
- };
- enum Types
- {
- INT32,
- INT64,
- FLOAT32,
- FLOAT64,
- SIMD,
- LIMIT
- };
- const Types FirstType = (Types)0;
- const Types LastType = (Types)(LIMIT - 1);
- uint32 GetTypeByteSize(Types type);
- Types FromIRType(IRType irType);
- /// Register space for const, parameters, variables and tmp values
- /// --------------------------------------------------------
- /// | Reserved | Consts | Parameters | Variables | Tmp
- /// --------------------------------------------------------
- /// Cannot allocate in any different order
- class RegisterSpace
- {
- // Total number of register allocated
- RegSlot mRegisterCount;
- // location of the first temporary register and last variable + 1
- RegSlot mFirstTmpReg;
- // Location of the next register to be allocated
- RegSlot mNextLocation;
- // number of const, includes the reserved slots
- RegSlot mNbConst;
- public:
- // Constructor
- RegisterSpace(RegSlot reservedSlotsCount = 0) :
- mRegisterCount( reservedSlotsCount )
- , mFirstTmpReg( reservedSlotsCount )
- , mNextLocation( reservedSlotsCount )
- , mNbConst( reservedSlotsCount )
- {
- }
- // Get the number of const allocated
- RegSlot GetConstCount() const { return mNbConst; }
- // Get the location of the first temporary register
- RegSlot GetFirstTmpRegister() const{ return mFirstTmpReg; }
- // Get the total number of temporary register allocated
- RegSlot GetTmpCount() const { return mRegisterCount-mFirstTmpReg; }
- // Get number of local variables
- RegSlot GetVarCount() const { return mFirstTmpReg - mNbConst; }
- // Get the total number of variable allocated ( including temporaries )
- RegSlot GetTotalVarCount() const { return mRegisterCount - mNbConst; }
- RegSlot GetRegisterCount() const { return mRegisterCount; }
- // Acquire a location for a register. Use only for arguments and Variables
- RegSlot AcquireRegister()
- {
- // Makes sure no temporary register have been allocated yet
- Assert(mFirstTmpReg == mRegisterCount && mNextLocation == mFirstTmpReg);
- ++mFirstTmpReg;
- ++mRegisterCount;
- return mNextLocation++;
- }
- // Acquire a location for a constant
- RegSlot AcquireConstRegister()
- {
- ++mNbConst;
- return AcquireRegister();
- }
- // Acquire a location for a temporary register
- RegSlot AcquireTmpRegister()
- {
- // Make sure this function is called correctly
- Assert(mNextLocation <= mRegisterCount && mNextLocation >= mFirstTmpReg);
- // Allocate a new temp pseudo-register, increasing the locals count if necessary.
- if(mNextLocation == mRegisterCount)
- {
- ++mRegisterCount;
- }
- #if DBG_DUMP
- PrintTmpRegisterAllocation(mNextLocation);
- #endif
- return mNextLocation++;
- }
- // Release a location for a temporary register, must be the last location acquired
- void ReleaseTmpRegister( RegSlot tmpReg )
- {
- // make sure the location released is valid
- Assert(tmpReg != Js::Constants::NoRegister);
- // Put this reg back on top of the temp stack (if it's a temp).
- if( this->IsTmpReg( tmpReg ) )
- {
- Assert( tmpReg == this->mNextLocation - 1 );
- #if DBG_DUMP
- PrintTmpRegisterAllocation(mNextLocation - 1, true);
- #endif
- mNextLocation--;
- }
- }
- // Checks if the register is a temporary register
- bool IsTmpReg(RegSlot tmpReg)
- {
- Assert(mFirstTmpReg != Js::Constants::NoRegister);
- return !IsConstReg(tmpReg) && tmpReg >= mFirstTmpReg;
- }
- // Checks if the register is a const register
- bool IsConstReg(RegSlot reg)
- {
- // a register is const if it is between the first register and the end of consts
- return reg < mNbConst && reg != 0;
- }
- // Checks if the register is a variable register
- bool IsVarReg(RegSlot reg)
- {
- // a register is a var if it is between the last const and the end
- // equivalent to reg>=mNbConst && reg<mRegisterCount
- // forcing unsigned, if reg < mNbConst then reg-mNbConst = 0xFFFFF..
- return (uint32)(reg - mNbConst) < (uint32)(mRegisterCount - mNbConst);
- }
- // Releases a location if its a temporary, safe to call with any expression
- void ReleaseLocation(const EmitInfoBase *pnode)
- {
- // Release the temp assigned to this expression so it can be re-used.
- if(pnode && pnode->location != Js::Constants::NoRegister)
- {
- ReleaseTmpRegister(pnode->location);
- }
- }
- // Checks if the location points to a temporary register
- bool IsTmpLocation(const EmitInfoBase* pnode)
- {
- if(pnode && pnode->location != Js::Constants::NoRegister)
- {
- return IsTmpReg(pnode->location);
- }
- return false;
- }
- // Checks if the location points to a constant register
- bool IsConstLocation(const EmitInfoBase* pnode)
- {
- if(pnode && pnode->location != Js::Constants::NoRegister)
- {
- return IsConstReg(pnode->location);
- }
- return false;
- }
- // Checks if the location points to a variable register
- bool IsVarLocation(const EmitInfoBase* pnode)
- {
- if(pnode && pnode->location != Js::Constants::NoRegister)
- {
- return IsVarReg(pnode->location);
- }
- return false;
- }
- // Checks if the location is valid (within bounds of already allocated registers)
- bool IsValidLocation(const EmitInfoBase* pnode)
- {
- if(pnode && pnode->location != Js::Constants::NoRegister)
- {
- return pnode->location < mRegisterCount;
- }
- return false;
- }
- template<typename T> static Types GetRegisterSpaceType();
- #if DBG_DUMP
- // Used for debugging
- Types mType;
- static void GetTypeDebugName(Types type, char16* buf, uint bufsize, bool shortName = false);
- void PrintTmpRegisterAllocation(RegSlot loc, bool deallocation = false);
- #endif
- };
- struct TypedConstSourcesInfo
- {
- uint32 srcByteOffsets[WAsmJs::LIMIT];
- uint32 bytesUsed;
- };
- struct TypedSlotInfo
- {
- TypedSlotInfo(): constCount(0), varCount(0), tmpCount(0), byteOffset(0), constSrcByteOffset(0) { }
- Field(uint32) constCount;
- Field(uint32) varCount;
- Field(uint32) tmpCount;
- // Offset in bytes from the start of InterpreterStack::m_localSlot
- Field(uint32) byteOffset;
- // Offset in bytes from the start of the const table before shuffling (InterpreterStackFrame::AlignMemoryForAsmJs())
- Field(uint32) constSrcByteOffset;
- };
- typedef RegisterSpace*(*AllocateRegisterSpaceFunc)(ArenaAllocator*, WAsmJs::Types);
- class TypedRegisterAllocator
- {
- uint32 mExcludedMask;
- RegisterSpace* mTypeSpaces[WAsmJs::LIMIT];
- public:
- TypedRegisterAllocator(ArenaAllocator* allocator, AllocateRegisterSpaceFunc allocateFunc, uint32 excludedMask = 0);
- void CommitToFunctionInfo(Js::AsmJsFunctionInfo* funcInfo, Js::FunctionBody* body) const;
- void CommitToFunctionBody(Js::FunctionBody* body);
- TypedConstSourcesInfo GetConstSourceInfos() const;
- bool IsTypeExcluded(Types type) const;
- #if DBG_DUMP
- void DumpLocalsInfo() const;
- // indexes' array size must be WAsmJs::RegisterSpace::LIMIT
- void GetArgumentStartIndex(uint32* indexes) const;
- #endif
- RegisterSpace* GetRegisterSpace(Types type) const;
- private:
- bool IsValidType(Types type) const;
- };
- };
- #endif
|