| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- //-------------------------------------------------------------------------------------------------------
- // 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
- namespace Js
- {
- enum CallFlags : unsigned
- {
- CallFlags_None = 0,
- CallFlags_New = 1,
- CallFlags_Value = 2,
- CallFlags_Eval = 4,
- CallFlags_ExtraArg = 8,
- CallFlags_NotUsed = 0x10,
- CallFlags_Wrapped = 0x20,
- CallFlags_NewTarget = 0x40,
- CallFlags_InternalFrame = 0x80
- };
- ENUM_CLASS_HELPERS(CallFlags, unsigned)
- struct CallInfo
- {
- CallInfo() {}
- /*
- * Removed the copy constructor because it forced the 64 bit compiler
- * to pass this object by reference. Interpreter stack setup code expects
- * CallInfo to be passed by value.
- */
- explicit CallInfo(ArgSlot count)
- : Flags(CallFlags_None)
- , Count(count)
- #ifdef TARGET_64
- , unused(0)
- #endif
- {
- // Keeping this version to avoid the assert
- }
- // The bool is used to avoid the signature confusion between the ArgSlot and uint version of the constructor
- explicit CallInfo(uint count, bool unusedBool)
- : Flags(CallFlags_None)
- , Count(count)
- #ifdef TARGET_64
- , unused(0)
- #endif
- {
- AssertOrFailFastMsg(count < CallInfo::kMaxCountArgs, "Argument list too large");
- }
- CallInfo(CallFlags flags, uint count)
- : Flags(flags)
- , Count(count)
- #ifdef TARGET_64
- , unused(0)
- #endif
- {
- // Keeping this version to avoid the assert
- }
- CallInfo(VirtualTableInfoCtorEnum v)
- {
- }
- ArgSlot GetArgCountWithExtraArgs() const
- {
- return CallInfo::GetArgCountWithExtraArgs(this->Flags, this->Count);
- }
- uint GetLargeArgCountWithExtraArgs() const
- {
- return CallInfo::GetLargeArgCountWithExtraArgs(this->Flags, this->Count);
- }
- bool HasExtraArg() const
- {
- return CallInfo::HasExtraArg(this->Flags);
- }
- bool HasNewTarget() const
- {
- return CallInfo::HasNewTarget(this->Flags);
- }
- static ArgSlot GetArgCountWithExtraArgs(CallFlags flags, uint count);
- static uint GetLargeArgCountWithExtraArgs(CallFlags flags, uint count);
- static ArgSlot GetArgCountWithoutExtraArgs(CallFlags flags, ArgSlot count);
- static bool HasExtraArg(CallFlags flags)
- {
- // Generally HasNewTarget should not be true if CallFlags_ExtraArg is not set.
- Assert(!CallInfo::HasNewTarget(flags) || flags & CallFlags_ExtraArg);
- // we will still check HasNewTarget to be safe in case if above invariant does not hold.
- return (flags & CallFlags_ExtraArg) || CallInfo::HasNewTarget(flags);
- }
- static bool HasNewTarget(CallFlags flags)
- {
- return (flags & CallFlags_NewTarget) == CallFlags_NewTarget;
- }
- // New target value is passed as an extra argument which is nto included in the Count
- static Var GetNewTarget(CallFlags flag, Var* values, uint count)
- {
- if (HasNewTarget(flag))
- {
- return values[count];
- }
- else
- {
- AssertOrFailFast(count > 0);
- return values[0];
- }
- }
- // Assumes big-endian layout
- // If the size of the count is changed, change should happen at following places also
- // - scriptdirect.idl
- // - LowererMDArch::LoadInputParamCount
- //
- Field(unsigned) Count : 24;
- Field(CallFlags) Flags : 8;
- #ifdef TARGET_64
- Field(unsigned) unused : 32;
- #endif
- #if DBG
- bool operator==(CallInfo other) const
- {
- return this->Count == other.Count && this->Flags == other.Flags;
- }
- #endif
- public:
- static const ushort ksizeofCount;
- static const ushort ksizeofCallFlags;
- static const uint kMaxCountArgs;
- };
- struct InlineeCallInfo
- {
- // Assumes big-endian layout.
- uint Count : 4;
- #if TARGET_32
- uint InlineeStartOffset : 28;
- #else
- uint unused : 28;
- uint InlineeStartOffset;
- #endif
- static size_t const MaxInlineeArgoutCount = 0xF;
- #if TARGET_32
- static uint const ksizeofInlineeStartOffset = 28;
- #else
- static uint const ksizeofInlineeStartOffset = 32;
- #endif
- static uint const inlineeStartOffsetShiftCount = (sizeof(void*) * CHAR_BIT - Js::InlineeCallInfo::ksizeofInlineeStartOffset);
- static bool Encode(intptr_t &callInfo, size_t count, size_t offset)
- {
- const size_t offsetMask = ~(uint)0 >> (sizeof(uint) * CHAR_BIT - ksizeofInlineeStartOffset);
- const size_t countMask = 0x0000000F;
- if (count != (count & countMask))
- {
- return false;
- }
- if (offset != (offset & offsetMask))
- {
- return false;
- }
- callInfo = (offset << inlineeStartOffsetShiftCount) | count;
- return true;
- }
- void Clear()
- {
- this->Count = 0;
- this->InlineeStartOffset = 0;
- }
- };
- }
|