| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- //-------------------------------------------------------------------------------------------------------
- // 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 OpCode
- ///
- /// OpCode defines the set of p-code instructions available for byte-code.
- ///
- ///----------------------------------------------------------------------------
- enum class OpCode : ushort
- {
- #define DEF_OP(x, y, ...) x,
- #include "OpCodeList.h"
- MaxByteSizedOpcodes = 255,
- #include "ExtendedOpCodeList.h"
- ByteCodeLast,
- #if ENABLE_NATIVE_CODEGEN
- #include "BackendOpCodeList.h"
- #endif
- #undef DEF_OP
- Count // Number of operations
- };
- inline OpCode operator+(OpCode o1, OpCode o2) { return (OpCode)((uint)o1 + (uint)o2); }
- inline uint operator+(OpCode o1, uint i) { return ((uint)o1 + i); }
- inline uint operator+(uint i, OpCode &o2) { return (i + (uint)o2); }
- inline OpCode operator++(OpCode &o) { return o = (OpCode)(o + 1U); }
- inline OpCode operator++(OpCode &o, int) { OpCode prev_o = o; o = (OpCode)(o + 1U); return prev_o; }
- inline OpCode operator-(OpCode o1, OpCode o2) { return (OpCode)((uint)o1 - (uint)o2); }
- inline uint operator-(OpCode o1, uint i) { return ((uint)o1 - i); }
- inline uint operator-(uint i, OpCode &o2) { return (i - (uint)o2); }
- inline OpCode operator--(OpCode &o) { return o = (OpCode)(o - 1U); }
- inline OpCode operator--(OpCode &o, int) { return o = (OpCode)(o - 1U); }
- inline uint operator<<(OpCode o1, uint i) { return ((uint)o1 << i); }
- inline OpCode& operator+=(OpCode &o, uint i) { return (o = (OpCode)(o + i)); }
- inline OpCode& operator-=(OpCode &o, uint i) { return (o = (OpCode)(o - i)); }
- inline bool operator==(OpCode &o, uint i) { return ((uint)(o) == i); }
- inline bool operator==(uint i, OpCode &o) { return (i == (uint)(o)); }
- inline bool operator!=(OpCode &o, uint i) { return ((uint)(o) != i); }
- inline bool operator!=(uint i, OpCode &o) { return (i != (uint)(o)); }
- inline bool operator<(OpCode &o, uint i) { return ((uint)(o) < i); }
- inline bool operator<(uint i, OpCode &o) { return (i < (uint)(o)); }
- inline bool operator>(OpCode &o, uint i) { return ((uint)(o) > i); }
- inline bool operator>(uint i, OpCode &o) { return (i > (uint)(o)); }
- #if ENABLE_NATIVE_CODEGEN
- inline bool IsSimd128Opcode(OpCode o) { return (o > Js::OpCode::Simd128_Start && o < Js::OpCode::Simd128_End) || (o > Js::OpCode::Simd128_Start_Extend && o < Js::OpCode::Simd128_End_Extend); }
- inline uint Simd128OpcodeCount() { return (uint)(Js::OpCode::Simd128_End - Js::OpCode::Simd128_Start) + 1 + (uint)(Js::OpCode::Simd128_End_Extend - Js::OpCode::Simd128_Start_Extend) + 1; }
- inline bool IsSimd128Load(OpCode o){ return o == Js::OpCode::Simd128_LdArr_I4 || o == Js::OpCode::Simd128_LdArr_F4; }
- inline bool IsSimd128Store(OpCode o){ return o == Js::OpCode::Simd128_StArr_I4 || o == Js::OpCode::Simd128_StArr_F4; }
- inline bool IsSimd128LoadStore(OpCode o) { return IsSimd128Load(o) || IsSimd128Store(o); }
- #endif
- ///----------------------------------------------------------------------------
- ///
- /// enum OpLayoutType
- ///
- /// OpLayoutType defines a set of layouts available for OpCodes. These layouts
- /// correspond to "OpLayout" structs defined below, such as "OpLayoutReg1".
- ///
- ///----------------------------------------------------------------------------
- BEGIN_ENUM_UINT(OpLayoutType)
- // This define only one enum for each layout type, but not for each layout variant
- #define LAYOUT_TYPE(x) x,
- #define LAYOUT_TYPE_WMS LAYOUT_TYPE
- #include "LayoutTypes.h"
- Count,
- END_ENUM_UINT()
- ///----------------------------------------------------------------------------
- ///
- /// struct OpLayoutXYZ
- ///
- /// OpLayoutXYZ structs define the standard patterns used to layout each
- /// OpCode's arguments.
- ///
- /// Set up packing:
- /// - Since we are reading / writing from a byte-stream, and we want everything
- /// to be tightly aligned with no unintended spaces, change to 'byte'
- /// packing.
- /// - On processors with alignment requirements, this will automatically
- /// generate read / write code to handle 'unaligned' access.
- ///
- /// - 3/9/10: Changing the layouts to make all fields well-aligned. This involves
- /// reducing the RegSlot from 4 bytes to 2, increasing the OpCode from 1 byte to 2,
- /// reordering fields, and adding pads where appropriate. Note that we assume all
- /// layouts are preceded by a 2-byte op. The orderings and padding will need to
- /// be revisited for Win64.
- ///
- /// - 5/2: X86-64 alignment: Changing code to expect all opcode layout structs
- /// to be aligned on 4 byte boundaries (on I386 and x86-64). This aligns all
- /// members on their natural boundaries except for Call and Regex which require
- /// padding before the pointers on x86-64.
- ///
- /// - 09/12: Adding one-byte RegSlot based OpLayout. These remove all the paddings to be
- /// able to compress the size. Also remove paddings for non ARM build
- ///
- /// - 08/22/2011: Removed paddings for ARM & x64 as well as both support unaligned access
- /// There is still paddings to make sure every opcode starts at 2 byte boundary to avoid
- /// pathological cases.
- /// Note: RegSlot is changed to 4 byte instead of 1 byte in this change.
- ///
- ///----------------------------------------------------------------------------
- #pragma pack(push, 1)
- template <typename SizePolicy>
- struct OpLayoutT_Reg1 // R0 <- op
- {
- typename SizePolicy::RegSlotType R0;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Reg1Unsigned1 // R0 <- op
- {
- typename SizePolicy::RegSlotType R0;
- typename SizePolicy::UnsignedType C1;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Reg2 // R0 <- op R1
- {
- typename SizePolicy::RegSlotType R0;
- typename SizePolicy::RegSlotType R1;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Reg3 // R0 <- R1 op R2 -- or -- R0 op R1 <- R2
- {
- typename SizePolicy::RegSlotType R0;
- typename SizePolicy::RegSlotType R1;
- typename SizePolicy::RegSlotType R2;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Reg3C // R0 <- R1 op R2 with space for FastPath
- {
- typename SizePolicy::RegSlotType R0;
- typename SizePolicy::RegSlotType R1;
- typename SizePolicy::RegSlotType R2;
- typename SizePolicy::CacheIdType inlineCacheIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Reg2B1
- {
- typename SizePolicy::RegSlotType R0;
- typename SizePolicy::RegSlotType R1;
- byte B2;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Reg3B1
- {
- typename SizePolicy::RegSlotType R0;
- typename SizePolicy::RegSlotType R1;
- typename SizePolicy::RegSlotType R2;
- byte B3;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Reg4 // R0 <- R1 op R2 op R3
- {
- typename SizePolicy::RegSlotType R0;
- typename SizePolicy::RegSlotType R1;
- typename SizePolicy::RegSlotType R2;
- typename SizePolicy::RegSlotType R3;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Reg5 // R0 <- R1 op R2 op R3 op R4
- {
- typename SizePolicy::RegSlotType R0;
- typename SizePolicy::RegSlotType R1;
- typename SizePolicy::RegSlotType R2;
- typename SizePolicy::RegSlotType R3;
- typename SizePolicy::RegSlotType R4;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ArgNoSrc // OutArg
- {
- typename SizePolicy::ArgSlotType Arg;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Arg // OutArg <- Reg -- or -- Reg <- InArg
- {
- typename SizePolicy::ArgSlotType Arg;
- typename SizePolicy::RegSlotType Reg;
- };
- struct OpLayoutBr // goto Offset
- {
- JumpOffset RelativeJumpOffset;
- };
- struct OpLayoutBrS // if (op val) goto Offset
- {
- JumpOffset RelativeJumpOffset;
- byte val;
- };
- template <typename SizePolicy>
- struct OpLayoutT_BrReg1 // if (op R1) goto Offset
- {
- JumpOffset RelativeJumpOffset;
- typename SizePolicy::RegSlotType R1;
- };
- template <typename SizePolicy>
- struct OpLayoutT_BrReg1Unsigned1
- {
- JumpOffset RelativeJumpOffset;
- typename SizePolicy::RegSlotType R1;
- typename SizePolicy::RegSlotType C2;
- };
- template <typename SizePolicy>
- struct OpLayoutT_BrReg2 // if (R1 op R2) goto Offset
- {
- JumpOffset RelativeJumpOffset;
- typename SizePolicy::RegSlotType R1;
- typename SizePolicy::RegSlotType R2;
- };
- struct OpLayoutBrProperty // if (R1.id) goto Offset
- {
- JumpOffset RelativeJumpOffset;
- RegSlot Instance;
- PropertyIdIndexType PropertyIdIndex;
- };
- struct OpLayoutBrLocalProperty // if (id) goto Offset
- {
- JumpOffset RelativeJumpOffset;
- PropertyIdIndexType PropertyIdIndex;
- };
- struct OpLayoutBrEnvProperty // if ([1].id) goto Offset
- {
- JumpOffset RelativeJumpOffset;
- PropertyIdIndexType PropertyIdIndex;
- int32 SlotIndex;
- };
- #ifdef BYTECODE_BRANCH_ISLAND
- struct OpLayoutBrLong
- {
- LongJumpOffset RelativeJumpOffset;
- };
- #endif
- struct OpLayoutStartCall
- {
- ArgSlot ArgCount;
- };
- enum CallIExtendedOptions : byte
- {
- CallIExtended_None = 0,
- CallIExtended_SpreadArgs = 1 << 0 // This call has arguments that need to be spread
- };
- template <typename SizePolicy>
- struct OpLayoutT_CallI // Return = Function(ArgCount)
- {
- typename SizePolicy::ArgSlotType ArgCount;
- typename SizePolicy::RegSlotSType Return;
- typename SizePolicy::RegSlotType Function;
- };
- template <typename SizePolicy>
- struct OpLayoutT_CallIExtended : public OpLayoutT_CallI<SizePolicy>
- {
- CallIExtendedOptions Options;
- uint32 SpreadAuxOffset; // Valid with Options & CallIExtended_SpreadArgs
- };
- template <typename SizePolicy>
- struct OpLayoutT_CallIFlags : public OpLayoutT_CallI<SizePolicy>
- {
- CallFlags callFlags;
- };
- template <typename SizePolicy>
- struct OpLayoutT_CallIWithICIndex : public OpLayoutT_CallI<SizePolicy>
- {
- InlineCacheIndex inlineCacheIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_CallIFlagsWithICIndex : public OpLayoutT_CallIWithICIndex<SizePolicy>
- {
- CallFlags callFlags;
- };
- template <typename SizePolicy>
- struct OpLayoutT_CallIExtendedFlags : public OpLayoutT_CallIExtended<SizePolicy>
- {
- CallFlags callFlags;
- };
- template <typename SizePolicy>
- struct OpLayoutT_CallIExtendedWithICIndex : public OpLayoutT_CallIExtended<SizePolicy>
- {
- InlineCacheIndex inlineCacheIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_CallIExtendedFlagsWithICIndex : public OpLayoutT_CallIExtendedWithICIndex<SizePolicy>
- {
- CallFlags callFlags;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Class // class _ extends Extends { Constructor(...) { ... } }
- {
- typename SizePolicy::RegSlotType Constructor;
- typename SizePolicy::RegSlotSType Extends;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementU // Instance.PropertyIndex = <some constant value>. e.g. undefined
- {
- typename SizePolicy::RegSlotType Instance;
- typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementScopedU // [env].PropertyIndex = <some constant value>. e.g. undefined
- {
- typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementRootU // Root.PropertyIndex = <some constant value>. e.g. undefined
- {
- typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementC // Value = Instance.PropertyIndex or Instance.PropertyIndex = Value
- {
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::RegSlotType Instance;
- typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementScopedC // Value = [env].PropertyIndex or [env].PropertyIndex = Value
- {
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementSlot // Value = Instance[SlotIndex] or Instance[SlotIndex] = Value
- {
- typename SizePolicy::UnsignedType SlotIndex;
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::RegSlotType Instance;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementSlotI1
- {
- typename SizePolicy::UnsignedType SlotIndex;
- typename SizePolicy::RegSlotType Value;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementSlotI2
- {
- typename SizePolicy::UnsignedType SlotIndex1;
- typename SizePolicy::UnsignedType SlotIndex2;
- typename SizePolicy::RegSlotType Value;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementCP // As OpLayoutElementC, with space for a FastPath LoadPatch
- {
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::RegSlotType Instance;
- typename SizePolicy::CacheIdType inlineCacheIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementP // As OpLayoutElementCP, but with no base pointer
- {
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::CacheIdType inlineCacheIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementPIndexed // As OpLayoutElementCP, but with scope index instead of base pointer
- {
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::CacheIdType inlineCacheIndex;
- typename SizePolicy::UnsignedType scopeIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementRootCP // Same as ElementCP, but for root object
- {
- RootCacheId inlineCacheIndex;
- typename SizePolicy::RegSlotType Value;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementScopedC2 // [implied base].PropertyIndex = Value, Instance2
- {
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::RegSlotType Value2;
- typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementC2 // Instance.PropertyIndex = Value, Instance2
- {
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::RegSlotType Instance;
- typename SizePolicy::RegSlotType Value2;
- typename SizePolicy::PropertyIdIndexType PropertyIdIndex;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementI // Value = Instance[Element] or Instance[Element] = Value
- {
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::RegSlotType Instance;
- typename SizePolicy::RegSlotType Element;
- };
- template <typename SizePolicy>
- struct OpLayoutT_ElementUnsigned1 // Value = Instance[Element] or Instance[Element] = Value
- {
- typename SizePolicy::UnsignedType Element;
- typename SizePolicy::RegSlotType Value;
- typename SizePolicy::RegSlotType Instance;
- };
- struct OpLayoutW1
- {
- unsigned short C1;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Reg2Int1 // R0 <- func(R1, C1)
- {
- int32 C1;
- typename SizePolicy::RegSlotType R0;
- typename SizePolicy::RegSlotType R1;
- };
- struct OpLayoutAuxNoReg
- {
- uint32 Offset;
- int32 C1;
- };
- struct OpLayoutAuxiliary : public OpLayoutAuxNoReg // R0 <- Load(Offset, C1)
- {
- RegSlot R0;
- };
- struct OpLayoutReg2Aux : public OpLayoutAuxiliary // R0 <- Load(Offset, R1, C1)
- {
- RegSlot R1;
- };
- template <typename SizePolicy>
- struct OpLayoutT_Unsigned1
- {
- typename SizePolicy::UnsignedType C1;
- };
- // Dynamic profile layout wrapper
- template <typename LayoutType>
- struct OpLayoutDynamicProfile : public LayoutType
- {
- ProfileId profileId;
- };
- template <typename LayoutType>
- struct OpLayoutDynamicProfile2 : public LayoutType
- {
- ProfileId profileId;
- ProfileId profileId2;
- };
- // Generate the multi size layout type defs
- #define LAYOUT_TYPE_WMS(layout) \
- typedef OpLayoutT_##layout<LargeLayoutSizePolicy> OpLayout##layout##_Large; \
- typedef OpLayoutT_##layout<MediumLayoutSizePolicy> OpLayout##layout##_Medium; \
- typedef OpLayoutT_##layout<SmallLayoutSizePolicy> OpLayout##layout##_Small;
- // Generate the profiled type defs
- #define LAYOUT_TYPE_PROFILED(layout) \
- typedef OpLayoutDynamicProfile<OpLayout##layout> OpLayoutProfiled##layout;
- #define LAYOUT_TYPE_PROFILED2(layout) \
- typedef OpLayoutDynamicProfile2<OpLayout##layout> OpLayoutProfiled2##layout;
- #define LAYOUT_TYPE_PROFILED_WMS(layout) \
- LAYOUT_TYPE_WMS(layout) \
- LAYOUT_TYPE_PROFILED(layout##_Large) \
- LAYOUT_TYPE_PROFILED(layout##_Medium) \
- LAYOUT_TYPE_PROFILED(layout##_Small)
- #define LAYOUT_TYPE_PROFILED2_WMS(layout) \
- LAYOUT_TYPE_PROFILED_WMS(layout) \
- LAYOUT_TYPE_PROFILED2(layout##_Large) \
- LAYOUT_TYPE_PROFILED2(layout##_Medium) \
- LAYOUT_TYPE_PROFILED2(layout##_Small)
- #include "LayoutTypes.h"
- #pragma pack(pop)
- // Generate structure to automatically map layout to its info
- template <OpLayoutType::_E layout> struct OpLayoutInfo;
- #define LAYOUT_TYPE(layout) \
- CompileAssert(sizeof(OpLayout##layout) <= MaxLayoutSize); \
- template <> struct OpLayoutInfo<OpLayoutType::layout> \
- { \
- static const bool HasMultiSizeLayout = false; \
- };
- #define LAYOUT_TYPE_WMS(layout) \
- CompileAssert(sizeof(OpLayout##layout##_Large) <= MaxLayoutSize); \
- template <> struct OpLayoutInfo<OpLayoutType::layout> \
- { \
- static const bool HasMultiSizeLayout = true; \
- };
- #include "LayoutTypes.h"
- // Generate structure to automatically map opcode to its info
- // Also generate assert to make sure the layout and opcode use the same macro with and without multiple size layout
- template <OpCode opcode> struct OpCodeInfo;
- #define DEFINE_OPCODEINFO(op, layout, extended) \
- CompileAssert(!OpLayoutInfo<OpLayoutType::layout>::HasMultiSizeLayout); \
- template <> struct OpCodeInfo<OpCode::op> \
- { \
- static const OpLayoutType::_E Layout = OpLayoutType::layout; \
- static const bool HasMultiSizeLayout = false; \
- static const bool IsExtendedOpcode = extended; \
- typedef OpLayout##layout LayoutType; \
- };
- #define DEFINE_OPCODEINFO_WMS(op, layout, extended) \
- CompileAssert(OpLayoutInfo<OpLayoutType::layout>::HasMultiSizeLayout); \
- template <> struct OpCodeInfo<OpCode::op> \
- { \
- static const OpLayoutType::_E Layout = OpLayoutType::layout; \
- static const bool HasMultiSizeLayout = true; \
- static const bool IsExtendedOpcode = extended; \
- typedef OpLayout##layout##_Large LayoutType_Large; \
- typedef OpLayout##layout##_Medium LayoutType_Medium; \
- typedef OpLayout##layout##_Small LayoutType_Small; \
- };
- #define MACRO(op, layout, ...) DEFINE_OPCODEINFO(op, layout, false)
- #define MACRO_WMS(op, layout, ...) DEFINE_OPCODEINFO_WMS(op, layout, false)
- #define MACRO_EXTEND(op, layout, ...) DEFINE_OPCODEINFO(op, layout, true)
- #define MACRO_EXTEND_WMS(op, layout, ...) DEFINE_OPCODEINFO_WMS(op, layout, true)
- #include "OpCodes.h"
- #undef DEFINE_OPCODEINFO
- #undef DEFINE_OPCODEINFO_WMS
- } // namespace Js
|