text: //-------------------------------------------------------------------------------------------------------
  // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  //-------------------------------------------------------------------------------------------------------
  
  #pragma once
  
  struct GlobalBailOutRecordDataTable;
  struct GlobalBailOutRecordDataRow;
  
  class BailOutInfo
  {
  public:
  
  #ifdef _M_IX86
      typedef struct
      {
          IR::Instr * instr;
          uint argCount;
          uint argRestoreAdjustCount;
          bool isOrphanedCall;
      } StartCallInfo;
  #else
      typedef uint StartCallInfo;
  #endif
  
      BailOutInfo(uint32 bailOutOffset, Func* bailOutFunc) :
          bailOutOffset(bailOutOffset), bailOutFunc(bailOutFunc),
          byteCodeUpwardExposedUsed(nullptr), polymorphicCacheIndex((uint)-1), startCallCount(0), startCallInfo(nullptr), bailOutInstr(nullptr),
          totalOutParamCount(0), argOutSyms(nullptr), bailOutRecord(nullptr), wasCloned(false), isInvertedBranch(false), sharedBailOutKind(true), isLoopTopBailOutInfo(false),
          outParamInlinedArgSlot(nullptr), liveVarSyms(nullptr), liveLosslessInt32Syms(nullptr), liveFloat64Syms(nullptr),
          branchConditionOpnd(nullptr),
          stackLiteralBailOutInfoCount(0), stackLiteralBailOutInfo(nullptr)
      {
          Assert(bailOutOffset != Js::Constants::NoByteCodeOffset);
  #ifdef _M_IX86
          outParamFrameAdjustArgSlot = nullptr;
  #endif
  #if DBG
          wasCopied = false;
  #endif
          this->capturedValues = JitAnew(bailOutFunc->m_alloc, CapturedValues);
          this->capturedValues->refCount = 1;
          this->usedCapturedValues.argObjSyms = nullptr;
      }
      void Clear(JitArenaAllocator * allocator);
  
      void FinalizeBailOutRecord(Func * func);
  #ifdef MD_GROW_LOCALS_AREA_UP
      void FinalizeOffsets(__in_ecount(count) int * offsets, uint count, Func *func, BVSparse<JitArenaAllocator> *bvInlinedArgSlot);
  #endif
  
      void RecordStartCallInfo(uint i, IR::Instr *instr);
      uint GetStartCallOutParamCount(uint i) const;
  #ifdef _M_IX86
      bool NeedsStartCallAdjust(uint i, const IR::Instr * instr) const;
      void UnlinkStartCall(const IR::Instr * instr);
  #endif
  
      static bool IsBailOutOnImplicitCalls(IR::BailOutKind kind)
      {
          const IR::BailOutKind kindMinusBits = kind & ~IR::BailOutKindBits;
          return kindMinusBits == IR::BailOutOnImplicitCalls ||
              kindMinusBits == IR::BailOutOnImplicitCallsPreOp;
      }
  
  #if DBG
      static bool IsBailOutHelper(IR::JnHelperMethod helper);
  #endif
      bool wasCloned;
      bool isInvertedBranch;
      bool sharedBailOutKind;
      bool isLoopTopBailOutInfo;
  
  #if DBG
      bool wasCopied;
  #endif
      uint32 bailOutOffset;
      BailOutRecord * bailOutRecord;
      CapturedValues* capturedValues;                                      // Values we know about after forward pass
      CapturedValues usedCapturedValues;                                  // Values that need to be restored in the bail out
      BVSparse<JitArenaAllocator> * byteCodeUpwardExposedUsed;            // Non-constant stack syms that needs to be restored in the bail out
      uint polymorphicCacheIndex;
      uint startCallCount;
      uint totalOutParamCount;
      Func ** startCallFunc;
  
      StartCallInfo * startCallInfo;
      StackSym ** argOutSyms;
  
      struct StackLiteralBailOutInfo
      {
          StackSym * stackSym;
          uint initFldCount;
      };
      uint stackLiteralBailOutInfoCount;
      StackLiteralBailOutInfo * stackLiteralBailOutInfo;
  
      BVSparse<JitArenaAllocator> * liveVarSyms;
      BVSparse<JitArenaAllocator> * liveLosslessInt32Syms;                // These are only the live int32 syms that fully represent the var-equivalent sym's value (see GlobOpt::FillBailOutInfo)
      BVSparse<JitArenaAllocator> * liveFloat64Syms;
      int * outParamOffsets;
  
      BVSparse<JitArenaAllocator> * outParamInlinedArgSlot;
  #ifdef _M_IX86
      BVSparse<JitArenaAllocator> * outParamFrameAdjustArgSlot;
      BVFixed * inlinedStartCall;
  #endif
  
  #ifdef MD_GROW_LOCALS_AREA_UP
      // Use a bias to guarantee that all sym offsets are non-zero.
      static const int32 StackSymBias = MachStackAlignment;
  #endif
  
      // The actual bailout instr, this is normally the instr that has the bailout info.
      // 1) If we haven't generated bailout (which happens in lowerer) for this bailout info, this is either of:
      // - the instr that has bailout info.
      // - in case of shared bailout this will be the BailTarget instr (corresponds to the call to SaveRegistersAndBailOut,
      //   while other instrs sharing bailout info will just have checks and JMP to BailTarget).
      // 2) After we generated bailout, this becomes label instr. In case of shared bailout other instrs JMP to this label.
      IR::Instr * bailOutInstr;
  
  #if ENABLE_DEBUG_CONFIG_OPTIONS
      Js::OpCode bailOutOpcode;
  #endif
      Func * bailOutFunc;
      IR::Opnd * branchConditionOpnd;
  
      template<class Fn>
      void IterateArgOutSyms(Fn callback)
      {
          uint argOutIndex = 0;
          for(uint i = 0; i < this->startCallCount; i++)
          {
              uint outParamCount = this->GetStartCallOutParamCount(i);
              for(uint j = 0; j < outParamCount; j++)
              {
                  StackSym* sym = this->argOutSyms[argOutIndex];
                  if(sym)
                  {
                      callback(argOutIndex, i + sym->GetArgSlotNum(), sym);
                  }
                  argOutIndex++;
              }
          }
      }
  };
  
  class BailOutRecord
  {
  public:
      BailOutRecord(uint32 bailOutOffset, uint bailOutCacheIndex, IR::BailOutKind kind, Func *bailOutFunc);
      static Js::Var BailOut(BailOutRecord const * bailOutRecord);
      static Js::Var BailOutFromFunction(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord, void * returnAddress, void * argoutRestoreAddress, Js::ImplicitCallFlags savedImplicitCallFlags);
      static uint32 BailOutFromLoopBody(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord);
  
      static Js::Var BailOutInlined(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord, void * returnAddress, Js::ImplicitCallFlags savedImplicitCallFlags);
      static uint32 BailOutFromLoopBodyInlined(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord, void * returnAddress);
  
      static Js::Var BailOutForElidedYield(void * framePointer);
  
      static size_t GetOffsetOfPolymorphicCacheIndex() { return offsetof(BailOutRecord, polymorphicCacheIndex); }
      static size_t GetOffsetOfBailOutKind() { return offsetof(BailOutRecord, bailOutKind); }
  
      static bool IsArgumentsObject(uint32 offset);
      static uint32 GetArgumentsObjectOffset();
      static const uint BailOutRegisterSaveSlotCount = LinearScanMD::RegisterSaveSlotCount;
  
      void Fixup(NativeCodeData::DataChunk* chunkList)
      {
          FixupNativeDataPointer(globalBailOutRecordTable, chunkList);
          FixupNativeDataPointer(argOutOffsetInfo, chunkList);
          FixupNativeDataPointer(parent, chunkList);
          FixupNativeDataPointer(constants, chunkList);
          FixupNativeDataPointer(ehBailoutData, chunkList);
          FixupNativeDataPointer(stackLiteralBailOutRecord, chunkList);
  #ifdef _M_IX86
          // special handling for startCallOutParamCounts and outParamOffsets, becuase it points to middle of the allocation
          if (argOutOffsetInfo)
          {
              uint* startCallArgRestoreAdjustCountsStart = startCallArgRestoreAdjustCounts - argOutOffsetInfo->startCallIndex;
              NativeCodeData::AddFixupEntry(startCallArgRestoreAdjustCounts, startCallArgRestoreAdjustCountsStart, &this->startCallArgRestoreAdjustCounts, this, chunkList);
          }
  #endif
      }
  
  public:
      void IsOffsetNativeIntOrFloat(uint offsetIndex, int argOutSlotStart, bool * pIsFloat64, bool * pIsInt32) const;
  
      template <typename Fn>
      void MapStartCallParamCounts(Fn fn);
  
      void SetBailOutKind(IR::BailOutKind bailOutKind) { this->bailOutKind = bailOutKind; }
      uint32 GetBailOutOffset() { return bailOutOffset; }
  #if ENABLE_DEBUG_CONFIG_OPTIONS
      Js::OpCode GetBailOutOpCode() { return bailOutOpcode; }
  #endif
      template <typename Fn>
      void MapArgOutOffsets(Fn fn);
  
      enum BailoutRecordType : byte
      {
          Normal = 0,
          Branch = 1,
          Shared = 2,
          SharedForLoopTop = 3
      };
      BailoutRecordType GetType() { return type; }
      void SetType(BailoutRecordType type) { this->type = type; }
      bool IsShared() const { return type == Shared || type == SharedForLoopTop; }
      bool IsForLoopTop() const { return type == SharedForLoopTop; }
  protected:
      struct BailOutReturnValue
      {
          Js::Var returnValue;
          Js::RegSlot returnValueRegSlot;
      };
      static Js::Var BailOutCommonNoCodeGen(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord,
          uint32 bailOutOffset, void * returnAddress, IR::BailOutKind bailOutKind, Js::Var branchValue, Js::Var * registerSaves,
          BailOutReturnValue * returnValue = nullptr, void * argoutRestoreAddress = nullptr);
      static Js::Var BailOutCommon(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord,
          uint32 bailOutOffset, void * returnAddress, IR::BailOutKind bailOutKind, Js::ImplicitCallFlags savedImplicitCallFlags, Js::Var branchValue = nullptr, BailOutReturnValue * returnValue = nullptr, void * argoutRestoreAddress = nullptr);
      static Js::Var BailOutInlinedCommon(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord,
          uint32 bailOutOffset, void * returnAddress, IR::BailOutKind bailOutKind, Js::ImplicitCallFlags savedImplicitCallFlags, Js::Var branchValue = nullptr);
      static uint32 BailOutFromLoopBodyCommon(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord,
          uint32 bailOutOffset, IR::BailOutKind bailOutKind, Js::Var branchValue = nullptr);
      static uint32 BailOutFromLoopBodyInlinedCommon(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord,
          uint32 bailOutOffset, void * returnAddress, IR::BailOutKind bailOutKind, Js::Var branchValue = nullptr);
  
      static Js::Var BailOutHelper(Js::JavascriptCallStackLayout * layout, Js::ScriptFunction ** functionRef, Js::Arguments& args, const bool boxArgs,
          BailOutRecord const * bailOutRecord, uint32 bailOutOffset, void * returnAddress, IR::BailOutKind bailOutKind, Js::Var * registerSaves, BailOutReturnValue * returnValue, Js::Var* pArgumentsObject,
          Js::Var branchValue = nullptr, void * argoutRestoreAddress = nullptr);
      static void BailOutInlinedHelper(Js::JavascriptCallStackLayout * layout, BailOutRecord const *& bailOutRecord, uint32 bailOutOffset, void * returnAddress,
          IR::BailOutKind bailOutKind, Js::Var * registerSaves, BailOutReturnValue * returnValue, Js::ScriptFunction ** innerMostInlinee, bool isInLoopBody, Js::Var branchValue = nullptr);
      static uint32 BailOutFromLoopBodyHelper(Js::JavascriptCallStackLayout * layout, BailOutRecord const * bailOutRecord,
          uint32 bailOutOffset, IR::BailOutKind bailOutKind, Js::Var branchValue, Js::Var * registerSaves, BailOutReturnValue * returnValue = nullptr);
  
      static void UpdatePolymorphicFieldAccess(Js::JavascriptFunction *  function, BailOutRecord const * bailOutRecord);
  
      static void ScheduleFunctionCodeGen(Js::ScriptFunction * function, Js::ScriptFunction * innerMostInlinee, BailOutRecord const * bailOutRecord, IR::BailOutKind bailOutKind, 
                                          uint32 actualBailOutOffset, Js::ImplicitCallFlags savedImplicitCallFlags, void * returnAddress);
      static void ScheduleLoopBodyCodeGen(Js::ScriptFunction * function, Js::ScriptFunction * innerMostInlinee, BailOutRecord const * bailOutRecord, IR::BailOutKind bailOutKind);
      static void CheckPreemptiveRejit(Js::FunctionBody* executeFunction, IR::BailOutKind bailOutKind, BailOutRecord* bailoutRecord, uint8& callsOrIterationsCount, int loopNumber);
      void RestoreValues(IR::BailOutKind bailOutKind, Js::JavascriptCallStackLayout * layout, Js::InterpreterStackFrame * newInstance, Js::ScriptContext * scriptContext,
          bool fromLoopBody, Js::Var * registerSaves, BailOutReturnValue * returnValue, Js::Var* pArgumentsObject, Js::Var branchValue = nullptr, void* returnAddress = nullptr, bool useStartCall = true, void * argoutRestoreAddress = nullptr) const;
      void RestoreValues(IR::BailOutKind bailOutKind, Js::JavascriptCallStackLayout * layout, uint count, __in_ecount_opt(count) int * offsets, int argOutSlotId,
          __out_ecount(count)Js::Var * values, Js::ScriptContext * scriptContext, bool fromLoopBody, Js::Var * registerSaves, Js::InterpreterStackFrame * newInstance, Js::Var* pArgumentsObject,
          void * argoutRestoreAddress = nullptr) const;
      void RestoreValue(IR::BailOutKind bailOutKind, Js::JavascriptCallStackLayout * layout, Js::Var * values, Js::ScriptContext * scriptContext,
          bool fromLoopBody, Js::Var * registerSaves, Js::InterpreterStackFrame * newInstance, Js::Var* pArgumentsObject, void * argoutRestoreAddress,
          uint regSlot, int offset, bool isLocal, bool isFloat64, bool isInt32) const;
  
      void AdjustOffsetsForDiagMode(Js::JavascriptCallStackLayout * layout, Js::ScriptFunction * function) const;
  
      Js::Var EnsureArguments(Js::InterpreterStackFrame * newInstance, Js::JavascriptCallStackLayout * layout, Js::ScriptContext* scriptContext, Js::Var* pArgumentsObject) const;
  
      Js::JavascriptCallStackLayout *GetStackLayout() const;
  
  public:
      struct StackLiteralBailOutRecord
      {
          Js::RegSlot regSlot;
          uint initFldCount;
      };
  
  protected:
      struct ArgOutOffsetInfo
      {
          BVFixed * argOutFloat64Syms;        // Used for float-type-specialized ArgOut symbols. Index = [0 .. BailOutInfo::totalOutParamCount].
          BVFixed * argOutLosslessInt32Syms;  // Used for int-type-specialized ArgOut symbols (which are native int and for bailout we need tagged ints).
  #ifdef _M_IX86
          BVFixed * isOrphanedArgSlot;
  #endif
          uint * startCallOutParamCounts;
          int * outParamOffsets;
          uint startCallCount;
          uint argOutSymStart;
          uint startCallIndex;
          void Fixup(NativeCodeData::DataChunk* chunkList)
          {
              FixupNativeDataPointer(argOutFloat64Syms, chunkList);
              FixupNativeDataPointer(argOutLosslessInt32Syms, chunkList);
  #ifdef _M_IX86
              FixupNativeDataPointer(isOrphanedArgSlot, chunkList);
  #endif
              // special handling for startCallOutParamCounts and outParamOffsets, becuase it points to middle of the allocation
              uint* startCallOutParamCountsStart = startCallOutParamCounts - startCallIndex;
              NativeCodeData::AddFixupEntry(startCallOutParamCounts, startCallOutParamCountsStart, &this->startCallOutParamCounts, this, chunkList);
  
              int* outParamOffsetsStart = outParamOffsets - argOutSymStart;
              NativeCodeData::AddFixupEntry(outParamOffsets, outParamOffsetsStart, &this->outParamOffsets, this, chunkList);
  
          }
      };
  
      // The offset to 'globalBailOutRecordTable' is hard-coded in LinearScanMD::SaveAllRegisters, so let this be the first member variable
      GlobalBailOutRecordDataTable *globalBailOutRecordTable;
      ArgOutOffsetInfo *argOutOffsetInfo;
      BailOutRecord * parent;
      Js::Var * constants;
      Js::EHBailoutData * ehBailoutData;
      StackLiteralBailOutRecord * stackLiteralBailOutRecord;
  #ifdef _M_IX86
      uint * startCallArgRestoreAdjustCounts;
  #endif
  
      // Index of start of section of argOuts for current record/current func, used with argOutFloat64Syms and
      // argOutLosslessInt32Syms when restoring values, as BailOutInfo uses one argOuts array for all funcs.
      // Similar to outParamOffsets which points to current func section for the offsets.
      Js::RegSlot localOffsetsCount;
      uint32 const bailOutOffset;
  
      uint stackLiteralBailOutRecordCount;
  
  
      Js::RegSlot branchValueRegSlot;
  
      uint polymorphicCacheIndex;
      IR::BailOutKind bailOutKind;
  #if DBG
      Js::ArgSlot actualCount;
      uint constantCount;
      int inlineDepth;
      void DumpArgOffsets(uint count, int* offsets, int argOutSlotStart);
      void DumpLocalOffsets(uint count, int argOutSlotStart);
      void DumpValue(int offset, bool isFloat64);
  #endif
      BailoutRecordType type;
      ushort bailOutCount;
      uint32 m_bailOutRecordId;
  
      friend class LinearScan;
      friend class BailOutInfo;
      friend struct FuncBailOutData;
  #if ENABLE_DEBUG_CONFIG_OPTIONS
  public:
      Js::OpCode bailOutOpcode;
  #if DBG
     void Dump();
  #endif
  #endif
  };
  
  class BranchBailOutRecord : public BailOutRecord
  {
  public:
      BranchBailOutRecord(uint32 trueBailOutOffset, uint32 falseBailOutOffset, Js::RegSlot resultByteCodeReg, IR::BailOutKind kind, Func *bailOutFunc);
  
      static Js::Var BailOut(BranchBailOutRecord const * bailOutRecord, BOOL cond);
      static Js::Var BailOutFromFunction(Js::JavascriptCallStackLayout * layout, BranchBailOutRecord const * bailOutRecord, BOOL cond, void * returnAddress, void * argoutRestoreAddress, Js::ImplicitCallFlags savedImplicitCallFlags);
      static uint32 BailOutFromLoopBody(Js::JavascriptCallStackLayout * layout, BranchBailOutRecord const * bailOutRecord, BOOL cond);
  
      static Js::Var BailOutInlined(Js::JavascriptCallStackLayout * layout, BranchBailOutRecord const * bailOutRecord, BOOL cond, void * returnAddress, Js::ImplicitCallFlags savedImplicitCallFlags);
      static uint32 BailOutFromLoopBodyInlined(Js::JavascriptCallStackLayout * layout, BranchBailOutRecord const * bailOutRecord, BOOL cond, void * returnAddress);
  private:
      uint falseBailOutOffset;
  };
  
  class SharedBailOutRecord : public BailOutRecord
  {
  public:
      Js::FunctionBody* functionBody; // function body in which the bailout originally was before possible hoisting
  
      SharedBailOutRecord(uint32 bailOutOffset, uint bailOutCacheIndex, IR::BailOutKind kind, Func *bailOutFunc);
      static size_t GetOffsetOfFunctionBody() { return offsetof(SharedBailOutRecord, functionBody); }
  };
  
  template <typename Fn>
  inline void BailOutRecord::MapStartCallParamCounts(Fn fn)
  {
      if (this->argOutOffsetInfo)
      {
          for (uint i = 0; i < this->argOutOffsetInfo->startCallCount; i++)
          {
              fn(this->argOutOffsetInfo->startCallOutParamCounts[i]);
          }
      }
  }
  
  template <typename Fn>
  inline void BailOutRecord::MapArgOutOffsets(Fn fn)
  {
      uint outParamSlot = 0;
      uint argOutSlotOffset = 0;
  
      if (this->argOutOffsetInfo)
      {
          for (uint i = 0; i < this->argOutOffsetInfo->startCallCount; i++)
          {
              uint startCallOutParamCount = this->argOutOffsetInfo->startCallOutParamCounts[i];
              argOutSlotOffset += 1; // skip pointer to self which is pushed by OP_StartCall
  
              for (uint j = 0; j < startCallOutParamCount; j++, outParamSlot++, argOutSlotOffset++)
              {
                  if (this->argOutOffsetInfo->outParamOffsets[outParamSlot] != 0)
                  {
                      fn(argOutSlotOffset, this->argOutOffsetInfo->outParamOffsets[outParamSlot]);
                  }
              }
          }
      }
  }
  
  struct GlobalBailOutRecordDataRow
  {
      int32 offset;
      uint32 start;           // start bailOutId
      uint32 end;             // end bailOutId
      unsigned regSlot : 30;
      unsigned isFloat : 1;
      unsigned isInt : 1;
  };
  
  struct GlobalBailOutRecordDataTable
  {
      // The offset to 'registerSaveSpace' is hard-coded in LinearScanMD::SaveAllRegisters, so let this be the first member variable
      Js::Var *registerSaveSpace;
      GlobalBailOutRecordDataRow *globalBailOutRecordDataRows;
      uint32 length;
      uint32 size;
      int32  firstActualStackOffset;
      int forInEnumeratorArrayRestoreOffset;
      Js::RegSlot returnValueRegSlot;
  
      bool isInlinedFunction      : 1;
      bool isInlinedConstructor   : 1;
      bool isLoopBody             : 1;
      bool hasNonSimpleParams     : 1;
      bool hasStackArgOpt         : 1;
      bool isScopeObjRestored     : 1;
  
      void Finalize(NativeCodeData::Allocator *allocator, JitArenaAllocator *tempAlloc);
      void AddOrUpdateRow(JitArenaAllocator *allocator, uint32 bailOutRecordId, uint32 regSlot, bool isFloat, bool isInt, int32 offset, uint *lastUpdatedRowIndex);
  
      template<class Fn>
      void IterateGlobalBailOutRecordTableRows(uint32 bailOutRecordId, Fn callback)
      {
          // Visit all the rows that have this bailout ID in their range.
          for (uint i = 0; i < this->length; i++)
          {
              if (bailOutRecordId > globalBailOutRecordDataRows[i].end)
              {
                  // Not in range.
                  continue;
              }
  
              if (globalBailOutRecordDataRows[i].start > bailOutRecordId)
              {
                  // Not in range, and we know there are no more in range (since the table is sorted by "start").
                  return;
              }
  
              // In range: take action.
              callback(&globalBailOutRecordDataRows[i]);
          }
      }
  
      template<class Fn>
      void VisitGlobalBailOutRecordTableRowsAtFirstBailOut(uint32 bailOutRecordId, Fn callback)
      {
          // Visit all the rows that have this bailout ID as the start of their range.
          // (I.e., visit each row once in a walk of the whole function)
          for (uint i = 0; i < this->length; i++)
          {
              if (bailOutRecordId == globalBailOutRecordDataRows[i].start)
              {
                  // Matching start ID: take action.
                  callback(&globalBailOutRecordDataRows[i]);
              }
              else if (globalBailOutRecordDataRows[i].start > bailOutRecordId)
              {
                  // We know there are no more in range (since the table is sorted by "start").
                  return;
              }
          }
      }
  
      void Fixup(NativeCodeData::DataChunk* chunkList)
      {
          FixupNativeDataPointer(globalBailOutRecordDataRows, chunkList);
      }
  };
  #if DBG
  template<> inline void NativeCodeData::AllocatorT<BailOutRecord::StackLiteralBailOutRecord>::Fixup(void* pThis, NativeCodeData::DataChunk* chunkList) {}
  template<> inline void NativeCodeData::AllocatorT<Js::EquivalentPropertyEntry>::Fixup(void* pThis, NativeCodeData::DataChunk* chunkList) {}
  template<> inline void NativeCodeData::AllocatorT<GlobalBailOutRecordDataRow>::Fixup(void* pThis, NativeCodeData::DataChunk* chunkList) {}
  #else
  template<>
  inline char*
  NativeCodeData::AllocatorT<BailOutRecord::StackLiteralBailOutRecord>::Alloc(size_t requestedBytes)
  {
      return __super::Alloc(requestedBytes);
  }
  template<>
  inline char*
  NativeCodeData::AllocatorT<BailOutRecord::StackLiteralBailOutRecord>::AllocZero(size_t requestedBytes)
  {
      return __super::AllocZero(requestedBytes);
  }
  
  template<>
  inline char*
  NativeCodeData::AllocatorT<Js::EquivalentPropertyEntry>::Alloc(size_t requestedBytes)
  {
      return __super::Alloc(requestedBytes);
  }
  template<>
  inline char*
  NativeCodeData::AllocatorT<Js::EquivalentPropertyEntry>::AllocZero(size_t requestedBytes)
  {
      return __super::AllocZero(requestedBytes);
  }
  
  template<>
  inline char*
  NativeCodeData::AllocatorT<GlobalBailOutRecordDataRow>::Alloc(size_t requestedBytes)
  {
      return __super::Alloc(requestedBytes);
  }
  template<>
  inline char*
  NativeCodeData::AllocatorT<GlobalBailOutRecordDataRow>::AllocZero(size_t requestedBytes)
  {
      return __super::AllocZero(requestedBytes);
  }
  #endif
  
  template<>
  inline void NativeCodeData::AllocatorT<GlobalBailOutRecordDataTable*>::Fixup(void* pThis, NativeCodeData::DataChunk* chunkList)
  {
      // for every pointer needs to update the table
      NativeCodeData::AddFixupEntryForPointerArray(pThis, chunkList);
  }
  