Преглед на файлове

fixup more data structures, don't completely disable globopt

Michael Holman преди 9 години
родител
ревизия
35dd3bc5de
променени са 44 файла, в които са добавени 420 реда и са изтрити 246 реда
  1. 10 10
      lib/Backend/BackwardPass.cpp
  2. 5 1
      lib/Backend/CodeGenWorkItem.cpp
  3. 1 1
      lib/Backend/CodeGenWorkItem.h
  4. 1 1
      lib/Backend/Encoder.cpp
  5. 3 3
      lib/Backend/FlowGraph.cpp
  6. 7 12
      lib/Backend/Func.cpp
  7. 4 7
      lib/Backend/Func.h
  8. 45 39
      lib/Backend/GlobOpt.cpp
  9. 2 2
      lib/Backend/GlobOptBailOut.cpp
  10. 4 4
      lib/Backend/GlobOptFields.cpp
  11. 4 4
      lib/Backend/IR.cpp
  12. 11 14
      lib/Backend/IRBuilder.cpp
  13. 33 33
      lib/Backend/Inline.cpp
  14. 7 0
      lib/Backend/JITOutput.cpp
  15. 1 0
      lib/Backend/JITOutput.h
  16. 55 0
      lib/Backend/JITTimeFunctionBody.cpp
  17. 10 0
      lib/Backend/JITTimeFunctionBody.h
  18. 5 5
      lib/Backend/LinearScan.cpp
  19. 53 58
      lib/Backend/Lower.cpp
  20. 2 2
      lib/Backend/LowerMDShared.cpp
  21. 6 2
      lib/Backend/NativeCodeGenerator.cpp
  22. 2 1
      lib/Backend/Opnd.cpp
  23. 1 1
      lib/Backend/SccLiveness.cpp
  24. 61 0
      lib/Backend/ScriptContextInfo.cpp
  25. 11 0
      lib/Backend/ScriptContextInfo.h
  26. 3 3
      lib/Backend/SwitchIRBuilder.cpp
  27. 2 2
      lib/Backend/Sym.cpp
  28. 1 1
      lib/Backend/TempTracker.cpp
  29. 6 0
      lib/Backend/ThreadContextInfo.cpp
  30. 3 0
      lib/Backend/ThreadContextInfo.h
  31. 1 1
      lib/Backend/amd64/EncoderMD.cpp
  32. 1 1
      lib/Backend/amd64/LowererMDArch.cpp
  33. 1 1
      lib/Backend/arm/LinearScanMD.cpp
  34. 3 3
      lib/Backend/arm/LowerMD.cpp
  35. 1 1
      lib/Backend/i386/LowererMDArch.cpp
  36. 21 1
      lib/JITIDL/ChakraJIT.idl
  37. 1 1
      lib/Runtime/Base/Debug.h
  38. 15 20
      lib/Runtime/Base/FunctionBody.cpp
  39. 1 7
      lib/Runtime/Base/FunctionBody.h
  40. 11 1
      lib/Runtime/Base/ScriptContext.h
  41. 1 0
      lib/Runtime/Base/ThreadContext.h
  42. 1 0
      lib/Runtime/Language/FunctionCodeGenJitTimeData.h
  43. 2 2
      lib/Runtime/Library/JavascriptFunction.cpp
  44. 1 1
      lib/Runtime/Library/JavascriptFunction.h

+ 10 - 10
lib/Backend/BackwardPass.cpp

@@ -604,7 +604,7 @@ BackwardPass::MergeSuccBlocksInfo(BasicBlock * block)
 
             PHASE_PRINT_TRACE(Js::ObjTypeSpecStorePhase, this->func,
                               L"ObjTypeSpecStore: func %s, edge %d => %d: ",
-                              this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                              this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                               block->GetBlockNum(), blockSucc->GetBlockNum());
 
             auto fixupFrom = [block, blockSucc, this](Bucket<AddPropertyCacheBucket> &bucket)
@@ -850,7 +850,7 @@ BackwardPass::MergeSuccBlocksInfo(BasicBlock * block)
         if (PHASE_TRACE(Js::ObjTypeSpecStorePhase, this->func))
         {
             Output::Print(L"ObjTypeSpecStore: func %s, block %d: ",
-                          this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                          this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                           block->GetBlockNum());
             if (stackSymToFinalType)
             {
@@ -865,7 +865,7 @@ BackwardPass::MergeSuccBlocksInfo(BasicBlock * block)
         if (PHASE_TRACE(Js::TraceObjTypeSpecTypeGuardsPhase, this->func))
         {
             Output::Print(L"ObjTypeSpec: func %s, block %d, guarded properties:\n",
-                this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer), block->GetBlockNum());
+                this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer), block->GetBlockNum());
             if (stackSymToGuardedProperties)
             {
                 stackSymToGuardedProperties->Dump();
@@ -880,7 +880,7 @@ BackwardPass::MergeSuccBlocksInfo(BasicBlock * block)
         if (PHASE_TRACE(Js::TraceObjTypeSpecWriteGuardsPhase, this->func))
         {
             Output::Print(L"ObjTypeSpec: func %s, block %d, write guards: ",
-                this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer), block->GetBlockNum());
+                this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer), block->GetBlockNum());
             if (stackSymToWriteGuardsMap)
             {
                 Output::Print(L"\n");
@@ -5738,13 +5738,13 @@ BackwardPass::EndIntOverflowDoesNotMatterRange()
         currentBlock->intOverflowDoesNotMatterRange->SetFirstInstr(boundaryInstr);
 
 #if DBG_DUMP
-        if(PHASE_TRACE(Js::TrackCompoundedIntOverflowPhase, func->GetJnFunction()))
+        if(PHASE_TRACE(Js::TrackCompoundedIntOverflowPhase, func))
         {
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
             Output::Print(
                 L"TrackCompoundedIntOverflow - Top function: %s (%s), Phase: %s, Block: %u\n",
                 func->GetWorkItem()->GetDisplayName(),
-                func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                 Js::PhaseNames[Js::BackwardPhase],
                 currentBlock->GetBlockNum());
             Output::Print(L"    Input syms to be int-specialized (lossless): ");
@@ -6387,8 +6387,8 @@ BackwardPass::ProcessInlineeStart(IR::Instr* inlineeStart)
     if (!inlineeStart->m_func->m_hasInlineArgsOpt)
     {
         PHASE_PRINT_TESTTRACE(Js::InlineArgsOptPhase, func, L"%s[%d]: Skipping inline args optimization: %s[%d] HasCalls: %s 'arguments' access: %s Can do inlinee args opt: %s\n",
-                func->GetJnFunction()->GetExternalDisplayName(), func->GetJnFunction()->GetFunctionNumber(),
-                inlineeStart->m_func->GetJnFunction()->GetExternalDisplayName(), inlineeStart->m_func->GetJnFunction()->GetFunctionNumber(),
+                func->GetWorkItem()->GetDisplayName(), func->GetJITFunctionBody()->GetFunctionNumber(),
+                inlineeStart->m_func->GetWorkItem()->GetDisplayName(), inlineeStart->m_func->GetJITFunctionBody()->GetFunctionNumber(),
                 IsTrueOrFalse(inlineeStart->m_func->GetHasCalls()),
                 IsTrueOrFalse(inlineeStart->m_func->GetHasUnoptimizedArgumentsAcccess()),
                 IsTrueOrFalse(inlineeStart->m_func->m_canDoInlineArgsOpt));
@@ -6398,7 +6398,7 @@ BackwardPass::ProcessInlineeStart(IR::Instr* inlineeStart)
     if (!inlineeStart->m_func->frameInfo->isRecorded)
     {
         PHASE_PRINT_TESTTRACE(Js::InlineArgsOptPhase, func, L"%s[%d]: InlineeEnd not found - usually due to a throw or a BailOnNoProfile (stressed, most likely)\n",
-            func->GetJnFunction()->GetExternalDisplayName(), func->GetJnFunction()->GetFunctionNumber());
+            func->GetWorkItem()->GetDisplayName(), func->GetJITFunctionBody()->GetFunctionNumber());
         inlineeStart->m_func->DisableCanDoInlineArgOpt();
         return false;
     }
@@ -7273,6 +7273,6 @@ BackwardPass::IsTraceEnabled() const
 {
     return
         Js::Configuration::Global.flags.Trace.IsEnabled(tag, this->func->GetSourceContextId(), this->func->GetLocalFunctionId()) &&
-        (PHASE_TRACE(Js::SimpleJitPhase, func->GetJnFunction()) || !func->IsSimpleJit());
+        (PHASE_TRACE(Js::SimpleJitPhase, func) || !func->IsSimpleJit());
 }
 #endif

+ 5 - 1
lib/Backend/CodeGenWorkItem.cpp

@@ -92,6 +92,8 @@ CodeGenWorkItem::CodeGenWorkItem(
     }
 
     // body data
+    this->jitData.bodyData.functionBodyAddr = (intptr_t)functionBody;
+
     this->jitData.bodyData.funcNumber = functionBody->GetFunctionNumber();
     this->jitData.bodyData.localFuncId = functionBody->GetLocalFunctionId();
     this->jitData.bodyData.sourceContextId = functionBody->GetSourceContextId();
@@ -131,6 +133,8 @@ CodeGenWorkItem::CodeGenWorkItem(
     this->jitData.bodyData.isLibraryCode = functionBody->GetUtf8SourceInfo()->GetIsLibraryCode();
     this->jitData.bodyData.isAsmJsMode = functionBody->GetIsAsmjsMode();
     this->jitData.bodyData.isStrictMode = functionBody->GetIsStrictMode();
+    this->jitData.bodyData.isGlobalFunc = functionBody->GetIsGlobalFunc();
+    this->jitData.bodyData.doJITLoopBody = functionBody->DoJITLoopBody();
     this->jitData.bodyData.hasScopeObject = functionBody->HasScopeObject();
     this->jitData.bodyData.hasImplicitArgIns = functionBody->GetHasImplicitArgIns();
     this->jitData.bodyData.hasCachedScopePropIds = functionBody->HasCachedScopePropIds();
@@ -161,7 +165,7 @@ CodeGenWorkItem::~CodeGenWorkItem()
 //
 bool CodeGenWorkItem::ShouldSpeculativelyJit(uint byteCodeSizeGenerated) const
 {
-    if(!functionBody->DoFullJit())
+    if(PHASE_OFF(Js::FullJitPhase, this->functionBody))
     {
         return false;
     }

+ 1 - 1
lib/Backend/CodeGenWorkItem.h

@@ -168,7 +168,7 @@ public:
     {
         Assert(GetJitMode() == ExecutionMode::SimpleJit || GetJitMode() == ExecutionMode::FullJit);
         Assert(GetJitMode() != ExecutionMode::SimpleJit || GetFunctionBody()->DoSimpleJit());
-        Assert(GetJitMode() != ExecutionMode::FullJit || GetFunctionBody()->DoFullJit());
+        Assert(GetJitMode() != ExecutionMode::FullJit || !PHASE_OFF(Js::FullJitPhase, GetFunctionBody()));
     }
 
     void OnAddToJitQueue();

+ 1 - 1
lib/Backend/Encoder.cpp

@@ -336,7 +336,7 @@ Encoder::Encode()
         {
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
             Output::Print(L"PinnedTypes: function %s(%s) pinned %d types.\n",
-                this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer), pinnedTypeRefCount);
+                this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer), pinnedTypeRefCount);
             Output::Flush();
         }
 

+ 3 - 3
lib/Backend/FlowGraph.cpp

@@ -35,7 +35,7 @@ FlowGraph::Build(void)
     // (BailOnSimpleJitToFullJitLoopBody). For that purpose, we need the flow from try to catch.
     if (this->func->HasTry() &&
         (this->func->DoOptimizeTryCatch() ||
-        this->func->IsSimpleJit() && this->func->GetJnFunction()->DoJITLoopBody()
+        this->func->IsSimpleJit() && this->func->GetJITFunctionBody()->DoJITLoopBody()
         )
        )
     {
@@ -802,7 +802,7 @@ bool Loop::EnsureMemOpVariablesInitialized()
                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                 Output::Print(L"MemOp skipped: minimum loop count not reached: Function: %s %s,  Loop: %d\n",
                               func->GetWorkItem()->GetDisplayName(),
-                              func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                              func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                               this->GetLoopNumber()
                               );
             }
@@ -1263,7 +1263,7 @@ FlowGraph::Destroy(void)
                     case Js::OpCode::BrOnNoException:
                         Assert(this->func->HasTry() &&
                                ((!this->func->HasFinally() && !this->func->IsLoopBody() && !PHASE_OFF(Js::OptimizeTryCatchPhase, this->func)) ||
-                               (this->func->IsSimpleJit() && this->func->GetJnFunction()->DoJITLoopBody()))); // should be relaxed as more bailouts are added in Simple Jit
+                               (this->func->IsSimpleJit() && this->func->GetJITFunctionBody()->DoJITLoopBody()))); // should be relaxed as more bailouts are added in Simple Jit
 
                         Assert(region->GetType() == RegionTypeTry || region->GetType() == RegionTypeCatch);
                         if (region->GetType() == RegionTypeCatch)

+ 7 - 12
lib/Backend/Func.cpp

@@ -498,8 +498,7 @@ Func::EnsureLocalVarSlots()
 
     if (!this->HasLocalVarSlotCreated())
     {
-        Assert(this->m_jnFunction != nullptr);
-        uint32 localSlotCount = this->m_jnFunction->GetNonTempLocalVarCount();
+        uint32 localSlotCount = GetJITFunctionBody()->GetNonTempLocalVarCount();
         if (localSlotCount && m_localVarSlotsOffset == Js::Constants::InvalidOffset)
         {
             // Allocate the slots.
@@ -581,8 +580,7 @@ Func::IsJitInDebugMode()
 bool
 Func::IsNonTempLocalVar(uint32 slotIndex)
 {
-    Assert(this->m_jnFunction != nullptr);
-    return this->m_jnFunction->IsNonTempLocalVar(slotIndex);
+    return GetJITFunctionBody()->IsNonTempLocalVar(slotIndex);
 }
 
 int32
@@ -601,7 +599,7 @@ Func::AdjustOffsetValue(int32 offset)
 void
 Func::AjustLocalVarSlotOffset()
 {
-    if (m_jnFunction->GetNonTempLocalVarCount())
+    if (GetJITFunctionBody()->GetNonTempLocalVarCount())
     {
         // Turn positive SP-relative base locals offset into negative frame-pointer-relative offset
         // This is changing value for restoring the locals when read due to locals inspection.
@@ -633,7 +631,7 @@ Func::SetDoFastPaths()
 
     bool doFastPaths = false;
 
-    if(!PHASE_OFF(Js::FastPathPhase, this) && (!IsSimpleJit() || Js::FunctionBody::IsNewSimpleJit()))
+    if(!PHASE_OFF(Js::FastPathPhase, this) && (!IsSimpleJit() || CONFIG_FLAG(NewSimpleJit)))
     {
         doFastPaths = true;
     }
@@ -656,7 +654,7 @@ Func::GetLocalsPointer() const
     }
 #endif
 
-    if (this->m_jnFunction->GetHasTry())
+    if (GetJITFunctionBody()->HasTry())
     {
         return ALT_LOCALS_PTR;
     }
@@ -1244,17 +1242,14 @@ Func::LinkCtorCacheToPropertyId(Js::PropertyId propertyId, Js::JitTimeConstructo
 
 Js::JitTimeConstructorCache* Func::GetConstructorCache(const Js::ProfileId profiledCallSiteId)
 {
-    Assert(GetJnFunction() != nullptr);
-    Assert(profiledCallSiteId < GetJnFunction()->GetProfiledCallSiteCount());
+    Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
     Assert(this->constructorCaches != nullptr);
     return this->constructorCaches[profiledCallSiteId];
 }
 
 void Func::SetConstructorCache(const Js::ProfileId profiledCallSiteId, Js::JitTimeConstructorCache* constructorCache)
 {
-    const auto functionBody = this->GetJnFunction();
-    Assert(functionBody != nullptr);
-    Assert(profiledCallSiteId < functionBody->GetProfiledCallSiteCount());
+    Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
     Assert(constructorCache != nullptr);
     Assert(this->constructorCaches != nullptr);
     Assert(this->constructorCaches[profiledCallSiteId] == nullptr);

+ 4 - 7
lib/Backend/Func.h

@@ -127,19 +127,16 @@ public:
     bool DoLoopFastPaths() const
     {
         return
-            (!IsSimpleJit() || Js::FunctionBody::IsNewSimpleJit()) &&
+            (!IsSimpleJit() || CONFIG_FLAG(NewSimpleJit)) &&
             !PHASE_OFF(Js::FastPathPhase, this) &&
             !PHASE_OFF(Js::LoopFastPathPhase, this);
     }
 
     bool DoGlobOpt() const
     {
-        return false;
-#if 0 // TODO: michhol OOP JIT, enable globopt
         return
             !PHASE_OFF(Js::GlobOptPhase, this) && !IsSimpleJit() &&
             (!GetTopFunc()->HasTry() || GetTopFunc()->CanOptimizeTryCatch());
-#endif
     }
 
     bool DoInline() const
@@ -288,12 +285,12 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
     bool IsGlobalFunc() const
     {
         Assert(this->IsTopFunc());
-        Assert(this->m_jnFunction);     // For now we always have a function body
-        return this->m_jnFunction->GetIsGlobalFunc();
+        return this->GetJITFunctionBody()->IsGlobalFunc();
     }
 
     RecyclerWeakReference<Js::FunctionBody> *GetWeakFuncRef() const;
-    Js::FunctionBody * GetJnFunction() const { return m_jnFunction; }
+    // TODO: OOP JIT, remove this
+    Js::FunctionBody * GetJnFunction() const { Assert(UNREACHED);  return m_jnFunction; }
 
     StackSym *EnsureLoopParamSym();
 

+ 45 - 39
lib/Backend/GlobOpt.cpp

@@ -14,7 +14,7 @@
             L"Testtrace: %s function %s (%s): ", \
             Js::PhaseNames[phase], \
             instr->m_func->GetWorkItem()->GetDisplayName(), \
-            instr->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer)); \
+            instr->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer)); \
         Output::Print(__VA_ARGS__); \
         Output::Flush(); \
     }
@@ -71,7 +71,7 @@
         Output::Print( \
             L"Function %s (%s, line %u)", \
             this->func->GetWorkItem()->GetDisplayName(), \
-            this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer), \
+            this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer), \
             this->func->GetJnFunction()->GetLineNumber()); \
         if(this->func->IsLoopBody()) \
         { \
@@ -82,7 +82,7 @@
             Output::Print( \
                 L", Inlinee %s (%s, line %u)", \
                 instr->m_func->GetWorkItem()->GetDisplayName(), \
-                instr->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer), \
+                instr->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer), \
                 instr->m_func->GetJnFunction()->GetLineNumber()); \
         } \
         Output::Print(L" - %s\n    ", Js::PhaseNames[phase]); \
@@ -116,14 +116,14 @@
 #endif  // ENABLE_DEBUG_CONFIG_OPTIONS && DBG_DUMP
 
 #if DBG_DUMP
-#define DO_MEMOP_TRACE() (PHASE_TRACE(Js::MemOpPhase, this->func->GetJnFunction()) ||\
-        PHASE_TRACE(Js::MemSetPhase, this->func->GetJnFunction()) ||\
-        PHASE_TRACE(Js::MemCopyPhase, this->func->GetJnFunction()))
-#define DO_MEMOP_TRACE_PHASE(phase) (PHASE_TRACE(Js::MemOpPhase, this->func->GetJnFunction()) || PHASE_TRACE(Js::phase ## Phase, this->func->GetJnFunction()))
+#define DO_MEMOP_TRACE() (PHASE_TRACE(Js::MemOpPhase, this->func) ||\
+        PHASE_TRACE(Js::MemSetPhase, this->func) ||\
+        PHASE_TRACE(Js::MemCopyPhase, this->func))
+#define DO_MEMOP_TRACE_PHASE(phase) (PHASE_TRACE(Js::MemOpPhase, this->func) || PHASE_TRACE(Js::phase ## Phase, this->func))
 
 #define OUTPUT_MEMOP_TRACE(loop, instr, ...) {\
     wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];\
-    Output::Print(15, L"Function: %s%s, Loop: %u: ", this->func->GetWorkItem()->GetDisplayName(), this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer), loop->GetLoopNumber());\
+    Output::Print(15, L"Function: %s%s, Loop: %u: ", this->func->GetWorkItem()->GetDisplayName(), this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer), loop->GetLoopNumber());\
     Output::Print(__VA_ARGS__);\
     IR::Instr* __instr__ = instr;\
     if(__instr__) __instr__->DumpByteCodeOffset();\
@@ -3774,9 +3774,9 @@ GlobOpt::TrackArgumentsSym(IR::RegOpnd* opnd)
         Output::Print(L"Created a new alias s%d for arguments object in function %s(%s) topFunc %s(%s)\n",
             opnd->m_sym->m_id,
             blockData.curFunc->GetWorkItem()->GetDisplayName(),
-            blockData.curFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+            blockData.curFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
             this->func->GetWorkItem()->GetDisplayName(),
-            this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer2)
+            this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer2)
             );
         Output::Flush();
     }
@@ -5346,7 +5346,7 @@ GlobOpt::OptSrc(IR::Opnd *opnd, IR::Instr * *pInstr, Value **indirIndexValRef, I
             IR::AddrOpnd *addrOpnd = opnd->AsAddrOpnd();
             if (addrOpnd->m_isFunction)
             {
-                AssertMsg(!PHASE_OFF(Js::FixedMethodsPhase, instr->m_func->GetJnFunction()), "Fixed function address operand with fixed method calls phase disabled?");
+                AssertMsg(!PHASE_OFF(Js::FixedMethodsPhase, instr->m_func), "Fixed function address operand with fixed method calls phase disabled?");
                 val = NewFixedFunctionValue((Js::JavascriptFunction *)addrOpnd->m_address, addrOpnd);
                 opnd->SetValueType(val->GetValueInfo()->Type());
                 return val;
@@ -5684,7 +5684,7 @@ GlobOpt::TryOptimizeInstrWithFixedDataProperty(IR::Instr ** const pInstr)
     IR::Opnd * src1 = instr->GetSrc1();
     Assert(src1 && src1->IsSymOpnd() && src1->AsSymOpnd()->IsPropertySymOpnd());
 
-    if(PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func->GetJnFunction()))
+    if(PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func))
     {
         return;
     }
@@ -6041,7 +6041,7 @@ GlobOpt::CopyProp(IR::Opnd *opnd, IR::Instr *instr, Value *val, IR::IndirOpnd *p
 
         if(opnd != instr->GetSrc1() && opnd != instr->GetSrc2())
         {
-            if(PHASE_OFF(Js::IndirCopyPropPhase, instr->m_func->GetJnFunction()))
+            if(PHASE_OFF(Js::IndirCopyPropPhase, instr->m_func))
             {
                 return opnd;
             }
@@ -6627,7 +6627,8 @@ Value *
 GlobOpt::GetVarConstantValue(IR::AddrOpnd *addrOpnd)
 {
     bool isVar = addrOpnd->IsVar();
-    bool isString = isVar && Js::JavascriptString::Is(addrOpnd->m_address);
+    // TODO: OOP JIT, fix string const stuff
+    bool isString = isVar && false;// Js::JavascriptString::Is(addrOpnd->m_address);
     Value *val = nullptr;
     Value *cachedValue;
     if(this->addrConstantToValueMap->TryGetValue(addrOpnd->m_address, &cachedValue))
@@ -7592,14 +7593,14 @@ GlobOpt::ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal)
         if(DoTypedArrayTypeSpec() && !IsLoopPrePass())
         {
             GOPT_TRACE_INSTR(instr, L"Didn't specialize array access.\n");
-            if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func->GetJnFunction()))
+            if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func))
             {
                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                 char baseValueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
                 baseValueType.ToString(baseValueTypeStr);
                 Output::Print(L"Typed Array Optimization:  function: %s (%s): instr: %s, base value type: %S, did not type specialize, because %s.\n",
                     this->func->GetWorkItem()->GetDisplayName(),
-                    this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                    this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                     Js::OpCodeUtil::GetOpCodeName(instr->m_opcode),
                     baseValueTypeStr,
                     instr->DoStackArgsOpt(this->func) ? L"instruction uses the arguments object" :
@@ -7708,7 +7709,7 @@ GlobOpt::ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal)
     Assert(toType != TyVar);
 
     GOPT_TRACE_INSTR(instr, L"Type specialized array access.\n");
-    if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func->GetJnFunction()))
+    if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func))
     {
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
         char baseValueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
@@ -7717,7 +7718,7 @@ GlobOpt::ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal)
         dstVal->GetValueInfo()->Type().ToString(dstValTypeStr);
         Output::Print(L"Typed Array Optimization:  function: %s (%s): instr: %s, base value type: %S, type specialized to %s producing %S",
             this->func->GetWorkItem()->GetDisplayName(),
-            this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+            this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
             Js::OpCodeUtil::GetOpCodeName(instr->m_opcode),
             baseValueTypeStr,
             toType == TyInt32 ? L"int32" : L"float64",
@@ -8770,6 +8771,11 @@ GlobOpt::GetConstantVar(IR::Opnd *opnd, Value *val)
 bool
 GlobOpt::OptConstFoldBranch(IR::Instr *instr, Value *src1Val, Value*src2Val, Value **pDstVal)
 {
+    if (true)
+    {
+        // TODO: michhol OOP JIT
+        return false;
+    }
     if (!src1Val)
     {
         return false;
@@ -12601,14 +12607,14 @@ GlobOpt::TypeSpecializeStElem(IR::Instr ** pInstr, Value *src1Val, Value **pDstV
         !(baseValueType.IsLikelyOptimizedTypedArray() || baseValueType.IsLikelyNativeArray()))
     {
         GOPT_TRACE_INSTR(instr, L"Didn't type specialize array access, because typed array type specialization is disabled, or base is not an optimized typed array.\n");
-        if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func->GetJnFunction()))
+        if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func))
         {
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
             char baseValueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
             baseValueType.ToString(baseValueTypeStr);
             Output::Print(L"Typed Array Optimization:  function: %s (%s): instr: %s, base value type: %S, did not specialize because %s.\n",
                 this->func->GetWorkItem()->GetDisplayName(),
-                this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                 Js::OpCodeUtil::GetOpCodeName(instr->m_opcode),
                 baseValueTypeStr,
                 instr->DoStackArgsOpt(this->func) ?
@@ -12656,14 +12662,14 @@ GlobOpt::TypeSpecializeStElem(IR::Instr ** pInstr, Value *src1Val, Value **pDstV
         else if (!this->IsInt32TypeSpecialized(sym, this->currentBlock) && !this->IsFloat64TypeSpecialized(sym, this->currentBlock))
         {
             GOPT_TRACE_INSTR(instr, L"Didn't specialize array access, because src is not type specialized.\n");
-            if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func->GetJnFunction()))
+            if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func))
             {
                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                 char baseValueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
                 baseValueType.ToString(baseValueTypeStr);
                 Output::Print(L"Typed Array Optimization:  function: %s (%s): instr: %s, base value type: %S, did not specialize because src is not specialized.\n",
                               this->func->GetWorkItem()->GetDisplayName(),
-                              this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                              this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                               Js::OpCodeUtil::GetOpCodeName(instr->m_opcode),
                               baseValueTypeStr);
                 Output::Flush();
@@ -12694,14 +12700,14 @@ GlobOpt::TypeSpecializeStElem(IR::Instr ** pInstr, Value *src1Val, Value **pDstV
     if (!ShouldExpectConventionalArrayIndexValue(dst))
     {
         GOPT_TRACE_INSTR(instr, L"Didn't specialize array access, because index is negative or likely not int.\n");
-        if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func->GetJnFunction()))
+        if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func))
         {
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
             char baseValueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
             baseValueType.ToString(baseValueTypeStr);
             Output::Print(L"Typed Array Optimization:  function: %s (%s): instr: %s, base value type: %S, did not specialize because index is negative or likely not int.\n",
                 this->func->GetWorkItem()->GetDisplayName(),
-                this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                 Js::OpCodeUtil::GetOpCodeName(instr->m_opcode),
                 baseValueTypeStr);
             Output::Flush();
@@ -12793,14 +12799,14 @@ GlobOpt::TypeSpecializeStElem(IR::Instr ** pInstr, Value *src1Val, Value **pDstV
     if (toType != TyVar)
     {
         GOPT_TRACE_INSTR(instr, L"Type specialized array access.\n");
-        if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func->GetJnFunction()))
+        if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func))
         {
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
             char baseValueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
             baseValueType.ToString(baseValueTypeStr);
             Output::Print(L"Typed Array Optimization:  function: %s (%s): instr: %s, base value type: %S, type specialized to %s.\n",
                 this->func->GetWorkItem()->GetDisplayName(),
-                this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                 Js::OpCodeUtil::GetOpCodeName(instr->m_opcode),
                 baseValueTypeStr,
                 toType == TyInt32 ? L"int32" : L"float64");
@@ -12870,14 +12876,14 @@ GlobOpt::TypeSpecializeStElem(IR::Instr ** pInstr, Value *src1Val, Value **pDstV
     else
     {
         GOPT_TRACE_INSTR(instr, L"Didn't specialize array access, because the source was not already specialized.\n");
-        if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func->GetJnFunction()))
+        if (PHASE_TRACE(Js::TypedArrayTypeSpecPhase, this->func))
         {
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
             char baseValueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
             baseValueType.ToString(baseValueTypeStr);
             Output::Print(L"Typed Array Optimization:  function: %s (%s): instr: %s, base value type: %S, did not type specialize, because of array type.\n",
                 this->func->GetWorkItem()->GetDisplayName(),
-                this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                 Js::OpCodeUtil::GetOpCodeName(instr->m_opcode),
                 baseValueTypeStr);
             Output::Flush();
@@ -13362,13 +13368,13 @@ GlobOpt::ToTypeSpecUse(IR::Instr *instr, IR::Opnd *opnd, BasicBlock *block, Valu
                         else
                         {
                             Assert(DoAggressiveIntTypeSpec());
-                            if(PHASE_TRACE(Js::BailOutPhase, this->func->GetJnFunction()))
+                            if(PHASE_TRACE(Js::BailOutPhase, this->func))
                             {
                                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                                 Output::Print(
                                     L"BailOut (compile-time): function: %s (%s) varSym: ",
                                     this->func->GetWorkItem()->GetDisplayName(),
-                                    this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                                    this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                                     varSym->m_id);
     #if DBG_DUMP
                                 varSym->Dump();
@@ -13387,7 +13393,7 @@ GlobOpt::ToTypeSpecUse(IR::Instr *instr, IR::Opnd *opnd, BasicBlock *block, Valu
                             {
                                 // Aggressive int type specialization is already off for some reason. Prevent trying to rejit again
                                 // because it won't help and the same thing will happen again. Just abort jitting this function.
-                                if(PHASE_TRACE(Js::BailOutPhase, this->func->GetJnFunction()))
+                                if(PHASE_TRACE(Js::BailOutPhase, this->func))
                                 {
                                     Output::Print(L"    Aborting JIT because AggressiveIntTypeSpec is already off\n");
                                     Output::Flush();
@@ -17625,13 +17631,13 @@ GlobOpt::PrepareForIgnoringIntOverflow(IR::Instr *const instr)
             if(intOverflowCurrentlyMattersInRange)
             {
 #if DBG_DUMP
-                if(PHASE_TRACE(Js::TrackCompoundedIntOverflowPhase, func->GetJnFunction()) && !IsLoopPrePass())
+                if(PHASE_TRACE(Js::TrackCompoundedIntOverflowPhase, func) && !IsLoopPrePass())
                 {
                     wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                     Output::Print(
                         L"TrackCompoundedIntOverflow - Top function: %s (%s), Phase: %s, Block: %u, Disabled ignoring overflows\n",
                         func->GetWorkItem()->GetDisplayName(),
-                        func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                        func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                         Js::PhaseNames[Js::ForwardPhase],
                         currentBlock->GetBlockNum());
                     Output::Print(L"    Input sym could not be turned into an int:   %u\n", couldNotConvertSymId);
@@ -17693,13 +17699,13 @@ GlobOpt::PrepareForIgnoringIntOverflow(IR::Instr *const instr)
     intOverflowDoesNotMatterRange->SymsRequiredToBeInt()->Minus(intOverflowDoesNotMatterRange->SymsRequiredToBeLossyInt());
 
 #if DBG_DUMP
-    if(PHASE_TRACE(Js::TrackCompoundedIntOverflowPhase, func->GetJnFunction()))
+    if(PHASE_TRACE(Js::TrackCompoundedIntOverflowPhase, func))
     {
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
         Output::Print(
             L"TrackCompoundedIntOverflow - Top function: %s (%s), Phase: %s, Block: %u\n",
             func->GetWorkItem()->GetDisplayName(),
-            func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+            func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
             Js::PhaseNames[Js::ForwardPhase],
             currentBlock->GetBlockNum());
         Output::Print(L"    Input syms to be int-specialized (lossless): ");
@@ -17752,13 +17758,13 @@ GlobOpt::VerifyIntSpecForIgnoringIntOverflow(IR::Instr *const instr)
     // overflow.
     Assert(!func->GetProfileInfo()->IsTrackCompoundedIntOverflowDisabled());
 
-    if(PHASE_TRACE(Js::BailOutPhase, this->func->GetJnFunction()))
+    if(PHASE_TRACE(Js::BailOutPhase, this->func))
     {
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
         Output::Print(
             L"BailOut (compile-time): function: %s (%s) instr: ",
             func->GetWorkItem()->GetDisplayName(),
-            func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
+            func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer));
 #if DBG_DUMP
         instr->Dump();
 #else
@@ -17772,7 +17778,7 @@ GlobOpt::VerifyIntSpecForIgnoringIntOverflow(IR::Instr *const instr)
     {
         // Tracking int overflows is already off for some reason. Prevent trying to rejit again because it won't help and the
         // same thing will happen again and cause an infinite loop. Just abort jitting this function.
-        if(PHASE_TRACE(Js::BailOutPhase, this->func->GetJnFunction()))
+        if(PHASE_TRACE(Js::BailOutPhase, this->func))
         {
             Output::Print(L"    Aborting JIT because TrackIntOverflow is already off\n");
             Output::Flush();
@@ -19334,7 +19340,7 @@ GlobOpt::CannotAllocateArgumentsObjectOnStack()
     if (PHASE_TESTTRACE(Js::StackArgOptPhase, this->func))
     {
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
-        Output::Print(L"Stack args disabled for function %s(%s)\n", func->GetWorkItem()->GetDisplayName(), func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
+        Output::Print(L"Stack args disabled for function %s(%s)\n", func->GetWorkItem()->GetDisplayName(), func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer));
         Output::Flush();
     }
 #endif

+ 2 - 2
lib/Backend/GlobOptBailOut.cpp

@@ -1021,8 +1021,8 @@ GlobOpt::NeedsTypeCheckBailOut(const IR::Instr *instr, IR::PropertySymOpnd *prop
     if (propertySymOpnd->MayNeedTypeCheckProtection())
     {
         bool isCheckFixedFld = instr->m_opcode == Js::OpCode::CheckFixedFld;
-        AssertMsg(!isCheckFixedFld || !PHASE_OFF(Js::FixedMethodsPhase, instr->m_func->GetJnFunction()) ||
-            !PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func->GetJnFunction()), "CheckFixedFld with fixed method/data phase disabled?");
+        AssertMsg(!isCheckFixedFld || !PHASE_OFF(Js::FixedMethodsPhase, instr->m_func) ||
+            !PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func), "CheckFixedFld with fixed method/data phase disabled?");
         Assert(!isStore || !isCheckFixedFld);
         // We don't share caches between field loads and stores.  We should never have a field store involving a proto cache.
         Assert(!isStore || !propertySymOpnd->IsLoadedFromProto());

+ 4 - 4
lib/Backend/GlobOptFields.cpp

@@ -601,7 +601,7 @@ GlobOpt::PreparePrepassFieldHoisting(Loop * loop)
     if (Js::Configuration::Global.flags.TestTrace.IsEnabled(Js::FieldHoistPhase, this->func->GetSourceContextId(), this->func->GetLocalFunctionId()))
     {
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
-        Output::Print(L"FieldHoist: START LOOP function %s (%s)\n", this->func->GetWorkItem()->GetDisplayName(), this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
+        Output::Print(L"FieldHoist: START LOOP function %s (%s)\n", this->func->GetWorkItem()->GetDisplayName(), this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer));
     }
 #endif
 
@@ -1555,7 +1555,7 @@ GlobOpt::GenerateHoistFieldLoad(PropertySym * sym, Loop * loop, IR::Instr * inst
     if (Js::Configuration::Global.flags.TestTrace.IsEnabled(Js::FieldHoistPhase, this->func->GetSourceContextId(), this->func->GetLocalFunctionId()))
     {
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
-        Output::Print(L"    FieldHoist: function %s (%s) ", this->func->GetWorkItem()->GetDisplayName(), this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
+        Output::Print(L"    FieldHoist: function %s (%s) ", this->func->GetWorkItem()->GetDisplayName(), this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer));
         newInstr->DumpTestTrace();
     }
 #endif
@@ -2809,8 +2809,8 @@ GlobOpt::SetTypeCheckBailOut(IR::Opnd *opnd, IR::Instr *instr, BailOutInfo *bail
             // been checked upstream and no bailout is necessary here.
             if (instr->m_opcode == Js::OpCode::CheckFixedFld)
             {
-                AssertMsg(!PHASE_OFF(Js::FixedMethodsPhase, instr->m_func->GetJnFunction()) ||
-                    !PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func->GetJnFunction()), "CheckFixedFld with fixed method/data phase disabled?");
+                AssertMsg(!PHASE_OFF(Js::FixedMethodsPhase, instr->m_func) ||
+                    !PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func), "CheckFixedFld with fixed method/data phase disabled?");
                 Assert(isTypeCheckProtected);
                 AssertMsg(instr->GetBailOutKind() == IR::BailOutFailedFixedFieldTypeCheck || instr->GetBailOutKind() == IR::BailOutFailedEquivalentFixedFieldTypeCheck,
                     "Only BailOutFailed[Equivalent]FixedFieldTypeCheck can be safely removed.  Why does CheckFixedFld carry a different bailout kind?.");

+ 4 - 4
lib/Backend/IR.cpp

@@ -1289,7 +1289,7 @@ BailOutInstrTemplate<InstrType>::New(Js::OpCode opcode, BailOutKind kind, BailOu
     // If the function has bailout instructions, we keep the loop bodies alive
     // in case we bail out to the interpreter, so that we can reuse the jitted
     // loop bodies
-    func->GetJnFunction()->SetHasBailoutInstrInJittedCode(true);
+    func->GetJITOutput()->SetHasBailoutInstr(true);
 
     return bailOutInstr;
 }
@@ -3918,7 +3918,7 @@ Instr::DumpFieldCopyPropTestTrace()
     case Js::OpCode::TypeofElem:
 
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
-        Output::Print(L"TestTrace fieldcopyprop: function %s (%s) ", this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
+        Output::Print(L"TestTrace fieldcopyprop: function %s (%s) ", this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer));
         if (this->IsInlined())
         {
             Js::FunctionBody* topFunctionBody = this->m_func->GetTopFunc()->GetJnFunction();
@@ -3974,7 +3974,7 @@ Instr::DumpByteCodeOffset()
     {
         Output::SkipToColumn(78);
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
-        Output::Print(L" Func #%s", this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
+        Output::Print(L" Func #%s", this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer));
     }
 #ifdef BAILOUT_INJECTION
     if (this->bailOutByteCodeLocation != (uint)-1)
@@ -4263,7 +4263,7 @@ PrintByteCodeOffsetEtc:
             if (!bailOutInfo->bailOutFunc->IsTopFunc())
             {
                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
-                Output::Print(L" Func %s", bailOutInfo->bailOutFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
+                Output::Print(L" Func %s", bailOutInfo->bailOutFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer));
             }
             Output::Print(L" (%S)", this->GetBailOutKindName());
         }

+ 11 - 14
lib/Backend/IRBuilder.cpp

@@ -397,7 +397,7 @@ IRBuilder::Build()
     Func * topFunc = this->m_func->GetTopFunc();
     if (topFunc->HasTry() &&
         ((!topFunc->HasFinally() && !topFunc->IsLoopBody() && !PHASE_OFF(Js::OptimizeTryCatchPhase, topFunc)) ||
-        (topFunc->IsSimpleJit() && topFunc->GetJnFunction()->DoJITLoopBody()))) // should be relaxed as more bailouts are added in Simple Jit
+        (topFunc->IsSimpleJit() && topFunc->GetJITFunctionBody()->DoJITLoopBody()))) // should be relaxed as more bailouts are added in Simple Jit
     {
         this->catchOffsetStack = JitAnew(m_tempAlloc, SList<uint>, m_tempAlloc);
     }
@@ -933,7 +933,7 @@ IRBuilder::EmitClosureRangeChecks()
     }
 
     // If not a loop, but there are loops and trys, restore scope slot pointer and FD
-    if (!m_func->IsLoopBody() && m_func->HasTry() && m_func->GetJnFunction()->GetByteCodeInLoopCount() != 0)
+    if (!m_func->IsLoopBody() && m_func->HasTry() && m_func->GetJITFunctionBody()->GetByteCodeInLoopCount() != 0)
     {
         BVSparse<JitArenaAllocator> * bv = nullptr;
         if (m_func->GetLocalClosureSym() && m_func->GetLocalClosureSym()->HasByteCodeRegSlot())
@@ -1334,9 +1334,8 @@ IRBuilder::BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type, bool isCatchObjectS
 void
 IRBuilder::BuildImplicitArgIns()
 {
-    Js::FunctionBody * functionBody = this->m_func->GetJnFunction();
     Js::RegSlot startReg = m_func->GetJITFunctionBody()->GetConstCount() - 1;
-    for (Js::ArgSlot i = 1; i < functionBody->GetInParamsCount(); i++)
+    for (Js::ArgSlot i = 1; i < m_func->GetJITFunctionBody()->GetInParamsCount(); i++)
     {
         this->BuildArgIn((uint32)-1, startReg + i, i);
     }
@@ -2539,7 +2538,7 @@ IRBuilder::BuildUnsigned1(Js::OpCode newOpcode, uint32 offset, uint32 num)
 
         case Js::OpCode::ProfiledLoopBodyStart:
         {
-            if (!(m_func->DoSimpleJitDynamicProfile() && m_func->GetJnFunction()->DoJITLoopBody()))
+            if (!(m_func->DoSimpleJitDynamicProfile() && m_func->GetJITFunctionBody()->DoJITLoopBody()))
             {
                 // This opcode is removed from the IR when we aren't doing Profiling SimpleJit or not jitting loop bodies
                 break;
@@ -2577,7 +2576,7 @@ IRBuilder::BuildUnsigned1(Js::OpCode newOpcode, uint32 offset, uint32 num)
         case Js::OpCode::ProfiledLoopStart:
         {
             // If we're in profiling SimpleJit and jitting loop bodies, we need to keep this until lowering.
-            if (m_func->DoSimpleJitDynamicProfile() && m_func->GetJnFunction()->DoJITLoopBody())
+            if (m_func->DoSimpleJitDynamicProfile() && m_func->GetJITFunctionBody()->DoJITLoopBody())
             {
                 // In order for the JIT engine to correctly allocate registers we need to have this set up before lowering.
 
@@ -2627,7 +2626,7 @@ IRBuilder::BuildUnsigned1(Js::OpCode newOpcode, uint32 offset, uint32 num)
         case Js::OpCode::ProfiledLoopEnd:
         {
             // TODO: Decide whether we want the implicit loop call flags to be recorded in simplejitted loop bodies
-            if (m_func->DoSimpleJitDynamicProfile() && m_func->GetJnFunction()->DoJITLoopBody())
+            if (m_func->DoSimpleJitDynamicProfile() && m_func->GetJITFunctionBody()->DoJITLoopBody())
             {
                 Assert(this->m_saveLoopImplicitCallFlags[num]);
 
@@ -3136,12 +3135,12 @@ IRBuilder::BuildProfiledSlotLoad(Js::OpCode loadOp, IR::RegOpnd *dstOpnd, IR::Sy
 #if ENABLE_DEBUG_CONFIG_OPTIONS
         if(Js::Configuration::Global.flags.TestTrace.IsEnabled(Js::DynamicProfilePhase))
         {
-            Js::FunctionBody * func = this->m_func->GetJnFunction();
+            const JITTimeFunctionBody * func = m_func->GetJITFunctionBody();
             const ValueType valueType(instr->AsProfiledInstr()->u.FldInfo().valueType);
             char valueTypeStr[VALUE_TYPE_MAX_STRING_SIZE];
             valueType.ToString(valueTypeStr);
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
-            Output::Print(L"TestTrace function %s (#%s) ValueType = %S ", func->GetDisplayName(), func->GetDebugNumberSet(debugStringBuffer), valueTypeStr);
+            Output::Print(L"TestTrace function %s (#%s) ValueType = %S ", m_func->GetWorkItem()->GetDisplayName(), func->GetDebugNumberSet(debugStringBuffer), valueTypeStr);
             instr->DumpTestTrace();
         }
 #endif
@@ -3917,9 +3916,7 @@ IRBuilder::BuildProfiledFieldLoad(Js::OpCode loadOp, IR::RegOpnd *dstOpnd, IR::S
 
 Js::RegSlot IRBuilder::GetEnvRegForEvalCode() const
 {
-    Js::FunctionBody * functionBody = m_func->GetJnFunction();
-
-    if (functionBody->GetIsStrictMode() && functionBody->GetIsGlobalFunc())
+    if (m_func->GetJITFunctionBody()->IsStrictMode() && m_func->GetJITFunctionBody()->IsGlobalFunc())
     {
         return m_func->GetJITFunctionBody()->GetLocalFrameDisplayReg();
     }
@@ -5190,7 +5187,7 @@ IRBuilder::BuildElementI(Js::OpCode newOpcode, uint32 offset, Js::RegSlot baseRe
             if (!this->m_func->HasProfileInfo() ||
                 (
                     PHASE_OFF(Js::TypedArrayPhase, this->m_func->GetTopFunc()) &&
-                    PHASE_OFF(Js::ArrayCheckHoistPhase, this->m_func->GetJnFunction())
+                    PHASE_OFF(Js::ArrayCheckHoistPhase, this->m_func)
                 ))
             {
                 break;
@@ -5206,7 +5203,7 @@ IRBuilder::BuildElementI(Js::OpCode newOpcode, uint32 offset, Js::RegSlot baseRe
             if (!this->m_func->HasProfileInfo() ||
                 (
                     PHASE_OFF(Js::TypedArrayPhase, this->m_func->GetTopFunc()) &&
-                    PHASE_OFF(Js::ArrayCheckHoistPhase, this->m_func->GetJnFunction())
+                    PHASE_OFF(Js::ArrayCheckHoistPhase, this->m_func)
                 ))
             {
                 break;

+ 33 - 33
lib/Backend/Inline.cpp

@@ -18,12 +18,12 @@ Inline::Optimize(Func *func, __in_ecount_opt(callerArgOutCount) IR::Instr *calle
         return;
     }
 
-    bool doFixedMethods = !PHASE_OFF(Js::FixedMethodsPhase, func->GetJnFunction());
+    bool doFixedMethods = !PHASE_OFF(Js::FixedMethodsPhase, func);
     const auto inlinerData = func->m_jitTimeData;
 
     bool doInline = (inlinerData->InlineeCount() > 0 || inlinerData->IsLdFldInlineePresent());
     if (PHASE_OFF(Js::InlinePhase, this->topFunc) ||
-        PHASE_OFF(Js::InlinePhase, func->GetJnFunction()) ||
+        PHASE_OFF(Js::InlinePhase, func) ||
         func->IsJitInDebugMode())
     {
         doInline = false;
@@ -171,7 +171,7 @@ Inline::Optimize(Func *func, __in_ecount_opt(callerArgOutCount) IR::Instr *calle
                     }
 
                     const auto profileId = static_cast<Js::ProfileId>(instr->AsProfiledInstr()->u.profileId);
-                    if(profileId >= func->GetJnFunction()->GetProfiledCallSiteCount())
+                    if(profileId >= func->GetJITFunctionBody()->GetProfiledCallSiteCount())
                     {
                         TryResetObjTypeSpecFldInfoOn(methodValueOpnd);
                         TryDisableRuntimePolymorphicCacheOn(methodValueOpnd);
@@ -190,8 +190,8 @@ Inline::Optimize(Func *func, __in_ecount_opt(callerArgOutCount) IR::Instr *calle
                     {
                         isPolymorphic = true;
                         if (isCtor ||
-                            (PHASE_OFF(Js::PolymorphicInlinePhase, this->topFunc) || PHASE_OFF(Js::PolymorphicInlinePhase, func->GetJnFunction())) ||
-                            (this->IsInliningOutSideLoops() && !PHASE_FORCE(Js::InlinePhase, this->topFunc) && !PHASE_FORCE(Js::InlinePhase, func->GetJnFunction())))
+                            (PHASE_OFF(Js::PolymorphicInlinePhase, this->topFunc) || PHASE_OFF(Js::PolymorphicInlinePhase, func)) ||
+                            (this->IsInliningOutSideLoops() && !PHASE_FORCE(Js::InlinePhase, this->topFunc) && !PHASE_FORCE(Js::InlinePhase, func)))
                         {
 #if defined(DBG_DUMP) || defined(ENABLE_DEBUG_CONFIG_OPTIONS)
                             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
@@ -297,7 +297,7 @@ Inline::Optimize(Func *func, __in_ecount_opt(callerArgOutCount) IR::Instr *calle
                             }
 
                             uint16 constantArguments = 0;
-                            if (!PHASE_OFF(Js::InlineRecursivePhase, func->GetJnFunction()))
+                            if (!PHASE_OFF(Js::InlineRecursivePhase, func))
                             {
                                 instr->IterateArgInstrs([&](IR::Instr* argInstr) {
                                     IR::Opnd *src1 = argInstr->GetSrc1();
@@ -365,7 +365,7 @@ Inline::Optimize(Func *func, __in_ecount_opt(callerArgOutCount) IR::Instr *calle
                 }
 
                 const auto profileId = static_cast<Js::ProfileId>(instr->AsProfiledInstr()->u.profileId);
-                if (profileId >= func->GetJnFunction()->GetProfiledCallSiteCount())
+                if (profileId >= func->GetJITFunctionBody()->GetProfiledCallSiteCount())
                 {
                     break;
                 }
@@ -1273,9 +1273,9 @@ bool
 Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, Js::FunctionInfo* functionInfo, bool isPolymorphic, bool isBuiltIn, bool isCtor, bool isInlined, bool &safeThis,
                                             bool dontOptimizeJustCheck, uint i /*i-th inlinee at a polymorphic call site*/)
 {
-    Assert(!callInstr->m_func->GetJnFunction()->GetHasTry());
+    Assert(!callInstr->m_func->GetJITFunctionBody()->HasTry());
 
-    if (PHASE_OFF(Js::FixedMethodsPhase, callInstr->m_func->GetJnFunction()))
+    if (PHASE_OFF(Js::FixedMethodsPhase, callInstr->m_func))
     {
         return false;
     }
@@ -1288,8 +1288,8 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, Js::FunctionIn
     wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
     wchar_t debugStringBuffer2[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
     bool printFixedFieldsTrace =
-        ((PHASE_TRACE(Js::FixedMethodsPhase, callInstr->m_func->GetJnFunction()) || PHASE_TESTTRACE(Js::FixedMethodsPhase, callInstr->m_func->GetJnFunction()) ||
-        (isCtor && PHASE_TRACE(Js::FixedNewObjPhase, callInstr->m_func->GetJnFunction()) || PHASE_TESTTRACE(Js::FixedNewObjPhase, callInstr->m_func->GetJnFunction()))) && !dontOptimizeJustCheck);
+        ((PHASE_TRACE(Js::FixedMethodsPhase, callInstr->m_func) || PHASE_TESTTRACE(Js::FixedMethodsPhase, callInstr->m_func) ||
+        (isCtor && PHASE_TRACE(Js::FixedNewObjPhase, callInstr->m_func) || PHASE_TESTTRACE(Js::FixedNewObjPhase, callInstr->m_func))) && !dontOptimizeJustCheck);
 
     if (printFixedFieldsTrace)
     {
@@ -1359,16 +1359,16 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, Js::FunctionIn
     IR::PropertySymOpnd* methodPropertyOpnd = ldMethodFldInstr->GetSrc1()->AsPropertySymOpnd();
 
     if ((isCtor &&
-            ((isInlined && PHASE_OFF(Js::FixedCtorInliningPhase, callInstr->m_func->GetJnFunction())) ||
-            (!isInlined && PHASE_OFF(Js::FixedCtorCallsPhase, callInstr->m_func->GetJnFunction())) ||
+            ((isInlined && PHASE_OFF(Js::FixedCtorInliningPhase, callInstr->m_func)) ||
+            (!isInlined && PHASE_OFF(Js::FixedCtorCallsPhase, callInstr->m_func)) ||
             (methodPropertyOpnd->UsesAccessor()))) ||
         (!isCtor &&
             ((isBuiltIn &&
-                ((isInlined && PHASE_OFF(Js::FixedBuiltInMethodInliningPhase, callInstr->m_func->GetJnFunction())) ||
-                (!isInlined && PHASE_OFF(Js::FixedBuiltInMethodCallsPhase, callInstr->m_func->GetJnFunction())))) ||
+                ((isInlined && PHASE_OFF(Js::FixedBuiltInMethodInliningPhase, callInstr->m_func)) ||
+                (!isInlined && PHASE_OFF(Js::FixedBuiltInMethodCallsPhase, callInstr->m_func)))) ||
             (!isBuiltIn &&
-                ((isInlined && PHASE_OFF(Js::FixedScriptMethodInliningPhase, callInstr->m_func->GetJnFunction())) ||
-                (!isInlined && !PHASE_ON(Js::FixedScriptMethodCallsPhase, callInstr->m_func->GetJnFunction()))))))
+                ((isInlined && PHASE_OFF(Js::FixedScriptMethodInliningPhase, callInstr->m_func)) ||
+                (!isInlined && !PHASE_ON(Js::FixedScriptMethodCallsPhase, callInstr->m_func))))))
        )
     {
 #if TRACE_FIXED_FIELDS
@@ -1494,7 +1494,7 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, Js::FunctionIn
             const wchar_t* profileFunctionName    = profileFunctionBody != nullptr ? profileFunctionBody->GetDisplayName() : L"<unknown>";
             const wchar_t* profileFunctionNumbers = profileFunctionBody ? profileFunctionBody->GetDebugNumberSet(debugStringBuffer3) : L"(null)";
 
-            if (PHASE_TRACE(Js::FixedMethodsPhase, callInstr->m_func->GetJnFunction()))
+            if (PHASE_TRACE(Js::FixedMethodsPhase, callInstr->m_func))
             {
                 Output::Print(L"FixedFields: function %s (#%s): function body mismatch for inlinee: %s (%s) 0x%p->0x%p != %s (%s) 0x%p (cache id: %d, layout: %s, type: 0x%p, proto: 0x%p, proto type: 0x%p).\n",
                     callerFunctionBody->GetDisplayName(), callerFunctionBody->GetDebugNumberSet(debugStringBuffer),
@@ -1503,7 +1503,7 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, Js::FunctionIn
                     methodPropertyOpnd->m_inlineCacheIndex, isProto ? L"proto" : isAccessor ? L"accessor" : L"local",
                     methodPropertyOpnd->GetType(), protoObject, protoObject != nullptr ? protoObject->GetType() : nullptr);
             }
-            if (PHASE_TESTTRACE(Js::FixedMethodsPhase, callInstr->m_func->GetJnFunction()))
+            if (PHASE_TESTTRACE(Js::FixedMethodsPhase, callInstr->m_func))
             {
                 Output::Print(L"FixedFields: function %s (%s): function body mismatch for inlinee: %s (%s) != %s (%s) (cache id: %d, layout: %s).\n",
                     callerFunctionBody->GetDisplayName(), callerFunctionBody->GetDebugNumberSet(debugStringBuffer),
@@ -1578,7 +1578,7 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, Js::FunctionIn
         {
 
 #if ENABLE_DEBUG_CONFIG_OPTIONS
-            if (PHASE_TRACE(Js::FixedNewObjPhase, callInstr->m_func->GetJnFunction()) || PHASE_TESTTRACE(Js::FixedNewObjPhase, callInstr->m_func->GetJnFunction()))
+            if (PHASE_TRACE(Js::FixedNewObjPhase, callInstr->m_func) || PHASE_TESTTRACE(Js::FixedNewObjPhase, callInstr->m_func))
             {
                 Js::FunctionBody* callerFunctionBody = callInstr->m_func->GetJnFunction();
                 Js::FunctionBody* calleeFunctionBody = functionInfo != nullptr && functionInfo->HasBody() ? functionInfo->GetFunctionBody() : nullptr;
@@ -1617,7 +1617,7 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, Js::FunctionIn
         else
         {
 #if ENABLE_DEBUG_CONFIG_OPTIONS
-            if (PHASE_TRACE(Js::FixedNewObjPhase, callInstr->m_func->GetJnFunction()) || PHASE_TESTTRACE(Js::FixedNewObjPhase, callInstr->m_func->GetJnFunction()))
+            if (PHASE_TRACE(Js::FixedNewObjPhase, callInstr->m_func) || PHASE_TESTTRACE(Js::FixedNewObjPhase, callInstr->m_func))
             {
                 Js::FunctionBody* callerFunctionBody = callInstr->m_func->GetJnFunction();
                 Js::FunctionBody* calleeFunctionBody = functionInfo != nullptr && functionInfo->HasBody() ? functionInfo->GetFunctionBody() : nullptr;
@@ -1679,8 +1679,8 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, Js::FunctionIn
 Js::Var
 Inline::TryOptimizeInstrWithFixedDataProperty(IR::Instr *&instr)
 {
-    if (PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func->GetJnFunction()) ||
-        PHASE_OFF(Js::UseFixedDataPropsInInlinerPhase, instr->m_func->GetJnFunction()))
+    if (PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func) ||
+        PHASE_OFF(Js::UseFixedDataPropsInInlinerPhase, instr->m_func))
     {
         return nullptr;
     }
@@ -2487,7 +2487,7 @@ bool Inline::InlineApplyTarget(IR::Instr *callInstr, const Js::FunctionCodeGenJi
     if (this->isApplyTargetInliningInProgress)
     {
         INLINE_TESTTRACE(L"INLINING: Skip Inline: Skipping apply target inlining, Recursive apply inlining is not supported \tCaller: %s\t(%s) \tTop Func:%s\t(%s)\n", inlinerData->GetFunctionBody()->GetDisplayName(),
-                                inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer), this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer2));
+                                inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer), this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer2));
         return false;
     }
 
@@ -2526,7 +2526,7 @@ bool Inline::InlineApplyTarget(IR::Instr *callInstr, const Js::FunctionCodeGenJi
     if (callInstr->m_func->IsTopFunc())
     {
         INLINE_TESTTRACE(L"INLINING: Skip Inline: Skipping apply target inlining in top func\tCaller: %s\t(%s) \tTop Func:%s\t(%s)\n", inlinerData->GetFunctionBody()->GetDisplayName(),
-            inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer), this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer2));
+            inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer), this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer2));
         return false;
     }
 
@@ -2701,7 +2701,7 @@ Inline::InlineCall(IR::Instr *callInstr, Js::FunctionInfo *funcInfo, const Js::F
     Func *func = callInstr->m_func;
 
     *pIsInlined = false;
-    if (PHASE_OFF(Js::InlineCallPhase, this->topFunc) || PHASE_OFF(Js::InlineCallPhase, func->GetJnFunction())
+    if (PHASE_OFF(Js::InlineCallPhase, this->topFunc) || PHASE_OFF(Js::InlineCallPhase, func)
         || !this->topFunc->GetJITFunctionBody()->GetInParamsCount())
     {
         return callInstr;
@@ -2922,11 +2922,11 @@ Inline::SkipCallApplyTargetInlining_Shared(IR::Instr *callInstr, const Js::Funct
 
     Assert(isApplyTarget ^ isCallTarget);
 
-    if (PHASE_OFF(Js::FixedMethodsPhase, callInstr->m_func->GetJnFunction()))
+    if (PHASE_OFF(Js::FixedMethodsPhase, callInstr->m_func))
     {
         INLINE_TESTTRACE(L"INLINING: Skip Inline: Skipping %s target inlining, Fixed Methods turned off\tCaller: %s\t(#%d) \tTop Func:%s\t(#%d)\n", isApplyTarget ? L"apply" : L"call" ,
             inlinerData->GetFunctionBody()->GetDisplayName(), inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer),
-            this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer2));
+            this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer2));
         return true;
     }
 
@@ -2934,7 +2934,7 @@ Inline::SkipCallApplyTargetInlining_Shared(IR::Instr *callInstr, const Js::Funct
     {
         INLINE_TESTTRACE(L"INLINING: Skip Inline: Skipping %s target inlining, inlineeData not present\tCaller: %s\t(#%d) \tTop Func:%s\t(#%d)\n", isApplyTarget ? L"apply" : L"call",
             inlinerData->GetFunctionBody()->GetDisplayName(), inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer),
-            this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer2));
+            this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer2));
         return true;
     }
 
@@ -2944,7 +2944,7 @@ Inline::SkipCallApplyTargetInlining_Shared(IR::Instr *callInstr, const Js::Funct
         {
             INLINE_TESTTRACE(L"INLINING: Skip Inline: Skipping .call inlining, target is a built-in\tCaller: %s\t(#%d) \tTop Func:%s\t(#%d)\n",
                 inlinerData->GetFunctionBody()->GetDisplayName(), inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer),
-                this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer2));
+                this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer2));
         }
         return true;
     }
@@ -2954,7 +2954,7 @@ Inline::SkipCallApplyTargetInlining_Shared(IR::Instr *callInstr, const Js::Funct
         INLINE_TESTTRACE(L"INLINING: Skip Inline: Skipping %s target inlining, not registered as a LdFld inlinee \tInlinee: %s (#%d)\tCaller: %s\t(#%d) \tTop Func:%s\t(#%d)\n", isApplyTarget ? L"apply" : L"call",
             inlineeData->GetFunctionBody()->GetDisplayName(), inlineeData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer),
             inlinerData->GetFunctionBody()->GetDisplayName(), inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer2),
-            this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer3));
+            this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer3));
         return true;
     }
 
@@ -2999,7 +2999,7 @@ Inline::TryGetFixedMethodsForBuiltInAndTarget(IR::Instr *callInstr, const Js::Fu
             INLINE_TESTTRACE(L"INLINING: Skip Inline: Skipping %s target inlining, did not get fixed method for %s target \tInlinee: %s (#%d)\tCaller: %s\t(#%d) \tTop Func:%s\t(#%d)\n", isApplyTarget ? L"apply" : L"call", isApplyTarget ? L"apply" : L"call",
                 inlineeData->GetFunctionBody()->GetDisplayName(), inlineeData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                 inlinerData->GetFunctionBody()->GetDisplayName(), inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer2),
-                this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer3));
+                this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer3));
             return false;
         }
     }
@@ -3008,7 +3008,7 @@ Inline::TryGetFixedMethodsForBuiltInAndTarget(IR::Instr *callInstr, const Js::Fu
         INLINE_TESTTRACE(L"INLINING: Skip Inline: Skipping %s target inlining, did not get fixed method for %s \tInlinee: %s (#%d)\tCaller: %s\t(#%d) \tTop Func:%s\t(#%d)\n", isApplyTarget ? L"apply" : L"call", isApplyTarget ? L"apply" : L"call",
             inlineeData->GetFunctionBody()->GetDisplayName(), inlineeData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer),
             inlinerData->GetFunctionBody()->GetDisplayName(), inlinerData->GetFunctionBody()->GetDebugNumberSet(debugStringBuffer2),
-            this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJnFunction()->GetDebugNumberSet(debugStringBuffer3));
+            this->topFunc->GetWorkItem()->GetDisplayName(), this->topFunc->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer3));
         return false;
     }
 

+ 7 - 0
lib/Backend/JITOutput.cpp

@@ -32,6 +32,13 @@ JITOutput::SetVarChangedOffset(int32 offset)
     m_outputData->writeableEPData.localVarChangedOffset = offset;
 }
 
+void
+JITOutput::SetHasBailoutInstr(bool val)
+{
+    m_outputData->hasBailoutInstr = val;
+}
+
+
 intptr_t
 JITOutput::GetCodeAddress() const
 {

+ 1 - 0
lib/Backend/JITOutput.h

@@ -14,6 +14,7 @@ public:
 
     void SetVarSlotsOffset(int32 offset);
     void SetVarChangedOffset(int32 offset);
+    void SetHasBailoutInstr(bool val);
 
     intptr_t GetCodeAddress() const;
 

+ 55 - 0
lib/Backend/JITTimeFunctionBody.cpp

@@ -11,6 +11,12 @@ JITTimeFunctionBody::JITTimeFunctionBody(FunctionBodyJITData * bodyData) :
     InitializeStatementMap();
 }
 
+intptr_t
+JITTimeFunctionBody::GetAddr() const
+{
+    return m_bodyData->functionBodyAddr;
+}
+
 uint
 JITTimeFunctionBody::GetFunctionNumber() const
 {
@@ -149,6 +155,27 @@ JITTimeFunctionBody::GetThisRegForEventHandler() const
     return static_cast<Js::RegSlot>(m_bodyData->thisRegisterForEventHandler);
 }
 
+Js::RegSlot
+JITTimeFunctionBody::GetFirstNonTempLocalIndex() const
+{
+    // First local var starts when the const vars end.
+    return GetConstCount();
+}
+
+Js::RegSlot
+JITTimeFunctionBody::GetEndNonTempLocalIndex() const
+{
+    // It will give the index on which current non temp locals ends, which is a first temp reg.
+    return GetFirstTmpReg() != Js::Constants::NoRegister ? GetFirstTmpReg() : GetLocalsCount();
+}
+
+Js::RegSlot
+JITTimeFunctionBody::GetNonTempLocalVarCount() const
+{
+    Assert(GetEndNonTempLocalIndex() >= GetFirstNonTempLocalIndex());
+    return GetEndNonTempLocalIndex() - GetFirstNonTempLocalIndex();
+}
+
 Js::PropertyId
 JITTimeFunctionBody::GetPropertyIdFromCacheId(uint cacheId) const
 {
@@ -276,6 +303,24 @@ JITTimeFunctionBody::HasRestParameter() const
     return Js::FunctionBody::GetHasRestParameter(GetFlags());
 }
 
+bool
+JITTimeFunctionBody::IsGlobalFunc() const
+{
+    return m_bodyData->isGlobalFunc != FALSE;
+}
+
+bool
+JITTimeFunctionBody::IsNonTempLocalVar(uint32 varIndex) const
+{
+    return GetFirstNonTempLocalIndex() <= varIndex && varIndex < GetEndNonTempLocalIndex();
+}
+
+bool
+JITTimeFunctionBody::DoJITLoopBody() const
+{
+    return m_bodyData->doJITLoopBody != FALSE;
+}
+
 const byte *
 JITTimeFunctionBody::GetByteCodeBuffer() const
 {
@@ -364,3 +409,13 @@ JITTimeFunctionBody::InitializeStatementMap()
             offsetsLength * sizeof(uint32));
     }
 }
+
+wchar_t*
+JITTimeFunctionBody::GetDebugNumberSet(wchar(&bufferToWriteTo)[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE]) const
+{
+    // (#%u.%u), #%u --> (source file Id . function Id) , function Number
+    int len = swprintf_s(bufferToWriteTo, MAX_FUNCTION_BODY_DEBUG_STRING_SIZE, L" (#%d.%u), #%u",
+        (int)GetSourceContextId(), GetLocalFunctionId(), GetFunctionNumber());
+    Assert(len > 8);
+    return bufferToWriteTo;
+}

+ 10 - 0
lib/Backend/JITTimeFunctionBody.h

@@ -10,6 +10,8 @@ class JITTimeFunctionBody
 public:
     JITTimeFunctionBody(FunctionBodyJITData * bodyData);
 
+    intptr_t GetAddr() const;
+
     uint GetFunctionNumber() const;
     uint GetLocalFunctionId() const;
     uint GetSourceContextId() const;
@@ -33,6 +35,9 @@ public:
     Js::RegSlot GetTempCount() const;
     Js::RegSlot GetFuncExprScopeReg() const;
     Js::RegSlot GetThisRegForEventHandler() const;
+    Js::RegSlot GetFirstNonTempLocalIndex() const;
+    Js::RegSlot GetEndNonTempLocalIndex() const;
+    Js::RegSlot GetNonTempLocalVarCount() const;
 
     Js::PropertyId GetPropertyIdFromCacheId(uint cacheId) const;
 
@@ -56,6 +61,9 @@ public:
     bool HasCachedScopePropIds() const;
     bool HasInlineCachesOnFunctionObject() const;
     bool DoInterruptProbe() const;
+    bool IsGlobalFunc() const;
+    bool IsNonTempLocalVar(uint32 varIndex) const;
+    bool DoJITLoopBody() const;
 
     const byte * GetByteCodeBuffer() const;
     Js::SmallSpanSequence * GetStatementMapSpanSequence();
@@ -64,6 +72,8 @@ public:
     intptr_t GetInlineCache(uint index) const;
     Js::TypeId GetConstantType(Js::RegSlot location) const;
 
+    wchar_t* GetDebugNumberSet(wchar(&bufferToWriteTo)[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE]) const;
+
 private:
     Js::FunctionInfo::Attributes GetAttributes() const;
     Js::FunctionBody::FunctionBodyFlags GetFlags() const;

+ 5 - 5
lib/Backend/LinearScan.cpp

@@ -1281,7 +1281,7 @@ LinearScan::EnsureGlobalBailOutRecordTable(Func *func)
         globalBailOutRecordDataTable->isLoopBody = topFunc->IsLoopBody();
         globalBailOutRecordDataTable->returnValueRegSlot = func->returnValueRegSlot;
         globalBailOutRecordDataTable->firstActualStackOffset = -1;
-        globalBailOutRecordDataTable->registerSaveSpace = func->GetScriptContext()->GetThreadContext()->GetBailOutRegisterSaveSpace();
+        globalBailOutRecordDataTable->registerSaveSpace = (Js::Var*)func->GetThreadContextInfo()->GetBailOutRegisterSaveSpace();
         globalBailOutRecordDataTable->globalBailOutRecordDataRows = nullptr;
 
 #ifdef PROFILE_BAILOUT_RECORD_MEMORY
@@ -1527,7 +1527,7 @@ LinearScan::FillBailOutRecord(IR::Instr * instr)
 
         if (hasFormalArgs)
         {
-            for (uint32 index = functionBody->GetFirstNonTempLocalIndex(); index < functionBody->GetEndNonTempLocalIndex(); index++)
+            for (uint32 index = func->GetJITFunctionBody()->GetFirstNonTempLocalIndex(); index < func->GetJITFunctionBody()->GetEndNonTempLocalIndex(); index++)
             {
                 StackSym * stackSym = this->func->m_symTable->FindStackSym(index);
                 if (stackSym != nullptr)
@@ -1535,9 +1535,9 @@ LinearScan::FillBailOutRecord(IR::Instr * instr)
                     Func * stackSymFunc = stackSym->GetByteCodeFunc();
 
                     Js::RegSlot regSlotId = stackSym->GetByteCodeRegSlot();
-                    if (functionBody->IsNonTempLocalVar(regSlotId))
+                    if (func->IsNonTempLocalVar(regSlotId))
                     {
-                        if (!propertyIdContainer->IsRegSlotFormal(regSlotId - functionBody->GetFirstNonTempLocalIndex()))
+                        if (!propertyIdContainer->IsRegSlotFormal(regSlotId - func->GetJITFunctionBody()->GetFirstNonTempLocalIndex()))
                         {
                             continue;
                         }
@@ -1931,7 +1931,7 @@ LinearScan::FillBailOutRecord(IR::Instr * instr)
         if(PHASE_DUMP(Js::BailOutPhase, this->func))
         {
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
-            Output::Print(L"Bailout function: %s [%s]\n", funcBailOutData[i].func->GetWorkItem()->GetDisplayName(), funcBailOutData[i].func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer), i);
+            Output::Print(L"Bailout function: %s [%s]\n", funcBailOutData[i].func->GetWorkItem()->GetDisplayName(), funcBailOutData[i].func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer), i);
             funcBailOutData[i].bailOutRecord->Dump();
         }
 #endif

+ 53 - 58
lib/Backend/Lower.cpp

@@ -80,7 +80,7 @@ Lowerer::Lower()
 #ifdef DBG
             // Pre-fill all local slots with a pattern. This will help identify non-initialized/garbage var values.
             // Note that in the beginning of the function in bytecode we should initialize all locals to undefined.
-            uint32 localSlotCount = m_func->GetJnFunction()->GetEndNonTempLocalIndex() - m_func->GetJnFunction()->GetFirstNonTempLocalIndex();
+            uint32 localSlotCount = m_func->GetJITFunctionBody()->GetEndNonTempLocalIndex() - m_func->GetJITFunctionBody()->GetFirstNonTempLocalIndex();
             for (uint i = 0; i < localSlotCount; ++i)
             {
                 int offset = m_func->GetLocalVarSlotOffset(i);
@@ -377,7 +377,7 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
             }
 
         case Js::OpCode::CheckFixedFld:
-            AssertMsg(!PHASE_OFF(Js::FixedMethodsPhase, instr->m_func->GetJnFunction()) || !PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func->GetJnFunction()), "CheckFixedFld with fixed prop(Data|Method) phase disabled?");
+            AssertMsg(!PHASE_OFF(Js::FixedMethodsPhase, instr->m_func) || !PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func), "CheckFixedFld with fixed prop(Data|Method) phase disabled?");
             this->GenerateCheckFixedFld(instr);
             break;
 
@@ -2262,7 +2262,7 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
                 }
 
                 // If we turned off fulljit, there's no reason to do this.
-                if (!m_func->GetJnFunction()->DoFullJit())
+                if (PHASE_OFF(Js::FullJitPhase, m_func))
                 {
                     instr->Remove();
                 }
@@ -2310,7 +2310,7 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
                 //       Bailout
                 //   }
 
-                if (!m_func->GetJnFunction()->DoFullJit() || !m_func->GetJnFunction()->DoJITLoopBody())
+                if (PHASE_OFF(Js::FullJitPhase, m_func) || !m_func->GetJITFunctionBody()->DoJITLoopBody())
                 {
                     // If we're not doing fulljit, we've turned off JitLoopBodies, or if we don't have loop headers allocated (the function has a Try,  etc)
                     //      just move false to dobailout
@@ -3012,7 +3012,7 @@ Lowerer::LoadScriptContext(IR::Instr * instr)
 IR::Opnd *
 Lowerer::LoadFunctionBodyOpnd(IR::Instr * instr)
 {
-    return IR::AddrOpnd::New(instr->m_func->GetJnFunction(), IR::AddrOpndKindDynamicFunctionBody, instr->m_func);
+    return IR::AddrOpnd::New(instr->m_func->GetJITFunctionBody()->GetAddr(), IR::AddrOpndKindDynamicFunctionBody, instr->m_func);
 }
 
 IR::Opnd *
@@ -3041,47 +3041,47 @@ Lowerer::LoadScriptContextValueOpnd(IR::Instr * instr, ScriptContextValue valueT
 IR::Opnd *
 Lowerer::LoadLibraryValueOpnd(IR::Instr * instr, LibraryValue valueType, RegNum regNum)
 {
-    Js::ScriptContext *scriptContext = instr->m_func->GetScriptContext();
+    ScriptContextInfo *scriptContext = instr->m_func->GetScriptContextInfo();
     switch (valueType)
     {
     case LibraryValue::ValueEmptyString:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetEmptyString(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
+        return IR::AddrOpnd::New(scriptContext->GetEmptyStringAddr(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
     case LibraryValue::ValueUndeclBlockVar:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetUndeclBlockVar(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
+        return IR::AddrOpnd::New(scriptContext->GetUndeclBlockVarAddr(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
     case LibraryValue::ValueUndefined:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetUndefined(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
+        return IR::AddrOpnd::New(scriptContext->GetUndefinedAddr(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
     case LibraryValue::ValueNull:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetNull(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
+        return IR::AddrOpnd::New(scriptContext->GetNullAddr(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
     case LibraryValue::ValueTrue:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetTrue(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
+        return IR::AddrOpnd::New(scriptContext->GetTrueAddr(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
     case LibraryValue::ValueFalse:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetFalse(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
+        return IR::AddrOpnd::New(scriptContext->GetFalseAddr(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
     case LibraryValue::ValueNegativeZero:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetNegativeZero(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
+        return IR::AddrOpnd::New(scriptContext->GetNegativeZeroAddr(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
     case LibraryValue::ValueNumberTypeStatic:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetNumberTypeStatic(), IR::AddrOpndKindDynamicType, instr->m_func, true);
+        return IR::AddrOpnd::New(scriptContext->GetNumberTypeStaticAddr(), IR::AddrOpndKindDynamicType, instr->m_func, true);
     case LibraryValue::ValueStringTypeStatic:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetStringTypeStatic(), IR::AddrOpndKindDynamicType, instr->m_func, true);
+        return IR::AddrOpnd::New(scriptContext->GetStringTypeStaticAddr(), IR::AddrOpndKindDynamicType, instr->m_func, true);
     case LibraryValue::ValueObjectType:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetObjectType(), IR::AddrOpndKindDynamicType, instr->m_func);
+        return IR::AddrOpnd::New(scriptContext->GetObjectTypeAddr(), IR::AddrOpndKindDynamicType, instr->m_func);
     case LibraryValue::ValueObjectHeaderInlinedType:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetObjectHeaderInlinedType(), IR::AddrOpndKindDynamicType, instr->m_func);
+        return IR::AddrOpnd::New(scriptContext->GetObjectHeaderInlinedTypeAddr(), IR::AddrOpndKindDynamicType, instr->m_func);
     case LibraryValue::ValueRegexType:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetRegexType(), IR::AddrOpndKindDynamicType, instr->m_func);
+        return IR::AddrOpnd::New(scriptContext->GetRegexTypeAddr(), IR::AddrOpndKindDynamicType, instr->m_func);
     case LibraryValue::ValueArrayConstructor:
-        return IR::AddrOpnd::New(scriptContext->GetLibrary()->GetArrayConstructor(), IR::AddrOpndKindDynamicVar, instr->m_func);
+        return IR::AddrOpnd::New(scriptContext->GetArrayConstructorAddr(), IR::AddrOpndKindDynamicVar, instr->m_func);
     case LibraryValue::ValueJavascriptArrayType:
-        return IR::AddrOpnd::New(Js::JavascriptArray::GetInitialType(scriptContext), IR::AddrOpndKindDynamicType, instr->m_func);
+        return IR::AddrOpnd::New(Js::JavascriptArray::GetInitialType(nullptr), IR::AddrOpndKindDynamicType, instr->m_func);
     case LibraryValue::ValueNativeIntArrayType:
-        return IR::AddrOpnd::New(Js::JavascriptNativeIntArray::GetInitialType(scriptContext), IR::AddrOpndKindDynamicType, instr->m_func);
+        return IR::AddrOpnd::New(Js::JavascriptNativeIntArray::GetInitialType(nullptr), IR::AddrOpndKindDynamicType, instr->m_func);
     case LibraryValue::ValueNativeFloatArrayType:
-        return IR::AddrOpnd::New(Js::JavascriptNativeFloatArray::GetInitialType(scriptContext), IR::AddrOpndKindDynamicType, instr->m_func);
+        return IR::AddrOpnd::New(Js::JavascriptNativeFloatArray::GetInitialType(nullptr), IR::AddrOpndKindDynamicType, instr->m_func);
     case LibraryValue::ValueConstructorCacheDefaultInstance:
         return IR::AddrOpnd::New(m_func->GetThreadContextInfo()->GetConstructorCacheDefaultInstanceAddr(), IR::AddrOpndKindDynamicMisc, instr->m_func);
     case LibraryValue::ValueAbsDoubleCst:
         return IR::MemRefOpnd::New(m_func->GetThreadContextInfo()->GetAbsDoubleCstAddr(), TyMachDouble, instr->m_func, IR::AddrOpndKindDynamicDoubleRef);
     case LibraryValue::ValueCharStringCache:
-        return IR::AddrOpnd::New((Js::Var)&scriptContext->GetLibrary()->GetCharStringCache(), IR::AddrOpndKindDynamicCharStringCache, instr->m_func);
+        return IR::AddrOpnd::New(scriptContext->GetCharStringCacheAddr(), IR::AddrOpndKindDynamicCharStringCache, instr->m_func);
     default:
         Assert(false);
         return nullptr;
@@ -3091,7 +3091,7 @@ Lowerer::LoadLibraryValueOpnd(IR::Instr * instr, LibraryValue valueType, RegNum
 IR::Opnd *
 Lowerer::LoadVTableValueOpnd(IR::Instr * instr, VTableValue vtableType)
 {
-    return IR::AddrOpnd::New((Js::Var)instr->m_func->GetScriptContext()->GetLibrary()->GetVTableAddresses()[vtableType], IR::AddrOpndKindDynamicVtable, this->m_func);
+    return IR::AddrOpnd::New((Js::Var)instr->m_func->GetScriptContextInfo()->GetVTableAddress(vtableType), IR::AddrOpndKindDynamicVtable, this->m_func);
 }
 
 IR::Opnd *
@@ -4364,7 +4364,7 @@ Lowerer::LowerNewScObject(IR::Instr *newObjInstr, bool callCtor, bool hasArgs, b
         if (newObjInstr->IsJitProfilingInstr())
         {
             Assert(m_func->IsSimpleJit());
-            Assert(!Js::FunctionBody::IsNewSimpleJit());
+            Assert(!CONFIG_FLAG(NewSimpleJit));
 
             // This path skipped calling the Ctor, which skips calling LowerCallI with newObjInstr, meaning that the call will not be profiled.
             //   So we insert it manually here.
@@ -4499,7 +4499,7 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
     AssertMsg(!PHASE_OFF(Js::ObjTypeSpecNewObjPhase, this->m_func) || !newObjInstr->HasBailOutInfo(),
         "Why do we have bailout on NewScObject when ObjTypeSpecNewObj is off?");
 
-    if (PHASE_OFF(Js::FixedNewObjPhase, newObjInstr->m_func->GetJnFunction()) && PHASE_OFF(Js::ObjTypeSpecNewObjPhase, this->m_func))
+    if (PHASE_OFF(Js::FixedNewObjPhase, newObjInstr->m_func) && PHASE_OFF(Js::ObjTypeSpecNewObjPhase, this->m_func))
     {
         return false;
     }
@@ -4533,12 +4533,11 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
 
         if (ctorCache == nullptr)
         {
-            if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func->GetJnFunction()) || PHASE_TESTTRACE(Js::FixedNewObjPhase, newObjInstr->m_func->GetJnFunction()))
+            if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func) || PHASE_TESTTRACE(Js::FixedNewObjPhase, newObjInstr->m_func))
             {
-                Js::FunctionBody* callerFunctionBody = newObjInstr->m_func->GetJnFunction();
                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                 Output::Print(L"FixedNewObj: function %s (%s): lowering non-fixed new script object for %s, because %s.\n",
-                    callerFunctionBody->GetDisplayName(), callerFunctionBody->GetDebugNumberSet(debugStringBuffer), Js::OpCodeUtil::GetOpCodeName(newObjInstr->m_opcode),
+                    newObjInstr->m_func->GetWorkItem()->GetDisplayName(), newObjInstr->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer), Js::OpCodeUtil::GetOpCodeName(newObjInstr->m_opcode),
                     newObjInstr->IsProfiledInstr() ? L"constructor cache hasn't been cloned" : L"instruction is not profiled");
                 Output::Flush();
             }
@@ -4556,9 +4555,8 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
     // object and call a specialized helper (or even constructor, directly) avoiding the checks in generic NewScObjectCommon.
     if (ctorCache->skipNewScObject)
     {
-        if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func->GetJnFunction()) || PHASE_TESTTRACE(Js::FixedNewObjPhase, newObjInstr->m_func->GetJnFunction()))
+        if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func) || PHASE_TESTTRACE(Js::FixedNewObjPhase, newObjInstr->m_func))
         {
-            Js::FunctionBody* callerFunctionBody = newObjInstr->m_func->GetJnFunction();
             const Js::JavascriptFunction* ctor = ctorCache->constructor;
             Js::FunctionBody* ctorBody = ctor->GetFunctionInfo()->HasBody() ? ctor->GetFunctionInfo()->GetFunctionBody() : nullptr;
             const wchar_t* ctorName = ctorBody != nullptr ? ctorBody->GetDisplayName() : L"<unknown>";
@@ -4567,7 +4565,7 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
             wchar_t debugStringBuffer2[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
 
             Output::Print(L"FixedNewObj: function %s (%s): lowering skipped new script object for %s with %s ctor <unknown> (%s %s).\n",
-                callerFunctionBody->GetDisplayName(), callerFunctionBody->GetDebugNumberSet(debugStringBuffer2), Js::OpCodeUtil::GetOpCodeName(newObjInstr->m_opcode),
+                newObjInstr->m_func->GetWorkItem()->GetDisplayName(), newObjInstr->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer2), Js::OpCodeUtil::GetOpCodeName(newObjInstr->m_opcode),
                 newObjInstr->m_opcode == Js::OpCode::NewScObjectNoCtor ? L"inlined" : L"called",
                 ctorName, ctorBody ? ctorBody->GetDebugNumberSet(debugStringBuffer) : L"(null)");
             Output::Flush();
@@ -4586,9 +4584,8 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
 
     AssertMsg(ctorCache->type != nullptr, "Why did we hard-code a mismatched, invalidated or polymorphic constructor cache?");
 
-    if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func->GetJnFunction()) || PHASE_TESTTRACE(Js::FixedNewObjPhase, newObjInstr->m_func->GetJnFunction()))
+    if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func) || PHASE_TESTTRACE(Js::FixedNewObjPhase, newObjInstr->m_func))
     {
-        Js::FunctionBody* callerFunctionBody = newObjInstr->m_func->GetJnFunction();
         const Js::JavascriptFunction* constructor = ctorCache->constructor;
         Js::FunctionBody* constructorBody = constructor->GetFunctionInfo()->HasBody() ? constructor->GetFunctionInfo()->GetFunctionBody() : nullptr;
         const wchar_t* constructorName = constructorBody != nullptr ? constructorBody->GetDisplayName() : L"<unknown>";
@@ -4596,10 +4593,10 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
         wchar_t debugStringBuffer2[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
 
-        if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func->GetJnFunction()))
+        if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func))
         {
             Output::Print(L"FixedNewObj: function %s (%s): lowering fixed new script object for %s with %s ctor <unknown> (%s %s): type = %p, slots = %d, inlined slots = %d.\n",
-                callerFunctionBody->GetDisplayName(), callerFunctionBody->GetDebugNumberSet(debugStringBuffer2), Js::OpCodeUtil::GetOpCodeName(newObjInstr->m_opcode),
+                newObjInstr->m_func->GetWorkItem()->GetDisplayName(), newObjInstr->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer2), Js::OpCodeUtil::GetOpCodeName(newObjInstr->m_opcode),
                 newObjInstr->m_opcode == Js::OpCode::NewScObjectNoCtor ? L"inlined" : L"called",
                 constructorName, constructorBody ? constructorBody->GetDebugNumberSet(debugStringBuffer) : L"(null)",
                 ctorCache->type, ctorCache->slotCount, ctorCache->inlineSlotCount);
@@ -4607,7 +4604,7 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
         else
         {
             Output::Print(L"FixedNewObj: function %s (%s): lowering fixed new script object for %s with %s ctor <unknown> (%s %s): slots = %d, inlined slots = %d.\n",
-                callerFunctionBody->GetDisplayName(), callerFunctionBody->GetDebugNumberSet(debugStringBuffer2), Js::OpCodeUtil::GetOpCodeName(newObjInstr->m_opcode),
+                newObjInstr->m_func->GetWorkItem()->GetDisplayName(), newObjInstr->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer2), Js::OpCodeUtil::GetOpCodeName(newObjInstr->m_opcode),
                 newObjInstr->m_opcode == Js::OpCode::NewScObjectNoCtor ? L"inlined" : L"called",
                 constructorName, debugStringBuffer, ctorCache->slotCount, ctorCache->inlineSlotCount);
         }
@@ -4669,7 +4666,7 @@ Lowerer::GenerateRecyclerAllocAligned(IR::JnHelperMethod allocHelper, size_t all
 {
     IR::LabelInstr * allocDoneLabel = nullptr;
 
-    if (!PHASE_OFF(Js::JitAllocNewObjPhase, insertionPointInstr->m_func->GetJnFunction()) && HeapInfo::IsSmallObject(allocSize))
+    if (!PHASE_OFF(Js::JitAllocNewObjPhase, insertionPointInstr->m_func) && HeapInfo::IsSmallObject(allocSize))
     {
         IR::LabelInstr * allocHelperLabel = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, true);
         allocDoneLabel = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, inOpHelper);
@@ -5716,8 +5713,8 @@ Lowerer::GenerateCheckFixedFld(IR::Instr * instrChkFld)
     IR::LabelInstr *labelBailOut = nullptr;
     IR::LabelInstr *labelDone = nullptr;
 
-    AssertMsg(!PHASE_OFF(Js::FixedMethodsPhase, instrChkFld->m_func->GetJnFunction()) ||
-        !PHASE_OFF(Js::UseFixedDataPropsPhase, instrChkFld->m_func->GetJnFunction()), "Lowering a check fixed field with fixed data/method phase disabled?");
+    AssertMsg(!PHASE_OFF(Js::FixedMethodsPhase, instrChkFld->m_func) ||
+        !PHASE_OFF(Js::UseFixedDataPropsPhase, instrChkFld->m_func), "Lowering a check fixed field with fixed data/method phase disabled?");
 
     Assert(instrChkFld->GetSrc1()->IsSymOpnd() && instrChkFld->GetSrc1()->AsSymOpnd()->IsPropertySymOpnd());
     IR::PropertySymOpnd *propertySymOpnd = instrChkFld->GetSrc1()->AsPropertySymOpnd();
@@ -5911,7 +5908,7 @@ Lowerer::GenerateNonConfigurableLdRootFld(IR::Instr * instrLdFld)
         return false;
     }
 
-    Assert(!PHASE_OFF(Js::RootObjectFldFastPathPhase, this->m_func->GetJnFunction()));
+    Assert(!PHASE_OFF(Js::RootObjectFldFastPathPhase, this->m_func));
     Assert(!instrLdFld->HasBailOutInfo());
     IR::Opnd * srcOpnd;
     Js::RootObjectBase * rootObject = this->m_func->GetJnFunction()->GetRootObject();
@@ -6873,7 +6870,7 @@ Lowerer::PinTypeRef(Js::Type* type, void* typeRef, IR::Instr* instr, Js::Propert
     {
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
         Output::Print(L"PinnedTypes: function %s(%s) instr %s property %s(#%u) pinned %s reference 0x%p to type 0x%p.\n",
-            this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+            this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
             Js::OpCodeUtil::GetOpCodeName(instr->m_opcode), GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer(), propertyId,
             typeRef == type ? L"strong" : L"weak", typeRef, type);
         Output::Flush();
@@ -6974,7 +6971,7 @@ Lowerer::CreateTypePropertyGuardForGuardedProperties(Js::Type* type, IR::Propert
                     wchar_t workItemName[256];
                     this->m_func->m_workItem->GetDisplayName(workItemName, _countof(workItemName));
                     Output::Print(L"ObjTypeSpec: function %s(%s) registered guard 0x%p with value 0x%p for property %s (%u).\n",
-                        workItemName, this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                        workItemName, this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                         guard, guard->GetValue(), this->GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer(), propertyId);
                     Output::Flush();
                 }
@@ -7006,7 +7003,7 @@ Lowerer::CreateEquivalentTypeGuardAndLinkToGuardedProperties(Js::Type* type, IR:
             {
                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                 Output::Print(L"ObjTypeSpec: function %s(%s) registered equivalent type spec guard 0x%p with value 0x%p for property %s (%u).\n",
-                    this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                    this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                     guard, guard->GetValue(), GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer(), propertyId);
                 Output::Flush();
             }
@@ -7087,7 +7084,7 @@ Lowerer::CreateEquivalentTypeGuardAndLinkToGuardedProperties(Js::Type* type, IR:
                     Js::FunctionBody* topFunctionBody = this->m_func->GetJnFunction();
                     Js::ScriptContext* scriptContext = topFunctionBody->GetScriptContext();
                     Output::Print(L"EquivObjTypeSpec: top function %s (%s): duplicate property clash on %s(#%d) \n",
-                        topFunctionBody->GetDisplayName(), topFunctionBody->GetDebugNumberSet(debugStringBuffer), propertyId, scriptContext->GetPropertyNameLocked(propertyId)->GetBuffer());
+                        m_func->GetWorkItem()->GetDisplayName(), m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer), propertyId, scriptContext->GetPropertyNameLocked(propertyId)->GetBuffer());
                     Output::Flush();
                 }
                 Assert(propIdCount < propOpCount);
@@ -7142,7 +7139,7 @@ Lowerer::LinkCtorCacheToGuardedProperties(Js::JitTimeConstructorCache* ctorCache
             {
                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                 Output::Print(L"ObjTypeSpec: function %s(%s) registered ctor cache 0x%p with value 0x%p for property %s (%u).\n",
-                    this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                    this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                     ctorCache->runtimeCache, ctorCache->type, GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer(), propertyId);
                 Output::Flush();
             }
@@ -7199,7 +7196,7 @@ Lowerer::LinkGuardToGuardedProperties(Js::EntryPointInfo* entryPointInfo, const
                     {
                         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                         Output::Print(L"ObjTypeStore: function %s(%s): no shared property guard for property % (%u).\n",
-                            this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                            this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                             GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer(), propertyId);
                         Output::Flush();
                     }
@@ -10237,8 +10234,7 @@ bool Lowerer::IsNullOrUndefRegOpnd(IR::RegOpnd *opnd) const
         return false;
     }
     Js::Var var = sym->GetConstAddress();
-    Js::TypeId typeId = Js::RecyclableObject::FromVar(var)->GetTypeId();
-    return typeId == Js::TypeIds_Null || typeId == Js::TypeIds_Undefined;
+    return (intptr_t)var == m_func->GetScriptContextInfo()->GetNullAddr() || (intptr_t)var == m_func->GetScriptContextInfo()->GetUndefinedAddr();
 }
 
 bool Lowerer::IsConstRegOpnd(IR::RegOpnd *opnd) const
@@ -15068,7 +15064,7 @@ Lowerer::GenerateFastLdElemI(IR::Instr *& ldElem, bool *instrIsInHelperBlockRef)
                     wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                     Output::Print(L"Typed Array Lowering: function: %s (%s): instr %s, not specialized by glob opt due to negative or not likely int index.\n",
                         this->m_func->GetWorkItem()->GetDisplayName(),
-                        this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                        this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                         Js::OpCodeUtil::GetOpCodeName(ldElem->m_opcode));
                     Output::Flush();
                 }
@@ -15248,7 +15244,7 @@ Lowerer::GenerateFastLdElemI(IR::Instr *& ldElem, bool *instrIsInHelperBlockRef)
                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                 Output::Print(L"Typed Array Lowering: function: %s (%s), instr: %s, base value type: %S, %s.",
                     this->m_func->GetWorkItem()->GetDisplayName(),
-                    this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                    this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                     Js::OpCodeUtil::GetOpCodeName(ldElem->m_opcode),
                     baseValueTypeStr,
                     (!dst->IsVar() ? L"specialized" : L"not specialized"));
@@ -15531,7 +15527,7 @@ Lowerer::GenerateFastStElemI(IR::Instr *& stElem, bool *instrIsInHelperBlockRef)
                 wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
                 Output::Print(L"Typed Array Lowering: function: %s (%s): instr %s, not specialized by glob opt due to negative or not likely int index.\n",
                     this->m_func->GetWorkItem()->GetDisplayName(),
-                    this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                    this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                     Js::OpCodeUtil::GetOpCodeName(stElem->m_opcode));
                 Output::Flush();
             }
@@ -15567,7 +15563,7 @@ Lowerer::GenerateFastStElemI(IR::Instr *& stElem, bool *instrIsInHelperBlockRef)
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
             Output::Print(L"Typed Array Lowering: function: %s (%s), instr: %s, base value type: %S, %s.",
                 this->m_func->GetWorkItem()->GetDisplayName(),
-                this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                 Js::OpCodeUtil::GetOpCodeName(stElem->m_opcode),
                 baseValueTypeStr,
                 (!src->IsVar() ? L"specialized" : L"not specialized"));
@@ -18731,7 +18727,7 @@ Lowerer::GenerateFastStFld(IR::Instr * const instrStFld, IR::JnHelperMethod help
                 #endif
                 PHASE_PRINT_TRACE(Js::AddFldFastPathPhase, this->m_func,
                     L"AddFldFastPath: function: %s(%s) property: %s(#%d) no fast path, because the phase is off.\n",
-                    this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                    this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                     this->m_func->GetScriptContext()->GetPropertyNameLocked(propertySym->m_propertyId)->GetBuffer(), propertySym->m_propertyId);
             }
 
@@ -18772,7 +18768,7 @@ Lowerer::GenerateFastStFld(IR::Instr * const instrStFld, IR::JnHelperMethod help
 #endif
         PHASE_PRINT_TRACE(Js::AddFldFastPathPhase, this->m_func,
             L"AddFldFastPath: function: %s(%s) property: %s(#%d) %s fast path for %s.\n",
-            this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+            this->m_func->GetWorkItem()->GetDisplayName(), this->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
             this->m_func->GetScriptContext()->GetPropertyNameLocked(propertySym->m_propertyId)->GetBuffer(), propertySym->m_propertyId,
             usePolymorphicInlineCache ? L"poly" : L"mono", doStore ? L"store and add" : L"add only");
     }
@@ -20818,11 +20814,10 @@ void Lowerer::LowerFunctionEntry(IR::Instr* funcEntry)
 
     if (m_func->DoSimpleJitDynamicProfile())
     {
-        const auto jn = m_func->GetJnFunction();
         // Only generate the argument profiling if the function expects to have some arguments to profile and only if
         //    it has implicit ArgIns (the latter is a restriction imposed by the Interpreter, so it is mirrored in SimpleJit)
 
-        if (jn->GetInParamsCount() > 1 && m_func->GetJITFunctionBody()->HasImplicitArgIns())
+        if (m_func->GetJITFunctionBody()->GetInParamsCount() > 1 && m_func->GetJITFunctionBody()->HasImplicitArgIns())
         {
             // Call out to the argument profiling helper
             IR::Instr* callInstr = IR::Instr::New(Js::OpCode::Call, m_func);
@@ -20845,7 +20840,7 @@ void Lowerer::LowerFunctionBodyCallCountChange(IR::Instr *const insertBeforeInst
     Func *const func = insertBeforeInstr->m_func;
     const bool isSimpleJit = func->IsSimpleJit();
 
-    if ((isSimpleJit && !func->GetTopFunc()->GetJnFunction()->DoFullJit()))
+    if ((isSimpleJit && PHASE_OFF(Js::FullJitPhase, m_func)))
     {
         return;
     }

+ 2 - 2
lib/Backend/LowerMDShared.cpp

@@ -3970,11 +3970,11 @@ LowererMD::GenerateFlagInlineCacheCheckForGetterSetter(
     IR::LabelInstr * labelNext)
 {
     uint accessorFlagMask;
-    if (PHASE_OFF(Js::InlineGettersPhase, insertBeforeInstr->m_func->GetJnFunction()))
+    if (PHASE_OFF(Js::InlineGettersPhase, insertBeforeInstr->m_func))
     {
         accessorFlagMask = Js::InlineCache::GetSetterFlagMask();
     }
-    else if (PHASE_OFF(Js::InlineSettersPhase, insertBeforeInstr->m_func->GetJnFunction()))
+    else if (PHASE_OFF(Js::InlineSettersPhase, insertBeforeInstr->m_func))
     {
         accessorFlagMask = Js::InlineCache::GetGetterFlagMask();
     }

+ 6 - 2
lib/Backend/NativeCodeGenerator.cpp

@@ -1022,6 +1022,10 @@ NativeCodeGenerator::CodeGen(PageAllocator * pageAllocator, CodeGenWorkItem* wor
             workItem->SetCodeAddress(jitWriteData.codeAddress);
 
             workItem->GetEntryPoint()->SetCodeGenRecorded((PVOID)jitWriteData.codeAddress, jitWriteData.codeSize, nullptr, nullptr, nullptr);
+            if (jitWriteData.hasBailoutInstr != FALSE)
+            {
+                body->SetHasBailoutInstrInJittedCode(true);
+            }
 
             {
                 if (IS_JS_ETW(EventEnabledJSCRIPT_FUNCTION_JIT_STOP()))
@@ -1684,11 +1688,11 @@ NativeCodeGenerator::IsInDebugMode() const
 ExecutionMode NativeCodeGenerator::PrejitJitMode(Js::FunctionBody *const functionBody)
 {
     Assert(IS_PREJIT_ON());
-    Assert(functionBody->DoSimpleJit() || functionBody->DoFullJit());
+    Assert(functionBody->DoSimpleJit() || !PHASE_OFF(Js::FullJitPhase, functionBody));
 
     // Prefer full JIT for prejitting unless it's off or simple JIT is forced
     return
-        functionBody->DoFullJit() && !(PHASE_FORCE(Js::Phase::SimpleJitPhase, functionBody) && functionBody->DoSimpleJit())
+        !PHASE_OFF(Js::FullJitPhase, functionBody) && !(PHASE_FORCE(Js::Phase::SimpleJitPhase, functionBody) && functionBody->DoSimpleJit())
             ? ExecutionMode::FullJit
             : ExecutionMode::SimpleJit;
 }

+ 2 - 1
lib/Backend/Opnd.cpp

@@ -3283,7 +3283,8 @@ Opnd::GetAddrDescription(__out_ecount(count) wchar_t *const description, const s
 
         case IR::AddrOpndKindDynamicFunctionBody:
             DumpAddress(address, printToConsole, skipMaskedAddress);
-            DumpFunctionInfo(&buffer, &n, (Js::FunctionInfo *)address, printToConsole);
+            // TODO: OOP JIT, allow this when in proc
+            //DumpFunctionInfo(&buffer, &n, (Js::FunctionInfo *)address, printToConsole);
             break;
 
         case IR::AddrOpndKindDynamicFunctionBodyWeakRef:

+ 1 - 1
lib/Backend/SccLiveness.cpp

@@ -470,7 +470,7 @@ SCCLiveness::ProcessStackSymUse(StackSym * stackSym, IR::Instr * instr, int usag
     {
 #if DBG
         wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
-        Output::Print(L"Function: %s (%s)       ", this->func->GetWorkItem()->GetDisplayName(), this->func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer));
+        Output::Print(L"Function: %s (%s)       ", this->func->GetWorkItem()->GetDisplayName(), this->func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer));
         Output::Print(L"Reg: ");
         stackSym->Dump();
         Output::Print(L"\n");

+ 61 - 0
lib/Backend/ScriptContextInfo.cpp

@@ -40,8 +40,69 @@ ScriptContextInfo::GetUndeclBlockVarAddr() const
     return m_contextData.undeclBlockVarAddr;
 }
 
+intptr_t
+ScriptContextInfo::GetEmptyStringAddr() const
+{
+    return m_contextData.emptyStringAddr;
+}
+
+intptr_t
+ScriptContextInfo::GetNegativeZeroAddr() const
+{
+    return m_contextData.negativeZeroAddr;
+}
+
+intptr_t
+ScriptContextInfo::GetNumberTypeStaticAddr() const
+{
+    return m_contextData.numberTypeStaticAddr;
+}
+
+intptr_t
+ScriptContextInfo::GetStringTypeStaticAddr() const
+{
+    return m_contextData.stringTypeStaticAddr;
+}
+
+intptr_t
+ScriptContextInfo::GetObjectTypeAddr() const
+{
+    return m_contextData.objectTypeAddr;
+}
+
+intptr_t
+ScriptContextInfo::GetObjectHeaderInlinedTypeAddr() const
+{
+    return m_contextData.objectHeaderInlinedTypeAddr;
+}
+
+intptr_t
+ScriptContextInfo::GetRegexTypeAddr() const
+{
+    return m_contextData.regexTypeAddr;
+}
+
+intptr_t
+ScriptContextInfo::GetArrayConstructorAddr() const
+{
+    return m_contextData.arrayConstructorAddr;
+}
+
+intptr_t
+ScriptContextInfo::GetCharStringCacheAddr() const
+{
+    return m_contextData.charStringCacheAddr;
+}
+
 intptr_t
 ScriptContextInfo::GetAddr() const
 {
     return m_contextData.scriptContextAddr;
 }
+
+intptr_t
+ScriptContextInfo::GetVTableAddress(VTableValue vtableType) const
+{
+    Assert(vtableType < VTableValue::Count);
+    return m_contextData.vtableAddresses[vtableType];
+}

+ 11 - 0
lib/Backend/ScriptContextInfo.h

@@ -14,8 +14,19 @@ public:
     intptr_t GetTrueAddr() const;
     intptr_t GetFalseAddr() const;
     intptr_t GetUndeclBlockVarAddr() const;
+    intptr_t GetEmptyStringAddr() const;
+    intptr_t GetNegativeZeroAddr() const;
+    intptr_t GetNumberTypeStaticAddr() const;
+    intptr_t GetStringTypeStaticAddr() const;
+    intptr_t GetObjectTypeAddr() const;
+    intptr_t GetObjectHeaderInlinedTypeAddr() const;
+    intptr_t GetRegexTypeAddr() const;
+    intptr_t GetArrayConstructorAddr() const;
+    intptr_t GetCharStringCacheAddr() const;
     intptr_t GetAddr() const;
 
+    intptr_t GetVTableAddress(VTableValue vtableType) const;
+
 
 private:
     ScriptContextData m_contextData;

+ 3 - 3
lib/Backend/SwitchIRBuilder.cpp

@@ -207,7 +207,7 @@ SwitchIRBuilder::SetProfiledInstruction(IR::Instr * instr, Js::ProfileId profile
             wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
 #endif
             PHASE_PRINT_TESTTRACE1(Js::SwitchOptPhase, L"Func %s, Switch %d: Expression Type : %S\n",
-                m_profiledSwitchInstr->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+                m_profiledSwitchInstr->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
                 m_profiledSwitchInstr->AsProfiledInstr()->u.profileId, valueTypeStr);
         }
     }
@@ -728,7 +728,7 @@ SwitchIRBuilder::BuildBailOnNotInteger()
     wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
 #endif
     PHASE_PRINT_TESTTRACE1(Js::SwitchOptPhase, L"Func %s, Switch %d:Optimized for Integers\n",
-        m_profiledSwitchInstr->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+        m_profiledSwitchInstr->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
         m_profiledSwitchInstr->AsProfiledInstr()->u.profileId);
 }
 
@@ -755,7 +755,7 @@ SwitchIRBuilder::BuildBailOnNotString()
     wchar_t debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
 #endif
     PHASE_PRINT_TESTTRACE1(Js::SwitchOptPhase, L"Func %s, Switch %d:Optimized for Strings\n",
-        m_profiledSwitchInstr->m_func->GetJnFunction()->GetDebugNumberSet(debugStringBuffer),
+        m_profiledSwitchInstr->m_func->GetJITFunctionBody()->GetDebugNumberSet(debugStringBuffer),
         m_profiledSwitchInstr->AsProfiledInstr()->u.profileId);
 }
 

+ 2 - 2
lib/Backend/Sym.cpp

@@ -1009,9 +1009,9 @@ Sym::Dump(IRDumpFlags flags, const ValueType valueType)
                     Js::FunctionBody* functionBody = sym->GetByteCodeFunc()->GetJnFunction();
                     if(functionBody->GetPropertyIdOnRegSlotsContainer())
                     {
-                        if(functionBody->IsNonTempLocalVar(sym->GetByteCodeRegSlot()))
+                        if(sym->GetByteCodeFunc()->IsNonTempLocalVar(sym->GetByteCodeRegSlot()))
                         {
-                            uint index = sym->GetByteCodeRegSlot() - functionBody->GetConstantCount();
+                            uint index = sym->GetByteCodeRegSlot() - sym->GetByteCodeFunc()->GetJITFunctionBody()->GetConstCount();
                             Js::PropertyId propertyId = functionBody->GetPropertyIdOnRegSlotsContainer()->propertyIdsForRegSlots[index];
                             Output::Print(L"(%s)", functionBody->GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer());
                         }

+ 1 - 1
lib/Backend/TempTracker.cpp

@@ -1094,7 +1094,7 @@ ObjectTemp::CanStoreTemp(IR::Instr * instr)
 #endif
         if (opcode == Js::OpCode::NewScObjectNoCtor)
         {
-            if (PHASE_OFF(Js::FixedNewObjPhase, instr->m_func->GetJnFunction()) && PHASE_OFF(Js::ObjTypeSpecNewObjPhase, instr->m_func->GetTopFunc()))
+            if (PHASE_OFF(Js::FixedNewObjPhase, instr->m_func) && PHASE_OFF(Js::ObjTypeSpecNewObjPhase, instr->m_func->GetTopFunc()))
             {
                 return false;
             }

+ 6 - 0
lib/Backend/ThreadContextInfo.cpp

@@ -217,6 +217,12 @@ ThreadContextInfo::GetRuntimeCRTBaseAddress() const
     return static_cast<intptr_t>(m_threadContextData.crtBaseAddress);
 }
 
+intptr_t
+ThreadContextInfo::GetBailOutRegisterSaveSpace() const
+{
+    return static_cast<intptr_t>(m_threadContextData.bailOutRegisterSaveSpace);
+}
+
 ptrdiff_t
 ThreadContextInfo::GetChakraBaseAddressDifference() const
 {

+ 3 - 0
lib/Backend/ThreadContextInfo.h

@@ -36,7 +36,10 @@ public:
     intptr_t GetConstructorCacheDefaultInstanceAddr() const;
     intptr_t GetJavascriptObjectNewInstanceAddr() const;
     intptr_t GetNativeFloatArrayMissingItemAddr() const;
+    intptr_t GetBailOutRegisterSaveSpace() const;
+
     size_t GetScriptStackLimit() const;
+
     bool IsThreadBound() const;
 
     PageAllocator * GetPageAllocator();

+ 1 - 1
lib/Backend/amd64/EncoderMD.cpp

@@ -1274,7 +1274,7 @@ EncoderMD::Encode(IR::Instr *instr, BYTE *pc, BYTE* beginCodeAddress)
             Js::ArrayAccessDecoder::InstructionData instrData;
             BYTE *tempPc = instrStart;
 
-            instrData = Js::ArrayAccessDecoder::CheckValidInstr(tempPc, &exceptionInfo, instr->m_func->GetJnFunction());
+            instrData = Js::ArrayAccessDecoder::CheckValidInstr(tempPc, &exceptionInfo);
 
             // Make sure we can decode the instr
             Assert(!instrData.isInvalidInstr);

+ 1 - 1
lib/Backend/amd64/LowererMDArch.cpp

@@ -743,7 +743,7 @@ LowererMDArch::LowerCallI(IR::Instr * callInstr, ushort callFlags, bool isHelper
     if (callInstr->IsJitProfilingInstr())
     {
         Assert(callInstr->m_func->IsSimpleJit());
-        Assert(!Js::FunctionBody::IsNewSimpleJit());
+        Assert(!CONFIG_FLAG(NewSimpleJit));
 
         if(finalDst &&
             finalDst->IsRegOpnd() &&

+ 1 - 1
lib/Backend/arm/LinearScanMD.cpp

@@ -218,7 +218,7 @@ LinearScanMD::GenerateBailOut(
     Func *const func = instr->m_func;
     BailOutInfo *const bailOutInfo = instr->GetBailOutInfo();
     IR::Instr *firstInstr = instr->m_prev;
-    Js::Var *const registerSaveSpace = func->GetScriptContext()->GetThreadContext()->GetBailOutRegisterSaveSpace();
+    Js::Var *const registerSaveSpace = (Js::Var*)func->GetThreadContextInfo()->GetBailOutRegisterSaveSpace();
 
     const auto LoadRegSaveSpaceIntoScratch = [&](const RegNum reg)
     {

+ 3 - 3
lib/Backend/arm/LowerMD.cpp

@@ -673,7 +673,7 @@ LowererMD::LowerCallI(IR::Instr * callInstr, ushort callFlags, bool isHelper, IR
     if (callInstr->IsJitProfilingInstr())
     {
         Assert(callInstr->m_func->IsSimpleJit());
-        Assert(!Js::FunctionBody::IsNewSimpleJit());
+        Assert(!CONFIG_FLAG(NewSimpleJit));
 
         if(finalDst &&
             finalDst->IsRegOpnd() &&
@@ -4649,11 +4649,11 @@ LowererMD::GenerateFlagInlineCacheCheckForGetterSetter(
     IR::LabelInstr * labelNext)
 {
     uint accessorFlagMask;
-    if (PHASE_OFF(Js::InlineGettersPhase, insertBeforeInstr->m_func->GetJnFunction()))
+    if (PHASE_OFF(Js::InlineGettersPhase, insertBeforeInstr->m_func))
     {
         accessorFlagMask = Js::InlineCache::GetSetterFlagMask();
     }
-    else if (PHASE_OFF(Js::InlineSettersPhase, insertBeforeInstr->m_func->GetJnFunction()))
+    else if (PHASE_OFF(Js::InlineSettersPhase, insertBeforeInstr->m_func))
     {
         accessorFlagMask = Js::InlineCache::GetGetterFlagMask();
     }

+ 1 - 1
lib/Backend/i386/LowererMDArch.cpp

@@ -730,7 +730,7 @@ LowererMDArch::LowerCallI(IR::Instr *callInstr, ushort callFlags, bool isHelper,
     if (callInstr->IsJitProfilingInstr())
     {
         Assert(callInstr->m_func->IsSimpleJit());
-        Assert(!Js::FunctionBody::IsNewSimpleJit());
+        Assert(!CONFIG_FLAG(NewSimpleJit));
 
         if(finalDst &&
             finalDst->IsRegOpnd() &&

+ 21 - 1
lib/JITIDL/ChakraJIT.idl

@@ -5,6 +5,9 @@
 
 import "wtypes.idl";
 
+// TODO: OOP JIT, how do we make this better?
+#define VTABLE_COUNT 39
+
 typedef struct CallSiteData
 {
     unsigned short bitFields;
@@ -95,17 +98,29 @@ typedef struct ThreadContextData
     __int3264 crtBaseAddress;
     __int3264 threadStackLimitAddr;
     __int3264 scriptStackLimit;
+    __int3264 bailOutRegisterSaveSpace;
     boolean isThreadBound;
 } ThreadContextData;
 
 typedef struct ScriptContextData
 {
+    __int3264 vtableAddresses[VTABLE_COUNT];
+
     __int3264 nullAddr;
     __int3264 undefinedAddr;
     __int3264 trueAddr;
     __int3264 falseAddr;
     __int3264 undeclBlockVarAddr;
     __int3264 scriptContextAddr;
+    __int3264 emptyStringAddr;
+    __int3264 negativeZeroAddr;
+    __int3264 numberTypeStaticAddr;
+    __int3264 stringTypeStaticAddr;
+    __int3264 objectTypeAddr;
+    __int3264 objectHeaderInlinedTypeAddr;
+    __int3264 regexTypeAddr;
+    __int3264 arrayConstructorAddr;
+    __int3264 charStringCacheAddr;
 } ScriptContextData;
 
 typedef struct SmallSpanSequenceData
@@ -132,6 +147,9 @@ typedef struct FunctionBodyJITData
     [size_is(inlineCacheCount)] __int3264 * inlineCaches;
 
     SmallSpanSequenceData statementMap;
+
+    __int3264 functionBodyAddr;
+
     unsigned int funcNumber;
     unsigned int localFuncId;
     unsigned int sourceContextId;
@@ -168,7 +186,8 @@ typedef struct FunctionBodyJITData
     boolean hasCachedScopePropIds;
     boolean inlineCachesOnFunctionObject;
     boolean doInterruptProbe;
-
+    boolean isGlobalFunc;
+    boolean doJITLoopBody;
 } FunctionBodyJITData;
 
 // EntryPointInfo fields, read/write in JIT
@@ -209,6 +228,7 @@ typedef struct JITOutputData
     unsigned short pdataCount;
     unsigned short xdataSize;
     boolean isInPrereservedRegion;
+    boolean hasBailoutInstr;
 } JITOutputData;
 
 [

+ 1 - 1
lib/Runtime/Base/Debug.h

@@ -43,7 +43,7 @@ WCHAR* DumpCallStack(uint frameCount = -1);
         Func->m_workItem->GetDisplayName(workItem, _countof(workItem)); \
         WCHAR prefixValue[512]; \
         swprintf_s(prefixValue, L"%s (#%d.%u, #%u)", workItem, \
-           (int)(Func)->GetJnFunction()->GetSourceContextId(), (Func)->GetJnFunction()->GetLocalFunctionId(), (Func)->GetJnFunction()->GetFunctionNumber()); \
+           (int)(Func)->GetJITFunctionBody()->GetSourceContextId(), (Func)->GetJITFunctionBody()->GetLocalFunctionId(), (Func)->GetJITFunctionBody()->GetFunctionNumber()); \
         Output::TraceWithPrefix((Phase), prefixValue, __VA_ARGS__); \
       }
 #define OUTPUT_VERBOSE_TRACE2(Phase, FunctionBody, ...) \

+ 15 - 20
lib/Runtime/Base/FunctionBody.cpp

@@ -6228,7 +6228,7 @@ namespace Js
                 break;
 
             case ExecutionMode::FullJit:
-                Assert(DoFullJit());
+                Assert(!PHASE_OFF(FullJitPhase, this));
                 break;
 
             default:
@@ -6277,7 +6277,7 @@ namespace Js
                 return GetExecutionMode();
 
             case ExecutionMode::SimpleJit:
-                if(IsNewSimpleJit())
+                if(CONFIG_FLAG(NewSimpleJit))
                 {
                     return GetDefaultInterpreterExecutionMode();
                 }
@@ -6412,7 +6412,7 @@ namespace Js
             }
 
             TransitionToFullJit:
-                if(DoFullJit())
+                if(!PHASE_OFF(FullJitPhase, this))
                 {
                     SetExecutionMode(ExecutionMode::FullJit);
                     return true;
@@ -6571,7 +6571,7 @@ namespace Js
             scale += autoProfilingInterpreter0Limit + autoProfilingInterpreter1Limit;
             autoProfilingInterpreter0Limit = 0;
             autoProfilingInterpreter1Limit = 0;
-            if(!IsNewSimpleJit())
+            if(!CONFIG_FLAG(NewSimpleJit))
             {
                 simpleJitLimit += profilingInterpreter0Limit;
                 profilingInterpreter0Limit = 0;
@@ -6579,7 +6579,7 @@ namespace Js
         }
         if(!DoSimpleJit())
         {
-            if(!IsNewSimpleJit() && doInterpreterProfile)
+            if(!CONFIG_FLAG(NewSimpleJit) && doInterpreterProfile)
             {
                 // The old simple JIT is off, but since it does profiling, it will be replaced with the profiling interpreter
                 profilingInterpreter1Limit += simpleJitLimit;
@@ -6590,7 +6590,7 @@ namespace Js
             }
             simpleJitLimit = 0;
         }
-        if(!DoFullJit())
+        if(PHASE_OFF(FullJitPhase, this))
         {
             scale += profilingInterpreter1Limit;
             profilingInterpreter1Limit = 0;
@@ -6705,7 +6705,7 @@ namespace Js
         const bool doSimpleJit = DoSimpleJit();
         const bool doInterpreterProfile = DoInterpreterProfile();
         const bool fullyScaled =
-            IsNewSimpleJit() && doSimpleJit && ScaleLimit(simpleJitLimit) ||
+            CONFIG_FLAG(NewSimpleJit) && doSimpleJit && ScaleLimit(simpleJitLimit) ||
             (
                 doInterpreterProfile
                     ?   DoInterpreterAutoProfile() &&
@@ -6713,7 +6713,7 @@ namespace Js
                     :   ScaleLimit(interpreterLimit)
             ) ||
             (
-                IsNewSimpleJit()
+                CONFIG_FLAG(NewSimpleJit)
                     ?   doInterpreterProfile &&
                         (ScaleLimit(profilingInterpreter1Limit) || ScaleLimit(profilingInterpreter0Limit))
                     :   doInterpreterProfile && ScaleLimit(profilingInterpreter0Limit) ||
@@ -6733,7 +6733,7 @@ namespace Js
                 // Simple JIT code has not yet been generated, and was either requested to be skipped, or the limit was scaled
                 // down too much. Skip simple JIT by moving any remaining iterations to an equivalent interpreter execution
                 // mode.
-                (IsNewSimpleJit() ? autoProfilingInterpreter1Limit : profilingInterpreter1Limit) += simpleJitLimit;
+                (CONFIG_FLAG(NewSimpleJit) ? autoProfilingInterpreter1Limit : profilingInterpreter1Limit) += simpleJitLimit;
                 simpleJitLimit = 0;
                 TryTransitionToNextInterpreterExecutionMode();
             }
@@ -6799,7 +6799,7 @@ namespace Js
         VerifyExecutionModeLimits();
 
         if(&limit == profilingInterpreter0Limit.AddressOf() ||
-            !IsNewSimpleJit() && &limit == simpleJitLimit.AddressOf() ||
+            !CONFIG_FLAG(NewSimpleJit) && &limit == simpleJitLimit.AddressOf() ||
             &limit == profilingInterpreter1Limit.AddressOf())
         {
             const uint16 newCommittedProfiledIterations = committedProfiledIterations + clampedExecutedIterations;
@@ -6880,7 +6880,7 @@ namespace Js
             }
 
             case ExecutionMode::SimpleJit:
-                if(!IsNewSimpleJit())
+                if(!CONFIG_FLAG(NewSimpleJit))
                 {
                     const uint16 newProfiledIterations = profiledIterations + GetSimpleJitExecutedIterations();
                     profiledIterations = newProfiledIterations >= profiledIterations ? newProfiledIterations : MAXUINT16;
@@ -6966,11 +6966,6 @@ namespace Js
         Output::Flush();
     }
 
-    bool FunctionBody::IsNewSimpleJit()
-    {
-        return CONFIG_FLAG(NewSimpleJit);
-    }
-
     bool FunctionBody::DoSimpleJit() const
     {
         return
@@ -6978,7 +6973,7 @@ namespace Js
             !GetScriptContext()->GetConfig()->IsNoNative() &&
             !GetScriptContext()->IsInDebugMode() &&
             DoInterpreterProfile() &&
-            (!IsNewSimpleJit() || DoInterpreterAutoProfile()) &&
+            (!CONFIG_FLAG(NewSimpleJit) || DoInterpreterAutoProfile()) &&
             !IsGenerator(); // Generator JIT requires bailout which SimpleJit cannot do since it skips GlobOpt
     }
 
@@ -6986,7 +6981,7 @@ namespace Js
     {
         Assert(DoSimpleJit());
 
-        return !PHASE_OFF(Js::SimpleJitDynamicProfilePhase, this) && !IsNewSimpleJit();
+        return !PHASE_OFF(Js::SimpleJitDynamicProfilePhase, this) && !CONFIG_FLAG(NewSimpleJit);
     }
 
     bool FunctionBody::DoInterpreterProfile() const
@@ -7042,7 +7037,7 @@ namespace Js
             TraceExecutionMode("WasCalledFromLoop (before)");
             if(fullJitThreshold > 1)
             {
-                SetFullJitThreshold(fullJitThreshold / 2, !IsNewSimpleJit());
+                SetFullJitThreshold(fullJitThreshold / 2, !CONFIG_FLAG(NewSimpleJit));
             }
         }
 
@@ -7097,7 +7092,7 @@ namespace Js
     {
         return
             static_cast<uint>(
-                IsNewSimpleJit()
+                CONFIG_FLAG(NewSimpleJit)
                     ? DEFAULT_CONFIG_MinProfileIterations
                     : DEFAULT_CONFIG_MinProfileIterations_OldSimpleJit);
     }

+ 1 - 7
lib/Runtime/Base/FunctionBody.h

@@ -1280,7 +1280,7 @@ namespace Js
         bool IsJitLoopBodyPhaseEnabled() const
         {
             // Consider: Allow JitLoopBody in generator functions for loops that do not yield.
-            return !PHASE_OFF(JITLoopBodyPhase, this) && DoFullJit() && !this->IsGenerator();
+            return !PHASE_OFF(JITLoopBodyPhase, this) && !PHASE_OFF(FullJitPhase, this) && !this->IsGenerator();
         }
 
         bool IsJitLoopBodyPhaseForced() const
@@ -1298,11 +1298,6 @@ namespace Js
         ULONG GetHostStartLine() const;
         ULONG GetHostStartColumn() const;
 
-        bool DoFullJit() const
-        {
-            return !PHASE_OFF(FullJitPhase, this);
-        }
-
     protected:
         // Static method(s)
         static void SetDisplayName(const wchar_t* srcName, WriteBarrierPtr<const wchar_t>* destName, uint displayNameLength, ScriptContext * scriptContext, SetDisplayNameFlags flags = SetDisplayNameFlagsNone);
@@ -2153,7 +2148,6 @@ namespace Js
         void DoTraceExecutionMode(const char *const eventDescription) const;
 
     public:
-        static bool IsNewSimpleJit();
         bool DoSimpleJit() const;
         bool DoSimpleJitDynamicProfile() const;
 

+ 11 - 1
lib/Runtime/Base/ScriptContext.h

@@ -414,7 +414,17 @@ namespace Js
             contextData.falseAddr = (intptr_t)GetLibrary()->GetFalse();
             contextData.undeclBlockVarAddr = (intptr_t)GetLibrary()->GetUndeclBlockVar();
             contextData.scriptContextAddr = (intptr_t)this;
-
+            contextData.emptyStringAddr = (intptr_t)GetLibrary()->GetEmptyString();
+            contextData.negativeZeroAddr = (intptr_t)GetLibrary()->GetNegativeZero();
+            contextData.numberTypeStaticAddr = (intptr_t)GetLibrary()->GetNumberTypeStatic();
+            contextData.stringTypeStaticAddr = (intptr_t)GetLibrary()->GetStringTypeStatic();
+            contextData.objectTypeAddr = (intptr_t)GetLibrary()->GetObjectType();
+            contextData.objectHeaderInlinedTypeAddr = (intptr_t)GetLibrary()->GetObjectHeaderInlinedType();
+            contextData.regexTypeAddr = (intptr_t)GetLibrary()->GetRegexType();
+            contextData.arrayConstructorAddr = (intptr_t)GetLibrary()->GetArrayConstructor();
+            contextData.charStringCacheAddr = (intptr_t)&GetLibrary()->GetCharStringCache();
+            CompileAssert(VTableValue::Count == 39); // need to update idl chen this changes
+            memcpy_s(contextData.vtableAddresses, 39 * sizeof(intptr_t), GetLibrary()->GetVTableAddresses(), VTableValue::Count * sizeof(INT_PTR));
             this->threadContext->m_codeGenManager.InitializeScriptContext(&contextData, &m_remoteScriptContextAddr);
         }
 

+ 1 - 0
lib/Runtime/Base/ThreadContext.h

@@ -528,6 +528,7 @@ public:
         contextData.chakraBaseAddress = (intptr_t)GetModuleHandle(L"Chakra.dll");
         contextData.crtBaseAddress = (intptr_t)GetModuleHandle(UCrtC99MathApis::LibraryName);
         contextData.threadStackLimitAddr = reinterpret_cast<intptr_t>(GetAddressOfStackLimitForCurrentThread());
+        contextData.threadStackLimitAddr = (intptr_t)bailOutRegisterSaveSpace;
         contextData.scriptStackLimit = reinterpret_cast<size_t>(GetScriptStackLimit());
         contextData.isThreadBound = GetIsThreadBound();
         m_codeGenManager.InitializeThreadContext(&contextData, &m_remoteThreadContextInfo);

+ 1 - 0
lib/Runtime/Language/FunctionCodeGenJitTimeData.h

@@ -464,6 +464,7 @@ namespace Js
 
     public:
         ObjTypeSpecFldInfo* GetInfo(FunctionBody *const functionBody, const uint index) const;
+        ObjTypeSpecFldInfo* GetInfo(const uint index) const;
 
         void SetInfo(Recycler *const recycler, FunctionBody *const functionBody,
             const uint index, ObjTypeSpecFldInfo* info);

+ 2 - 2
lib/Runtime/Library/JavascriptFunction.cpp

@@ -1629,7 +1629,7 @@ LABEL1:
 
     */
 #ifdef _M_X64
-    ArrayAccessDecoder::InstructionData ArrayAccessDecoder::CheckValidInstr(BYTE* &pc, PEXCEPTION_POINTERS exceptionInfo, FunctionBody* funcBody) // get the reg operand and isLoad and
+    ArrayAccessDecoder::InstructionData ArrayAccessDecoder::CheckValidInstr(BYTE* &pc, PEXCEPTION_POINTERS exceptionInfo) // get the reg operand and isLoad and
     {
         InstructionData instrData;
         uint prefixValue = 0;
@@ -2026,7 +2026,7 @@ LABEL1:
         }
 
         BYTE* pc = (BYTE*)exceptionInfo->ExceptionRecord->ExceptionAddress;
-        ArrayAccessDecoder::InstructionData instrData = ArrayAccessDecoder::CheckValidInstr(pc, exceptionInfo, funcBody);
+        ArrayAccessDecoder::InstructionData instrData = ArrayAccessDecoder::CheckValidInstr(pc, exceptionInfo);
         // Check If the instruction is valid
         if (instrData.isInvalidInstr)
         {

+ 1 - 1
lib/Runtime/Library/JavascriptFunction.h

@@ -228,7 +228,7 @@ namespace Js
             uint rexValue;
             RexByteValue() :isR(0), isX(0), isW(0), isB(0), rexValue(0){}
         };
-        static InstructionData CheckValidInstr(BYTE* &pc, PEXCEPTION_POINTERS exceptionInfo, FunctionBody* funcBody);
+        static InstructionData CheckValidInstr(BYTE* &pc, PEXCEPTION_POINTERS exceptionInfo);
     };
 
     //