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

basic obj type spec implementation

Michael Holman преди 9 години
родител
ревизия
b7eb685713
променени са 67 файла, в които са добавени 1611 реда и са изтрити 751 реда
  1. 2 2
      lib/Backend/AsmJsJITInfo.cpp
  2. 2 2
      lib/Backend/AsmJsJITInfo.h
  3. 4 0
      lib/Backend/Backend.h
  4. 19 17
      lib/Backend/BackwardPass.cpp
  5. 8 0
      lib/Backend/Chakra.Backend.vcxproj
  6. 8 0
      lib/Backend/Chakra.Backend.vcxproj.filters
  7. 2 2
      lib/Backend/CodeGenWorkItem.h
  8. 6 6
      lib/Backend/Encoder.cpp
  9. 8 8
      lib/Backend/FlowGraph.h
  10. 17 32
      lib/Backend/Func.cpp
  11. 11 12
      lib/Backend/Func.h
  12. 2 2
      lib/Backend/FunctionJITRuntimeInfo.cpp
  13. 2 2
      lib/Backend/FunctionJITRuntimeInfo.h
  14. 170 13
      lib/Backend/FunctionJITTimeInfo.cpp
  15. 7 4
      lib/Backend/FunctionJITTimeInfo.h
  16. 9 13
      lib/Backend/GlobOpt.cpp
  17. 12 12
      lib/Backend/GlobOpt.h
  18. 20 22
      lib/Backend/GlobOptFields.cpp
  19. 17 32
      lib/Backend/IR.cpp
  20. 2 3
      lib/Backend/IR.h
  21. 7 10
      lib/Backend/IRBuilder.cpp
  22. 2 0
      lib/Backend/IRBuilderAsmJs.cpp
  23. 25 23
      lib/Backend/Inline.cpp
  24. 1 1
      lib/Backend/Inline.h
  25. 224 0
      lib/Backend/JITObjTypeSpecFldInfo.cpp
  26. 62 0
      lib/Backend/JITObjTypeSpecFldInfo.h
  27. 2 2
      lib/Backend/JITOutput.cpp
  28. 3 3
      lib/Backend/JITOutput.h
  29. 143 0
      lib/Backend/JITTimeConstructorCache.cpp
  30. 37 0
      lib/Backend/JITTimeConstructorCache.h
  31. 25 7
      lib/Backend/JITTimeFunctionBody.cpp
  32. 7 5
      lib/Backend/JITTimeFunctionBody.h
  33. 25 17
      lib/Backend/JITTimeProfileInfo.cpp
  34. 4 3
      lib/Backend/JITTimeProfileInfo.h
  35. 4 5
      lib/Backend/JITTimeWorkItem.cpp
  36. 5 5
      lib/Backend/JITTimeWorkItem.h
  37. 91 0
      lib/Backend/JITType.cpp
  38. 33 0
      lib/Backend/JITType.h
  39. 58 0
      lib/Backend/JITTypeHandler.cpp
  40. 24 0
      lib/Backend/JITTypeHandler.h
  41. 106 113
      lib/Backend/Lower.cpp
  42. 14 14
      lib/Backend/Lower.h
  43. 4 0
      lib/Backend/NativeCodeData.cpp
  44. 1 1
      lib/Backend/NativeCodeData.h
  45. 3 2
      lib/Backend/NativeCodeGenerator.cpp
  46. 29 26
      lib/Backend/Opnd.cpp
  47. 19 24
      lib/Backend/Opnd.h
  48. 7 1
      lib/Backend/ScriptContextInfo.cpp
  49. 3 2
      lib/Backend/ScriptContextInfo.h
  50. 3 3
      lib/Backend/ThreadContextInfo.cpp
  51. 5 4
      lib/Backend/ThreadContextInfo.h
  52. 4 4
      lib/JITClient/JITManager.cpp
  53. 4 4
      lib/JITClient/JITManager.h
  54. 153 83
      lib/JITIDL/ChakraJIT.idl
  55. 4 4
      lib/JITServer/JITServer.cpp
  56. 2 2
      lib/Runtime/Base/FunctionBody.cpp
  57. 10 9
      lib/Runtime/Base/FunctionBody.h
  58. 1 1
      lib/Runtime/Base/ScriptContext.h
  59. 1 1
      lib/Runtime/Base/ThreadContext.cpp
  60. 2 2
      lib/Runtime/Language/FunctionCodeGenJitTimeData.cpp
  61. 7 4
      lib/Runtime/Language/FunctionCodeGenJitTimeData.h
  62. 2 2
      lib/Runtime/Language/InlineCache.cpp
  63. 14 6
      lib/Runtime/Language/InlineCache.h
  64. 3 3
      lib/Runtime/Language/JavascriptOperators.cpp
  65. 12 7
      lib/Runtime/Language/ObjTypeSpecFldInfo.cpp
  66. 85 164
      lib/Runtime/Language/ObjTypeSpecFldInfo.h
  67. 3 0
      lib/Runtime/Library/JavascriptLibrary.cpp

+ 2 - 2
lib/Backend/AsmJsJITInfo.cpp

@@ -5,10 +5,10 @@
 
 #include "Backend.h"
 
-AsmJsJITInfo::AsmJsJITInfo(AsmJsJITData * data) :
+AsmJsJITInfo::AsmJsJITInfo(AsmJsDataIDL * data) :
     m_data(*data)
 {
-    CompileAssert(sizeof(AsmJsJITInfo) == sizeof(AsmJsJITData));
+    CompileAssert(sizeof(AsmJsJITInfo) == sizeof(AsmJsDataIDL));
 }
 
 int

+ 2 - 2
lib/Backend/AsmJsJITInfo.h

@@ -8,7 +8,7 @@
 class AsmJsJITInfo
 {
 public:
-    AsmJsJITInfo(AsmJsJITData * data);
+    AsmJsJITInfo(AsmJsDataIDL * data);
 
     int GetIntConstCount() const;
     int GetDoubleConstCount() const;
@@ -38,5 +38,5 @@ public:
     bool UsesHeapBuffer() const;
 
 private:
-    AsmJsJITData m_data;
+    AsmJsDataIDL m_data;
 };

+ 4 - 0
lib/Backend/Backend.h

@@ -117,6 +117,10 @@ enum IRDumpFlags
 #include "CodeGenWorkItemType.h"
 #include "CodeGenAllocators.h"
 #include "ThreadContextInfo.h"
+#include "JITTimeConstructorCache.h"
+#include "JITTypeHandler.h"
+#include "JITType.h"
+#include "JITObjTypeSpecFldInfo.h"
 #include "ScriptContextInfo.h"
 #include "JITOutput.h"
 #include "JITTimeScriptContext.h"

+ 19 - 17
lib/Backend/BackwardPass.cpp

@@ -3299,7 +3299,7 @@ BackwardPass::ProcessNewScObject(IR::Instr* instr)
 
             Assert(instr->GetDst()->AsRegOpnd()->GetStackSym()->HasObjectTypeSym());
 
-            Js::JitTimeConstructorCache* ctorCache = instr->m_func->GetConstructorCache(static_cast<Js::ProfileId>(instr->AsProfiledInstr()->u.profileId));
+            JITTimeConstructorCache* ctorCache = instr->m_func->GetConstructorCache(static_cast<Js::ProfileId>(instr->AsProfiledInstr()->u.profileId));
 
             if (block->stackSymToFinalType != nullptr)
             {
@@ -3310,7 +3310,7 @@ BackwardPass::ProcessNewScObject(IR::Instr* instr)
                     pBucket->GetInitialType() != nullptr &&
                     pBucket->GetFinalType() != pBucket->GetInitialType())
                 {
-                    Assert(pBucket->GetInitialType() == ctorCache->type);
+                    Assert(pBucket->GetInitialType() == ctorCache->GetType());
                     if (!this->IsPrePass())
                     {
                         this->InsertTypeTransition(instr->m_next, objSym, pBucket);
@@ -3946,7 +3946,7 @@ BackwardPass::TrackObjTypeSpecProperties(IR::PropertySymOpnd *opnd, BasicBlock *
 #if DBG
         FOREACH_BITSET_IN_SPARSEBV(propOpId, guardedPropertyOps)
         {
-            Js::ObjTypeSpecFldInfo* existingFldInfo = this->func->GetGlobalObjTypeSpecFldInfo(propOpId);
+            JITObjTypeSpecFldInfo* existingFldInfo = this->func->GetGlobalObjTypeSpecFldInfo(propOpId);
             Assert(existingFldInfo != nullptr);
 
             if (existingFldInfo->GetPropertyId() != opnd->GetPropertyId())
@@ -4128,8 +4128,8 @@ BackwardPass::TrackAddPropertyTypes(IR::PropertySymOpnd *opnd, BasicBlock *block
     Assert(this->tag == Js::DeadStorePhase);
     Assert(opnd->IsMono() || opnd->HasEquivalentTypeSet());
 
-    Js::Type *typeWithProperty = opnd->IsMono() ? opnd->GetType() : opnd->GetFirstEquivalentType();
-    Js::Type *typeWithoutProperty = opnd->HasInitialType() ? opnd->GetInitialType() : nullptr;
+    JITType *typeWithProperty = opnd->IsMono() ? opnd->GetType() : opnd->GetFirstEquivalentType();
+    JITType *typeWithoutProperty = opnd->HasInitialType() ? opnd->GetInitialType() : nullptr;
 
     if (typeWithoutProperty == nullptr ||
         typeWithProperty == typeWithoutProperty ||
@@ -4149,7 +4149,7 @@ BackwardPass::TrackAddPropertyTypes(IR::PropertySymOpnd *opnd, BasicBlock *block
         return;
     }
 
-#if DBG
+#if 0 // TODO: OOP JIT, add these assert back (ReadProcessMemory?)
     Assert(typeWithProperty != nullptr);
     Js::DynamicTypeHandler * typeWithoutPropertyTypeHandler = static_cast<Js::DynamicType *>(typeWithoutProperty)->GetTypeHandler();
     Js::DynamicTypeHandler * typeWithPropertyTypeHandler = static_cast<Js::DynamicType *>(typeWithProperty)->GetTypeHandler();
@@ -4171,9 +4171,9 @@ BackwardPass::TrackAddPropertyTypes(IR::PropertySymOpnd *opnd, BasicBlock *block
     AddPropertyCacheBucket *pBucket =
         block->stackSymToFinalType->FindOrInsertNew(propertySym->m_stackSym->m_id);
 
-    Js::Type* finalType = nullptr;
+    JITType * finalType = nullptr;
 #if DBG
-    Js::Type * deadStoreUnavailableFinalType = nullptr;
+    JITType * deadStoreUnavailableFinalType = nullptr;
 #endif
     if (pBucket->GetInitialType() == nullptr || opnd->GetType() != pBucket->GetInitialType())
     {
@@ -4201,7 +4201,7 @@ BackwardPass::TrackAddPropertyTypes(IR::PropertySymOpnd *opnd, BasicBlock *block
 
     if (!PHASE_OFF(Js::ObjTypeSpecStorePhase, this->func))
     {
-#if DBG
+#if 0 //TODO: OOP JIT, reenable assert
 
         // We may regress in this case:
         // if (b)
@@ -4222,7 +4222,7 @@ BackwardPass::TrackAddPropertyTypes(IR::PropertySymOpnd *opnd, BasicBlock *block
         if (!opnd->IsTypeDead())
         {
             // This is the type that would have been propagated if we didn't kill it because the type isn't available
-            Js::Type * checkFinalType = deadStoreUnavailableFinalType ? deadStoreUnavailableFinalType : finalType;
+            JITType * checkFinalType = deadStoreUnavailableFinalType ? deadStoreUnavailableFinalType : finalType;
             if (opnd->HasFinalType() && opnd->GetFinalType() != checkFinalType)
             {
                 // Final type discovery must be progressively better (unless we kill it in the deadstore pass
@@ -4301,9 +4301,12 @@ BackwardPass::InsertTypeTransition(IR::Instr *instrInsertBefore, StackSym *objSy
     baseOpnd->SetIsJITOptimizedReg(true);
 
     IR::AddrOpnd *initialTypeOpnd =
-        IR::AddrOpnd::New(data->GetInitialType(), IR::AddrOpndKindDynamicType, this->func);
+        IR::AddrOpnd::New(data->GetInitialType()->GetAddr(), IR::AddrOpndKindDynamicType, this->func);
+    initialTypeOpnd->m_metadata = data->GetInitialType();
+
     IR::AddrOpnd *finalTypeOpnd =
-        IR::AddrOpnd::New(data->GetFinalType(), IR::AddrOpndKindDynamicType, this->func);
+        IR::AddrOpnd::New(data->GetFinalType()->GetAddr(), IR::AddrOpndKindDynamicType, this->func);
+    finalTypeOpnd->m_metadata = data->GetFinalType();
 
     IR::Instr *adjustTypeInstr =
         IR::Instr::New(Js::OpCode::AdjustObjType, finalTypeOpnd, baseOpnd, initialTypeOpnd, this->func);
@@ -4467,13 +4470,13 @@ BackwardPass::ForEachAddPropertyCacheBucket(Fn fn)
 bool
 BackwardPass::TransitionUndoesObjectHeaderInlining(AddPropertyCacheBucket *data) const
 {
-    Js::Type *type = data->GetInitialType();
+    JITType *type = data->GetInitialType();
     if (type == nullptr || !Js::DynamicType::Is(type->GetTypeId()))
     {
         return false;
     }
-    Js::DynamicType *dynamicType = static_cast<Js::DynamicType*>(type);
-    if (!dynamicType->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler())
+
+    if (!type->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler())
     {
         return false;
     }
@@ -4483,8 +4486,7 @@ BackwardPass::TransitionUndoesObjectHeaderInlining(AddPropertyCacheBucket *data)
     {
         return false;
     }
-    dynamicType = static_cast<Js::DynamicType*>(type);
-    return !dynamicType->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler();
+    return !type->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler();
 }
 
 void

+ 8 - 0
lib/Backend/Chakra.Backend.vcxproj

@@ -369,10 +369,14 @@
     <ClInclude Include="IRViewer.h" />
     <ClInclude Include="IRType.h" />
     <ClInclude Include="IRTypeList.h" />
+    <ClInclude Include="JITObjTypeSpecFldInfo.h" />
     <ClInclude Include="JITOutput.h" />
+    <ClInclude Include="JITTimeConstructorCache.h" />
     <ClInclude Include="JITTimeFunctionBody.h" />
     <ClInclude Include="JITTimeProfileInfo.h" />
     <ClInclude Include="JITTimeScriptContext.h" />
+    <ClInclude Include="JITType.h" />
+    <ClInclude Include="JITTypeHandler.h" />
     <ClInclude Include="ScriptContextInfo.h" />
     <ClInclude Include="ThreadContextInfo.h" />
     <ClInclude Include="JITTimeWorkItem.h" />
@@ -437,6 +441,10 @@
     <ClCompile Include="AsmJsJITInfo.cpp" />
     <ClCompile Include="FunctionJITRuntimeInfo.cpp" />
     <ClCompile Include="FunctionJITTimeInfo.cpp" />
+    <ClCompile Include="JITObjTypeSpecFldInfo.cpp" />
+    <ClCompile Include="JITTimeConstructorCache.cpp" />
+    <ClCompile Include="JITType.cpp" />
+    <ClCompile Include="JITTypeHandler.cpp" />
   </ItemGroup>
   <Import Project="$(BuildConfigPropsPath)Chakra.Build.targets" Condition="exists('$(BuildConfigPropsPath)Chakra.Build.targets')" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+ 8 - 0
lib/Backend/Chakra.Backend.vcxproj.filters

@@ -116,6 +116,10 @@
     <ClCompile Include="AsmJsJITInfo.cpp" />
     <ClCompile Include="FunctionJITTimeInfo.cpp" />
     <ClCompile Include="FunctionJITRuntimeInfo.cpp" />
+    <ClCompile Include="JITObjTypeSpecFldInfo.cpp" />
+    <ClCompile Include="JITTimeConstructorCache.cpp" />
+    <ClCompile Include="JITType.cpp" />
+    <ClCompile Include="JITTypeHandler.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="AgenPeeps.h" />
@@ -317,6 +321,10 @@
     <ClInclude Include="AsmJsJITInfo.h" />
     <ClInclude Include="FunctionJITTimeInfo.h" />
     <ClInclude Include="FunctionJITRuntimeInfo.h" />
+    <ClInclude Include="JITObjTypeSpecFldInfo.h" />
+    <ClInclude Include="JITTimeConstructorCache.h" />
+    <ClInclude Include="JITType.h" />
+    <ClInclude Include="JITTypeHandler.h" />
   </ItemGroup>
   <ItemGroup>
     <MASM Include="$(MSBuildThisFileDirectory)amd64\LinearScanMdA.asm">

+ 2 - 2
lib/Backend/CodeGenWorkItem.h

@@ -17,7 +17,7 @@ protected:
         CodeGenWorkItemType type);
     ~CodeGenWorkItem();
 
-    CodeGenWorkItemJITData jitData;
+    CodeGenWorkItemIDL jitData;
 
     Js::FunctionBody *const functionBody;
     size_t codeAddress;
@@ -50,7 +50,7 @@ public:
         return static_cast<ExecutionMode>(this->jitData.jitMode);
     }
 
-    CodeGenWorkItemJITData * GetJITData()
+    CodeGenWorkItemIDL * GetJITData()
     {
         return &this->jitData;
     }

+ 6 - 6
lib/Backend/Encoder.cpp

@@ -363,8 +363,8 @@ Encoder::Encode()
                 this->m_func->GetJITFunctionBody()->GetDisplayName(), this->m_func->GetDebugNumberSet(debugStringBuffer), pinnedTypeRefCount);
             Output::Flush();
         }
-
-        entryPointInfo->GetJitTransferData()->SetRuntimeTypeRefs(compactPinnedTypeRefs, pinnedTypeRefCount);
+        // TODO: OOP JIT, JIT Transfer data
+        //entryPointInfo->GetJitTransferData()->SetRuntimeTypeRefs(compactPinnedTypeRefs, pinnedTypeRefCount);
     }
 
     // Save all equivalent type guards in a fixed size array on the JIT transfer data
@@ -379,7 +379,7 @@ Encoder::Encode()
         {
             *dstGuard++ = srcGuard;
         });
-        entryPointInfo->GetJitTransferData()->SetEquivalentTypeGuards(guards, count);
+        //entryPointInfo->GetJitTransferData()->SetEquivalentTypeGuards(guards, count);
     }
 
     if (this->m_func->lazyBailoutProperties.Count() > 0)
@@ -452,7 +452,7 @@ Encoder::Encode()
 
         //TODO: OOP JIT need a way to pass back the jitTransferData and in main process it need to amend the reference to typeGuardTransferRecord
         // or just have a allocation offset to locate the typeGuardTransferRecord
-        entryPointInfo->RecordTypeGuards(this->m_func->indexedPropertyGuardCount, typeGuardTransferRecord, typeGuardTransferSize);
+        //entryPointInfo->RecordTypeGuards(this->m_func->indexedPropertyGuardCount, typeGuardTransferRecord, typeGuardTransferSize);
     }
 
     // Save all constructor caches on the JIT transfer data in a map keyed by property ID. We will use this map when installing the entry
@@ -496,12 +496,12 @@ Encoder::Encode()
 
             int cacheIndex = 0;
 
-            srcCacheSet->Map([dstEntry, &cacheIndex](Js::ConstructorCache* cache) -> void
+            srcCacheSet->Map([dstEntry, &cacheIndex](intptr_t cache) -> void
             {
                 dstEntry->caches[cacheIndex++] = cache;
             });
 
-            dstEntry->caches[cacheIndex++] = nullptr;
+            dstEntry->caches[cacheIndex++] = 0;
             dstEntry = reinterpret_cast<Js::CtorCacheGuardTransferEntry*>(&dstEntry->caches[cacheIndex]);
         });
         dstEntry->propertyId = Js::Constants::NoProperty;

+ 8 - 8
lib/Backend/FlowGraph.h

@@ -13,8 +13,8 @@ class Func;
 class AddPropertyCacheBucket
 {
 private:
-    Js::Type* initialType;
-    Js::Type* finalType;
+    JITType* initialType;
+    JITType* finalType;
 public:
     AddPropertyCacheBucket() : initialType(nullptr), finalType(nullptr)
 #if DBG
@@ -52,18 +52,18 @@ public:
 #endif
     }
 
-    Js::Type *GetInitialType() const { return this->initialType; }
-    Js::Type *GetFinalType() const { return this->finalType; }
-    void SetInitialType(Js::Type *type) { this->initialType = type; }
-    void SetFinalType(Js::Type *type)  { this->finalType = type; }
+    JITType *GetInitialType() const { return this->initialType; }
+    JITType *GetFinalType() const { return this->finalType; }
+    void SetInitialType(JITType *type) { this->initialType = type; }
+    void SetFinalType(JITType *type)  { this->finalType = type; }
 
 #if DBG_DUMP
     void Dump() const;
 #endif
 
 #ifdef DBG
-    Js::Type * deadStoreUnavailableInitialType;
-    Js::Type * deadStoreUnavailableFinalType;
+    JITType * deadStoreUnavailableInitialType;
+    JITType * deadStoreUnavailableFinalType;
 #endif
 };
 

+ 17 - 32
lib/Backend/Func.cpp

@@ -9,7 +9,7 @@
 Func::Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
     ThreadContextInfo * threadContextInfo,
     ScriptContextInfo * scriptContextInfo,
-    JITOutputData * outputData,
+    JITOutputIDL * outputData,
     const FunctionJITRuntimeInfo *const runtimeInfo,
     Js::PolymorphicInlineCacheInfo * const polymorphicInlineCacheInfo, CodeGenAllocators *const codeGenAllocators,
     CodeGenNumberAllocator * numberAllocator,
@@ -197,7 +197,7 @@ Func::Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
     }
 
     this->constructorCacheCount = 0;
-    this->constructorCaches = AnewArrayZ(this->m_alloc, Js::JitTimeConstructorCache*, GetJITFunctionBody()->GetProfiledCallSiteCount());
+    this->constructorCaches = AnewArrayZ(this->m_alloc, JITTimeConstructorCache*, GetJITFunctionBody()->GetProfiledCallSiteCount());
 
 #if DBG_DUMP
     m_codeSize = -1;
@@ -456,7 +456,7 @@ Func::Codegen()
         ////
         
 
-        JITOutputData* jitOutputData = m_output.GetOutputData();
+        JITOutputIDL* jitOutputData = m_output.GetOutputData();
 
         jitOutputData->nativeDataFixupTable = (NativeDataFixupTable*)midl_user_allocate(offsetof(NativeDataFixupTable, fixupRecords) + sizeof(NativeDataFixupRecord)* (dataAllocator->allocCount));
         jitOutputData->nativeDataFixupTable->count = dataAllocator->allocCount;
@@ -1157,7 +1157,7 @@ Func::GetPolyCacheUtil(const uint index) const
     return this->m_polymorphicInlineCacheInfo->GetUtilArray()->GetUtil(this->m_jnFunction, index);
 }
 
-Js::ObjTypeSpecFldInfo*
+JITObjTypeSpecFldInfo*
 Func::GetObjTypeSpecFldInfo(const uint index) const
 {
     if (GetJITFunctionBody()->GetInlineCacheCount() == 0)
@@ -1168,25 +1168,10 @@ Func::GetObjTypeSpecFldInfo(const uint index) const
     return GetWorkItem()->GetJITTimeInfo()->GetObjTypeSpecFldInfo(index);
 }
 
-Js::ObjTypeSpecFldInfo*
+JITObjTypeSpecFldInfo*
 Func::GetGlobalObjTypeSpecFldInfo(uint propertyInfoId) const
 {
-    Assert(UNREACHED); // TODO: OOP JIT
-#if 0
-    Assert(this->m_jitTimeData != nullptr);
-    return this->m_jitTimeData->GetGlobalObjTypeSpecFldInfo(propertyInfoId);
-#endif
-    return nullptr;
-}
-
-void
-Func::SetGlobalObjTypeSpecFldInfo(uint propertyInfoId, Js::ObjTypeSpecFldInfo* info)
-{
-    Assert(UNREACHED); // TODO: OOP JIT
-#if 0
-    Assert(this->m_jitTimeData != nullptr);
-    this->m_jitTimeData->SetGlobalObjTypeSpecFldInfo(propertyInfoId, info);
-#endif
+    return GetWorkItem()->GetJITTimeInfo()->GetGlobalObjTypeSpecFldInfo(propertyInfoId);
 }
 
 void
@@ -1215,20 +1200,20 @@ Func::EnsureSingleTypeGuards()
 }
 
 Js::JitTypePropertyGuard*
-Func::GetOrCreateSingleTypeGuard(Js::Type* type)
+Func::GetOrCreateSingleTypeGuard(intptr_t typeAddr)
 {
     EnsureSingleTypeGuards();
 
     Js::JitTypePropertyGuard* guard;
-    if (!this->singleTypeGuards->TryGetValue(type, &guard))
+    if (!this->singleTypeGuards->TryGetValue(typeAddr, &guard))
     {
         // Property guards are allocated by NativeCodeData::Allocator so that their lifetime extends as long as the EntryPointInfo is alive.
-        guard = NativeCodeDataNew(GetNativeCodeDataAllocator(), Js::JitTypePropertyGuard, type, this->indexedPropertyGuardCount++);
-        this->singleTypeGuards->Add(type, guard);
+        guard = NativeCodeDataNew(GetNativeCodeDataAllocator(), Js::JitTypePropertyGuard, typeAddr, this->indexedPropertyGuardCount++);
+        this->singleTypeGuards->Add(typeAddr, guard);
     }
     else
     {
-        Assert(guard->GetType() == type);
+        Assert(guard->GetTypeAddr() == typeAddr);
     }
 
     return guard;
@@ -1244,11 +1229,11 @@ Func::EnsureEquivalentTypeGuards()
 }
 
 Js::JitEquivalentTypeGuard*
-Func::CreateEquivalentTypeGuard(Js::Type* type, uint32 objTypeSpecFldId)
+Func::CreateEquivalentTypeGuard(JITType* type, uint32 objTypeSpecFldId)
 {
     EnsureEquivalentTypeGuards();
 
-    Js::JitEquivalentTypeGuard* guard = NativeCodeDataNew(GetNativeCodeDataAllocator(), Js::JitEquivalentTypeGuard, type, this->indexedPropertyGuardCount++, objTypeSpecFldId);
+    Js::JitEquivalentTypeGuard* guard = NativeCodeDataNew(GetNativeCodeDataAllocator(), Js::JitEquivalentTypeGuard, type->GetAddr(), this->indexedPropertyGuardCount++, objTypeSpecFldId);
 
     // If we want to hard code the address of the cache, we will need to go back to allocating it from the native code data allocator.
     // We would then need to maintain consistency (double write) to both the recycler allocated cache and the one on the heap.
@@ -1299,7 +1284,7 @@ Func::LinkGuardToPropertyId(Js::PropertyId propertyId, Js::JitIndexedPropertyGua
 }
 
 void
-Func::LinkCtorCacheToPropertyId(Js::PropertyId propertyId, Js::JitTimeConstructorCache* cache)
+Func::LinkCtorCacheToPropertyId(Js::PropertyId propertyId, JITTimeConstructorCache* cache)
 {
     Assert(cache != nullptr);
     Assert(this->ctorCachesByPropertyId != nullptr);
@@ -1311,17 +1296,17 @@ Func::LinkCtorCacheToPropertyId(Js::PropertyId propertyId, Js::JitTimeConstructo
         this->ctorCachesByPropertyId->Add(propertyId, set);
     }
 
-    set->Item(cache->runtimeCache);
+    set->Item(cache->GetRuntimeCacheAddr());
 }
 
-Js::JitTimeConstructorCache* Func::GetConstructorCache(const Js::ProfileId profiledCallSiteId)
+JITTimeConstructorCache* Func::GetConstructorCache(const Js::ProfileId profiledCallSiteId)
 {
     Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
     Assert(this->constructorCaches != nullptr);
     return this->constructorCaches[profiledCallSiteId];
 }
 
-void Func::SetConstructorCache(const Js::ProfileId profiledCallSiteId, Js::JitTimeConstructorCache* constructorCache)
+void Func::SetConstructorCache(const Js::ProfileId profiledCallSiteId, JITTimeConstructorCache* constructorCache)
 {
     Assert(profiledCallSiteId < GetJITFunctionBody()->GetProfiledCallSiteCount());
     Assert(constructorCache != nullptr);

+ 11 - 12
lib/Backend/Func.h

@@ -70,7 +70,7 @@ public:
     Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
         ThreadContextInfo * threadContextInfo,
         ScriptContextInfo * scriptContextInfo,
-        JITOutputData * outputData,
+        JITOutputIDL * outputData,
         const FunctionJITRuntimeInfo *const runtimeInfo,
         Js::PolymorphicInlineCacheInfo * const polymorphicInlineCacheInfo, CodeGenAllocators *const codeGenAllocators,
         CodeGenNumberAllocator * numberAllocator,
@@ -333,19 +333,19 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
     void PinTypeRef(void* typeRef);
 
     void EnsureSingleTypeGuards();
-    Js::JitTypePropertyGuard* GetOrCreateSingleTypeGuard(Js::Type* type);
+    Js::JitTypePropertyGuard* GetOrCreateSingleTypeGuard(intptr_t typeAddr);
 
     void  EnsureEquivalentTypeGuards();
-    Js::JitEquivalentTypeGuard * CreateEquivalentTypeGuard(Js::Type* type, uint32 objTypeSpecFldId);
+    Js::JitEquivalentTypeGuard * CreateEquivalentTypeGuard(JITType* type, uint32 objTypeSpecFldId);
 
     void EnsurePropertyGuardsByPropertyId();
     void EnsureCtorCachesByPropertyId();
 
     void LinkGuardToPropertyId(Js::PropertyId propertyId, Js::JitIndexedPropertyGuard* guard);
-    void LinkCtorCacheToPropertyId(Js::PropertyId propertyId, Js::JitTimeConstructorCache* cache);
+    void LinkCtorCacheToPropertyId(Js::PropertyId propertyId, JITTimeConstructorCache* cache);
 
-    Js::JitTimeConstructorCache* GetConstructorCache(const Js::ProfileId profiledCallSiteId);
-    void SetConstructorCache(const Js::ProfileId profiledCallSiteId, Js::JitTimeConstructorCache* constructorCache);
+    JITTimeConstructorCache * GetConstructorCache(const Js::ProfileId profiledCallSiteId);
+    void SetConstructorCache(const Js::ProfileId profiledCallSiteId, JITTimeConstructorCache* constructorCache);
 
     void EnsurePropertiesWrittenTo();
 
@@ -443,9 +443,8 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
 
     Js::JavascriptNumber* AllocateOOPNumber(double value);
 
-    Js::ObjTypeSpecFldInfo* GetObjTypeSpecFldInfo(const uint index) const;
-    Js::ObjTypeSpecFldInfo* GetGlobalObjTypeSpecFldInfo(uint propertyInfoId) const;
-    void SetGlobalObjTypeSpecFldInfo(uint propertyInfoId, Js::ObjTypeSpecFldInfo* info);
+    JITObjTypeSpecFldInfo* GetObjTypeSpecFldInfo(const uint index) const;
+    JITObjTypeSpecFldInfo* GetGlobalObjTypeSpecFldInfo(uint propertyInfoId) const;
 
     // Gets an inline cache pointer to use in jitted code. Cached data may not be stable while jitting. Does not return null.
     intptr_t GetRuntimeInlineCache(const uint index) const;
@@ -487,12 +486,12 @@ public:
     uint constructorCacheCount;
 
     // This array maps callsite ids to constructor caches. The size corresponds to the number of callsites in the function.
-    Js::JitTimeConstructorCache** constructorCaches;
+    JITTimeConstructorCache** constructorCaches;
 
     typedef JsUtil::BaseHashSet<void*, JitArenaAllocator, PowerOf2SizePolicy> TypeRefSet;
     TypeRefSet* pinnedTypeRefs;
 
-    typedef JsUtil::BaseDictionary<Js::Type*, Js::JitTypePropertyGuard*, JitArenaAllocator, PowerOf2SizePolicy> TypePropertyGuardDictionary;
+    typedef JsUtil::BaseDictionary<intptr_t, Js::JitTypePropertyGuard*, JitArenaAllocator, PowerOf2SizePolicy> TypePropertyGuardDictionary;
     TypePropertyGuardDictionary* singleTypeGuards;
 
     typedef SListCounted<Js::JitEquivalentTypeGuard*> EquivalentTypeGuardList;
@@ -502,7 +501,7 @@ public:
     typedef JsUtil::BaseDictionary<Js::PropertyId, IndexedPropertyGuardSet*, JitArenaAllocator, PowerOf2SizePolicy> PropertyGuardByPropertyIdMap;
     PropertyGuardByPropertyIdMap* propertyGuardsByPropertyId;
 
-    typedef JsUtil::BaseHashSet<Js::ConstructorCache*, JitArenaAllocator, PowerOf2SizePolicy> CtorCacheSet;
+    typedef JsUtil::BaseHashSet<intptr_t, JitArenaAllocator, PowerOf2SizePolicy> CtorCacheSet;
     typedef JsUtil::BaseDictionary<Js::PropertyId, CtorCacheSet*, JitArenaAllocator, PowerOf2SizePolicy> CtorCachesByPropertyIdMap;
     CtorCachesByPropertyIdMap* ctorCachesByPropertyId;
 

+ 2 - 2
lib/Backend/FunctionJITRuntimeInfo.cpp

@@ -5,9 +5,9 @@
 
 #include "Backend.h"
 
-FunctionJITRuntimeInfo::FunctionJITRuntimeInfo(FunctionJITRuntimeData * data) : m_data(*data)
+FunctionJITRuntimeInfo::FunctionJITRuntimeInfo(FunctionJITRuntimeIDL * data) : m_data(*data)
 {
-    CompileAssert(sizeof(FunctionJITRuntimeInfo) == sizeof(FunctionJITRuntimeData));
+    CompileAssert(sizeof(FunctionJITRuntimeInfo) == sizeof(FunctionJITRuntimeIDL));
 }
 
 intptr_t

+ 2 - 2
lib/Backend/FunctionJITRuntimeInfo.h

@@ -8,11 +8,11 @@
 class FunctionJITRuntimeInfo
 {
 public:
-    FunctionJITRuntimeInfo(FunctionJITRuntimeData * data);
+    FunctionJITRuntimeInfo(FunctionJITRuntimeIDL * data);
 
     intptr_t GetClonedInlineCache(uint index) const;
     bool HasClonedInlineCaches() const;
 
 private:
-    FunctionJITRuntimeData m_data;
+    FunctionJITRuntimeIDL m_data;
 };

+ 170 - 13
lib/Backend/FunctionJITTimeInfo.cpp

@@ -5,18 +5,18 @@
 
 #include "Backend.h"
 
-FunctionJITTimeInfo::FunctionJITTimeInfo(FunctionJITTimeData * data) : m_data(*data)
+FunctionJITTimeInfo::FunctionJITTimeInfo(FunctionJITTimeDataIDL * data) : m_data(*data)
 {
     // we will cast the data (i.e. midl struct) pointers into info pointers so we can extend with methods
-    CompileAssert(sizeof(FunctionJITTimeData) == sizeof(FunctionJITTimeInfo));
+    CompileAssert(sizeof(FunctionJITTimeDataIDL) == sizeof(FunctionJITTimeInfo));
 }
 
 /* static */
-FunctionJITTimeData *
+FunctionJITTimeDataIDL *
 FunctionJITTimeInfo::BuildJITTimeData(ArenaAllocator * alloc, const Js::FunctionCodeGenJitTimeData * codeGenData, bool isInlinee)
 {
     // using arena because we can't recycler allocate (may be on background), and heap freeing this is slightly complicated
-    FunctionJITTimeData * jitData = AnewStructZ(alloc, FunctionJITTimeData);
+    FunctionJITTimeDataIDL * jitData = AnewStructZ(alloc, FunctionJITTimeDataIDL);
     jitData->bodyData = codeGenData->GetJITBody();
     jitData->functionInfoAddr = (intptr_t)codeGenData->GetFunctionInfo();
 
@@ -25,7 +25,7 @@ FunctionJITTimeInfo::BuildJITTimeData(ArenaAllocator * alloc, const Js::Function
     jitData->isInlined = codeGenData->GetIsInlined();
     jitData->weakFuncRef = (intptr_t)codeGenData->GetWeakFuncRef();
 
-    jitData->inlineesBv = (BVFixedData*)codeGenData->inlineesBv;
+    jitData->inlineesBv = (BVFixedIDL*)codeGenData->inlineesBv;
 
     if (codeGenData->GetFunctionInfo()->HasBody())
     {
@@ -33,7 +33,7 @@ FunctionJITTimeInfo::BuildJITTimeData(ArenaAllocator * alloc, const Js::Function
         if (functionBody->HasDynamicProfileInfo())
         {
             Assert(jitData->bodyData != nullptr);
-            ProfileData * profileData = AnewStruct(alloc, ProfileData);
+            ProfileDataIDL * profileData = AnewStruct(alloc, ProfileDataIDL);
             JITTimeProfileInfo::InitializeJITProfileData(functionBody->GetAnyDynamicProfileInfo(), functionBody, profileData);
 
             jitData->bodyData->profileData = profileData;
@@ -46,12 +46,27 @@ FunctionJITTimeInfo::BuildJITTimeData(ArenaAllocator * alloc, const Js::Function
                 Assert(defaultEntryPointInfo->IsFunctionEntryPointInfo());
                 Js::FunctionEntryPointInfo *functionEntryPointInfo = static_cast<Js::FunctionEntryPointInfo*>(defaultEntryPointInfo);
                 jitData->callsCountAddress = (intptr_t)&functionEntryPointInfo->callsCount;
+
+                auto sharedGuards = functionEntryPointInfo->GetSharedPropertyGuards();
+                if (sharedGuards != nullptr)
+                {
+                    jitData->sharedPropGuardCount = sharedGuards->Count();
+                    jitData->sharedPropertyGuards = AnewArray(alloc, Js::PropertyId, sharedGuards->Count());
+                    auto sharedGuardIter = sharedGuards->GetIterator();
+                    uint i = 0;
+                    while (sharedGuardIter.IsValid())
+                    {
+                        jitData->sharedPropertyGuards[i] = sharedGuardIter.CurrentKey();
+                        sharedGuardIter.MoveNext();
+                        ++i;
+                    }
+                }
             }
         }
         if (jitData->bodyData->profiledCallSiteCount > 0)
         {
             jitData->inlineeCount = jitData->bodyData->profiledCallSiteCount;
-            jitData->inlinees = AnewArrayZ(alloc, FunctionJITTimeData*, jitData->bodyData->profiledCallSiteCount);
+            jitData->inlinees = AnewArrayZ(alloc, FunctionJITTimeDataIDL*, jitData->bodyData->profiledCallSiteCount);
             for (Js::ProfileId i = 0; i < jitData->bodyData->profiledCallSiteCount; ++i)
             {
                 const Js::FunctionCodeGenJitTimeData * inlinee = codeGenData->GetInlinee(i);
@@ -64,7 +79,13 @@ FunctionJITTimeInfo::BuildJITTimeData(ArenaAllocator * alloc, const Js::Function
         if (jitData->bodyData->inlineCacheCount > 0)
         {
             jitData->ldFldInlineeCount = jitData->bodyData->inlineCacheCount;
-            jitData->ldFldInlinees = AnewArrayZ(alloc, FunctionJITTimeData*, jitData->bodyData->inlineCacheCount);
+            jitData->ldFldInlinees = AnewArrayZ(alloc, FunctionJITTimeDataIDL*, jitData->bodyData->inlineCacheCount);
+
+            Js::ObjTypeSpecFldInfo ** objTypeSpecInfo = codeGenData->GetObjTypeSpecFldInfoArray() ? codeGenData->GetObjTypeSpecFldInfoArray()->GetInfoArray() : nullptr;
+            if(objTypeSpecInfo)
+            {
+                jitData->objTypeSpecFldInfoArray = AnewArrayZ(alloc, ObjTypeSpecFldIDL*, jitData->bodyData->inlineCacheCount);
+            }
             for (Js::InlineCacheIndex i = 0; i < jitData->bodyData->inlineCacheCount; ++i)
             {
                 const Js::FunctionCodeGenJitTimeData * inlinee = codeGenData->GetLdFldInlinee(i);
@@ -72,9 +93,118 @@ FunctionJITTimeInfo::BuildJITTimeData(ArenaAllocator * alloc, const Js::Function
                 {
                     jitData->ldFldInlinees[i] = BuildJITTimeData(alloc, inlinee);
                 }
+                if (objTypeSpecInfo != nullptr && objTypeSpecInfo[i] != nullptr)
+                {
+                    jitData->objTypeSpecFldInfoArray[i] = AnewStructZ(alloc, ObjTypeSpecFldIDL);
+                    if (objTypeSpecInfo[i]->IsLoadedFromProto())
+                    {
+                        jitData->objTypeSpecFldInfoArray[i]->protoObjectAddr = (intptr_t)objTypeSpecInfo[i]->GetProtoObject();
+                    }
+                    jitData->objTypeSpecFldInfoArray[i]->propertyGuardValueAddr = (intptr_t)objTypeSpecInfo[i]->GetPropertyGuard()->GetAddressOfValue();
+                    jitData->objTypeSpecFldInfoArray[i]->propertyId = objTypeSpecInfo[i]->GetPropertyId();
+                    jitData->objTypeSpecFldInfoArray[i]->typeId = objTypeSpecInfo[i]->GetTypeId();
+                    jitData->objTypeSpecFldInfoArray[i]->id = objTypeSpecInfo[i]->GetObjTypeSpecFldId();
+                    jitData->objTypeSpecFldInfoArray[i]->flags = objTypeSpecInfo[i]->GetFlags();
+                    jitData->objTypeSpecFldInfoArray[i]->slotIndex = objTypeSpecInfo[i]->GetSlotIndex();
+                    jitData->objTypeSpecFldInfoArray[i]->fixedFieldCount = objTypeSpecInfo[i]->GetFixedFieldCount();
+
+                    if (objTypeSpecInfo[i]->HasInitialType())
+                    {
+                        jitData->objTypeSpecFldInfoArray[i]->initialType = AnewStructZ(alloc, TypeIDL);
+                        JITType::BuildFromJsType(objTypeSpecInfo[i]->GetInitialType(), (JITType*)jitData->objTypeSpecFldInfoArray[i]->initialType);
+                    }
+
+                    if (objTypeSpecInfo[i]->GetCtorCache() != nullptr)
+                    {
+                        jitData->objTypeSpecFldInfoArray[i]->ctorCache = objTypeSpecInfo[i]->GetCtorCache()->GetData();
+                    }
+
+                    Js::EquivalentTypeSet * equivTypeSet = objTypeSpecInfo[i]->GetEquivalentTypeSet();
+                    if (equivTypeSet != nullptr)
+                    {
+                        jitData->objTypeSpecFldInfoArray[i]->typeSet = AnewStruct(alloc, EquivalentTypeSetIDL);
+                        jitData->objTypeSpecFldInfoArray[i]->typeSet->sortedAndDuplicatesRemoved = equivTypeSet->GetSortedAndDuplicatesRemoved();
+                        // REVIEW: OOP JIT, is this stable?
+                        jitData->objTypeSpecFldInfoArray[i]->typeSet->count = equivTypeSet->GetCount();
+                        jitData->objTypeSpecFldInfoArray[i]->typeSet->types = (TypeIDL**)equivTypeSet->GetTypes();
+                    }
+
+                    jitData->objTypeSpecFldInfoArray[i]->fixedFieldInfoArray = AnewArrayZ(alloc, FixedFieldIDL, objTypeSpecInfo[i]->GetFixedFieldCount());
+                    Js::FixedFieldInfo * ffInfo = objTypeSpecInfo[i]->GetFixedFieldInfoArray();
+                    for (uint16 j = 0; j < objTypeSpecInfo[i]->GetFixedFieldCount(); ++j)
+                    {
+                        jitData->objTypeSpecFldInfoArray[i]->fixedFieldInfoArray[j].fieldValue = (intptr_t)ffInfo[j].fieldValue;
+                        jitData->objTypeSpecFldInfoArray[i]->fixedFieldInfoArray[j].nextHasSameFixedField = ffInfo[j].nextHasSameFixedField;
+                        if(ffInfo[j].type != nullptr)
+                        {
+                            JITType::BuildFromJsType(ffInfo[j].type, (JITType*)&jitData->objTypeSpecFldInfoArray[i]->fixedFieldInfoArray[j].type);
+                        }
+                    }
+                }
             }
-            CompileAssert(sizeof(ObjTypeSpecFldData) == sizeof(Js::ObjTypeSpecFldInfo));
-            jitData->objTypeSpecFldInfoArray = reinterpret_cast<ObjTypeSpecFldData**>(codeGenData->GetObjTypeSpecFldInfoArray()->GetInfoArray());
+        }
+        if (codeGenData->GetGlobalObjTypeSpecFldInfoCount() > 0)
+        {
+            jitData->globalObjTypeSpecFldInfoCount = codeGenData->GetGlobalObjTypeSpecFldInfoCount();
+
+            Js::ObjTypeSpecFldInfo ** globObjTypeSpecInfo = codeGenData->GetGlobalObjTypeSpecFldInfoArray();
+            Assert(globObjTypeSpecInfo != nullptr);
+            jitData->globalObjTypeSpecFldInfoArray = AnewArrayZ(alloc, ObjTypeSpecFldIDL*, jitData->globalObjTypeSpecFldInfoCount);
+            for (uint i = 0; i < codeGenData->GetGlobalObjTypeSpecFldInfoCount(); ++i)
+            {
+                if (globObjTypeSpecInfo[i] == nullptr)
+                {
+                    continue;
+                }
+                jitData->globalObjTypeSpecFldInfoArray[i] = AnewStructZ(alloc, ObjTypeSpecFldIDL);
+                if (globObjTypeSpecInfo[i]->IsLoadedFromProto())
+                {
+                    jitData->globalObjTypeSpecFldInfoArray[i]->protoObjectAddr = (intptr_t)globObjTypeSpecInfo[i]->GetProtoObject();
+                }
+                jitData->globalObjTypeSpecFldInfoArray[i]->propertyGuardValueAddr = (intptr_t)globObjTypeSpecInfo[i]->GetPropertyGuard()->GetAddressOfValue();
+                jitData->globalObjTypeSpecFldInfoArray[i]->propertyId = globObjTypeSpecInfo[i]->GetPropertyId();
+                jitData->globalObjTypeSpecFldInfoArray[i]->typeId = globObjTypeSpecInfo[i]->GetTypeId();
+                jitData->globalObjTypeSpecFldInfoArray[i]->id = globObjTypeSpecInfo[i]->GetObjTypeSpecFldId();
+                jitData->globalObjTypeSpecFldInfoArray[i]->flags = globObjTypeSpecInfo[i]->GetFlags();
+                jitData->globalObjTypeSpecFldInfoArray[i]->slotIndex = globObjTypeSpecInfo[i]->GetSlotIndex();
+                jitData->globalObjTypeSpecFldInfoArray[i]->fixedFieldCount = globObjTypeSpecInfo[i]->GetFixedFieldCount();
+
+                if (globObjTypeSpecInfo[i]->HasInitialType())
+                {
+                    jitData->globalObjTypeSpecFldInfoArray[i]->initialType = AnewStructZ(alloc, TypeIDL);
+                    JITType::BuildFromJsType(globObjTypeSpecInfo[i]->GetInitialType(), (JITType*)jitData->globalObjTypeSpecFldInfoArray[i]->initialType);
+                }
+
+                if (globObjTypeSpecInfo[i]->GetCtorCache() != nullptr)
+                {
+                    jitData->globalObjTypeSpecFldInfoArray[i]->ctorCache = globObjTypeSpecInfo[i]->GetCtorCache()->GetData();
+                }
+
+                Js::EquivalentTypeSet * equivTypeSet = globObjTypeSpecInfo[i]->GetEquivalentTypeSet();
+                if (equivTypeSet != nullptr)
+                {
+                    jitData->globalObjTypeSpecFldInfoArray[i]->typeSet = AnewStruct(alloc, EquivalentTypeSetIDL);
+                    jitData->globalObjTypeSpecFldInfoArray[i]->typeSet->sortedAndDuplicatesRemoved = equivTypeSet->GetSortedAndDuplicatesRemoved();
+                    // REVIEW: OOP JIT, is this stable?
+                    jitData->globalObjTypeSpecFldInfoArray[i]->typeSet->count = equivTypeSet->GetCount();
+                    jitData->globalObjTypeSpecFldInfoArray[i]->typeSet->types = (TypeIDL**)equivTypeSet->GetTypes();
+                }
+
+                jitData->globalObjTypeSpecFldInfoArray[i]->fixedFieldInfoArray = AnewArrayZ(alloc, FixedFieldIDL, globObjTypeSpecInfo[i]->GetFixedFieldCount());
+                Js::FixedFieldInfo * ffInfo = globObjTypeSpecInfo[i]->GetFixedFieldInfoArray();
+                for (uint16 j = 0; j< globObjTypeSpecInfo[i]->GetFixedFieldCount(); ++j)
+                {
+                    jitData->globalObjTypeSpecFldInfoArray[i]->fixedFieldInfoArray[j].fieldValue = (intptr_t)ffInfo[j].fieldValue;
+                    jitData->globalObjTypeSpecFldInfoArray[i]->fixedFieldInfoArray[j].nextHasSameFixedField = ffInfo[j].nextHasSameFixedField;
+                    if (ffInfo[j].type != nullptr)
+                    {
+                        // TODO: OOP JIT, maybe type should be out of line? might not save anything on x64 though
+                        JITType::BuildFromJsType(ffInfo[j].type, (JITType*)&jitData->globalObjTypeSpecFldInfoArray[i]->fixedFieldInfoArray[j].type);
+                    }
+                }
+            }
+
+
         }
 
         auto codegenRuntimeData = functionBody->GetCodeGenRuntimeData();
@@ -82,7 +212,7 @@ FunctionJITTimeInfo::BuildJITTimeData(ArenaAllocator * alloc, const Js::Function
         {
             jitData->bodyData->runtimeDataCount = jitData->bodyData->profiledCallSiteCount;
             Assert(jitData->bodyData->profiledCallSiteCount > 0);
-            jitData->bodyData->profiledRuntimeData = AnewArrayZ(alloc, FunctionJITRuntimeData, jitData->bodyData->runtimeDataCount);
+            jitData->bodyData->profiledRuntimeData = AnewArrayZ(alloc, FunctionJITRuntimeIDL, jitData->bodyData->runtimeDataCount);
             // REVIEW: OOP JIT is this safe to be doing in background? I'm guessing probably not...
             for (uint i = 0; i < jitData->bodyData->runtimeDataCount; ++i)
             {
@@ -117,6 +247,25 @@ FunctionJITTimeInfo::IsLdFldInlineePresent() const
     return m_data.ldFldInlineeCount != 0;
 }
 
+bool
+FunctionJITTimeInfo::HasSharedPropertyGuards() const
+{
+    return m_data.sharedPropGuardCount != 0;
+}
+
+bool
+FunctionJITTimeInfo::HasSharedPropertyGuard(Js::PropertyId id) const
+{
+    for (uint i = 0; i < m_data.sharedPropGuardCount; ++i)
+    {
+        if (m_data.sharedPropertyGuards[i] == id)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
 intptr_t
 FunctionJITTimeInfo::GetFunctionInfoAddr() const
 {
@@ -164,13 +313,21 @@ FunctionJITTimeInfo::GetJitTimeDataFromFunctionInfoAddr(intptr_t polyFuncInfo) c
     return next;
 }
 
-Js::ObjTypeSpecFldInfo *
+JITObjTypeSpecFldInfo *
 FunctionJITTimeInfo::GetObjTypeSpecFldInfo(uint index) const
 {
     Assert(index < GetBody()->GetInlineCacheCount());
-    return reinterpret_cast<Js::ObjTypeSpecFldInfo **>(m_data.objTypeSpecFldInfoArray)[index];
+    return reinterpret_cast<JITObjTypeSpecFldInfo **>(m_data.objTypeSpecFldInfoArray)[index];
 }
 
+JITObjTypeSpecFldInfo *
+FunctionJITTimeInfo::GetGlobalObjTypeSpecFldInfo(uint index) const
+{
+    Assert(index < m_data.globalObjTypeSpecFldInfoCount);
+    return reinterpret_cast<JITObjTypeSpecFldInfo **>(m_data.globalObjTypeSpecFldInfoArray)[index];
+}
+
+
 uint
 FunctionJITTimeInfo::GetSourceContextId() const
 {

+ 7 - 4
lib/Backend/FunctionJITTimeInfo.h

@@ -8,8 +8,8 @@
 class FunctionJITTimeInfo
 {
 public:
-    FunctionJITTimeInfo(FunctionJITTimeData * data);
-    static FunctionJITTimeData * BuildJITTimeData(ArenaAllocator * alloc, const Js::FunctionCodeGenJitTimeData * codeGenData, bool isInlinee = true);
+    FunctionJITTimeInfo(FunctionJITTimeDataIDL * data);
+    static FunctionJITTimeDataIDL * BuildJITTimeData(ArenaAllocator * alloc, const Js::FunctionCodeGenJitTimeData * codeGenData, bool isInlinee = true);
 
     uint GetInlineeCount() const;
     bool IsLdFldInlineePresent() const;
@@ -28,11 +28,14 @@ public:
     bool IsInlined() const;
     const BVFixed * GetInlineesBV() const;
     const FunctionJITTimeInfo * GetJitTimeDataFromFunctionInfoAddr(intptr_t polyFuncInfo) const;
-    Js::ObjTypeSpecFldInfo * GetObjTypeSpecFldInfo(uint index) const;
+    JITObjTypeSpecFldInfo * GetObjTypeSpecFldInfo(uint index) const;
+    JITObjTypeSpecFldInfo * GetGlobalObjTypeSpecFldInfo(uint index) const;
     bool ForceJITLoopBody() const;
+    bool HasSharedPropertyGuards() const;
+    bool HasSharedPropertyGuard(Js::PropertyId id) const;
 
     wchar_t* GetDisplayName() const;
     wchar_t* GetDebugNumberSet(wchar(&bufferToWriteTo)[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE]) const;
 private:
-    FunctionJITTimeData m_data;
+    FunctionJITTimeDataIDL m_data;
 };

+ 9 - 13
lib/Backend/GlobOpt.cpp

@@ -2777,7 +2777,7 @@ BOOL GlobOpt::PreloadPRECandidate(Loop *loop, GlobHashBucket* candidate)
     IR::Instr * ldInstr = this->prePassInstrMap->Lookup(propertySym->m_id, nullptr);
     Assert(ldInstr);
 
-    Js::Type *propertyType = nullptr;
+    JITType *propertyType = nullptr;
 
     // Create instr to put in landing pad for compensation
     Assert(IsPREInstrCandidateLoad(ldInstr->m_opcode));
@@ -3359,9 +3359,9 @@ JsTypeValueInfo* GlobOpt::MergeJsTypeValueInfo(JsTypeValueInfo * toValueInfo, Js
         return nullptr;
     }
 
-    const Js::Type* toType = toValueInfo->GetJsType();
-    const Js::Type* fromType = fromValueInfo->GetJsType();
-    const Js::Type* mergedType = toType == fromType ? toType : nullptr;
+    const JITType* toType = toValueInfo->GetJsType();
+    const JITType* fromType = fromValueInfo->GetJsType();
+    const JITType* mergedType = toType == fromType ? toType : nullptr;
 
     Js::EquivalentTypeSet* toTypeSet = toValueInfo->GetJsTypeSet();
     Js::EquivalentTypeSet* fromTypeSet = fromValueInfo->GetJsTypeSet();
@@ -6719,7 +6719,7 @@ GlobOpt::HoistConstantLoadAndPropagateValueBackward(Js::Var varConst, IR::Instr
     // Insert a load of the constant at the top of the function
     StackSym *    dstSym = StackSym::New(this->func);
     IR::RegOpnd * constRegOpnd = IR::RegOpnd::New(dstSym, TyVar, this->func);
-    IR::Instr *   loadInstr = IR::Instr::NewConstantLoad(constRegOpnd, (intptr_t)varConst, Js::TypeId::TypeIds_Limit, this->func);
+    IR::Instr *   loadInstr = IR::Instr::NewConstantLoad(constRegOpnd, (intptr_t)varConst, ValueType::GetInt(true), this->func);
     this->func->m_fg->blockList->GetFirstInstr()->InsertAfter(loadInstr);
 
     // Type-spec the load (Support for floats needs to be added when we start hoisting float constants).
@@ -8770,11 +8770,6 @@ 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;
@@ -8795,8 +8790,9 @@ GlobOpt::OptConstFoldBranch(IR::Instr *instr, Value *src1Val, Value*src2Val, Val
     }
 
     // Make sure GetConstantVar only returns primitives.
-    Assert(!src1Var || !Js::JavascriptOperators::IsObject(src1Var));
-    Assert(!src2Var || !Js::JavascriptOperators::IsObject(src2Var));
+    // TODO: OOP JIT, enabled these asserts
+    //Assert(!src1Var || !Js::JavascriptOperators::IsObject(src1Var));
+    //Assert(!src2Var || !Js::JavascriptOperators::IsObject(src2Var));
 
     BOOL result;
     int32 constVal;
@@ -19969,7 +19965,7 @@ void ValueInfo::Dump()
     }
     else if(IsJsType())
     {
-        const Js::Type* type = AsJsType()->GetJsType();
+        const JITType* type = AsJsType()->GetJsType();
         type != nullptr ? Output::Print(L"type: 0x%p, ", type) : Output::Print(L"type: null, ");
         Output::Print(L"type Set: ");
         Js::EquivalentTypeSet* typeSet = AsJsType()->GetJsTypeSet();

+ 12 - 12
lib/Backend/GlobOpt.h

@@ -476,7 +476,7 @@ public:
 
 struct ObjectTypePropertyEntry
 {
-    Js::ObjTypeSpecFldInfo* fldInfo;
+    JITObjTypeSpecFldInfo* fldInfo;
     uint blockNumber;
 };
 
@@ -485,12 +485,12 @@ typedef JsUtil::BaseDictionary<Js::PropertyId, ObjectTypePropertyEntry, JitArena
 class JsTypeValueInfo : public ValueInfo
 {
 private:
-    const Js::Type * jsType;
+    const JITType * jsType;
     Js::EquivalentTypeSet * jsTypeSet;
     bool isShared;
 
 public:
-    JsTypeValueInfo(Js::Type * type)
+    JsTypeValueInfo(JITType * type)
         : ValueInfo(Uninitialized, ValueStructureKind::JsType),
         jsType(type), jsTypeSet(nullptr), isShared(false)
     {
@@ -508,7 +508,7 @@ public:
     {
     }
 
-    static JsTypeValueInfo * New(JitArenaAllocator *const allocator, Js::Type * typeSet)
+    static JsTypeValueInfo * New(JitArenaAllocator *const allocator, JITType * typeSet)
     {
         return JitAnew(allocator, JsTypeValueInfo, typeSet);
     }
@@ -518,13 +518,13 @@ public:
         return JitAnew(allocator, JsTypeValueInfo, typeSet);
     }
 
-    JsTypeValueInfo(const Js::Type* type, Js::EquivalentTypeSet * typeSet)
+    JsTypeValueInfo(const JITType* type, Js::EquivalentTypeSet * typeSet)
         : ValueInfo(Uninitialized, ValueStructureKind::JsType),
         jsType(type), jsTypeSet(typeSet), isShared(false)
     {
     }
 
-    static JsTypeValueInfo * New(JitArenaAllocator *const allocator, const Js::Type* type, Js::EquivalentTypeSet * typeSet)
+    static JsTypeValueInfo * New(JitArenaAllocator *const allocator, const JITType* type, Js::EquivalentTypeSet * typeSet)
     {
         return JitAnew(allocator, JsTypeValueInfo, type, typeSet);
     }
@@ -537,12 +537,12 @@ public:
         return newInfo;
     }
 
-    const Js::Type * GetJsType() const
+    const JITType * GetJsType() const
     {
         return this->jsType;
     }
 
-    void SetJsType(const Js::Type * value)
+    void SetJsType(const JITType * value)
     {
         Assert(!this->isShared);
         this->jsType = value;
@@ -1729,12 +1729,12 @@ private:
     bool                    ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd, BasicBlock* block, bool updateExistingValue, bool* emitsTypeCheckOut = nullptr, bool* changesTypeValueOut = nullptr, bool *isObjTypeChecked = nullptr);
     void                    KillObjectHeaderInlinedTypeSyms(BasicBlock *block, bool isObjTypeSpecialized, SymID symId = (SymID)-1);
     void                    ValueNumberObjectType(IR::Opnd *dstOpnd, IR::Instr *instr);
-    void                    SetSingleTypeOnObjectTypeValue(Value* value, const Js::Type* type);
+    void                    SetSingleTypeOnObjectTypeValue(Value* value, const JITType* type);
     void                    SetTypeSetOnObjectTypeValue(Value* value, Js::EquivalentTypeSet* typeSet);
-    void                    UpdateObjectTypeValue(Value* value, const Js::Type* type, bool setType, Js::EquivalentTypeSet* typeSet, bool setTypeSet);
+    void                    UpdateObjectTypeValue(Value* value, const JITType* type, bool setType, Js::EquivalentTypeSet* typeSet, bool setTypeSet);
     void                    SetObjectTypeFromTypeSym(StackSym *typeSym, Value* value, BasicBlock* block = nullptr);
-    void                    SetObjectTypeFromTypeSym(StackSym *typeSym, const Js::Type *type, Js::EquivalentTypeSet * typeSet, BasicBlock* block = nullptr, bool updateExistingValue = false);
-    void                    SetObjectTypeFromTypeSym(StackSym *typeSym, const Js::Type *type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData, bool updateExistingValue = false);
+    void                    SetObjectTypeFromTypeSym(StackSym *typeSym, const JITType *type, Js::EquivalentTypeSet * typeSet, BasicBlock* block = nullptr, bool updateExistingValue = false);
+    void                    SetObjectTypeFromTypeSym(StackSym *typeSym, const JITType *type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData, bool updateExistingValue = false);
     void                    KillObjectType(StackSym *objectSym, BVSparse<JitArenaAllocator>* liveFields = nullptr);
     void                    KillAllObjectTypes(BVSparse<JitArenaAllocator>* liveFields = nullptr);
     void                    EndFieldLifetime(IR::SymOpnd *symOpnd);

+ 20 - 22
lib/Backend/GlobOptFields.cpp

@@ -2107,7 +2107,7 @@ GlobOpt::PreparePropertySymOpndForTypeCheckSeq(IR::PropertySymOpnd * propertySym
         return false;
     }
 
-    Js::ObjTypeSpecFldInfo* info = propertySymOpnd->GetObjTypeSpecInfo();
+    JITObjTypeSpecFldInfo* info = propertySymOpnd->GetObjTypeSpecInfo();
 
     if (info->UsesAccessor() || info->IsRootObjectNonConfigurableFieldLoad())
     {
@@ -2225,11 +2225,10 @@ GlobOpt::KillObjectHeaderInlinedTypeSyms(BasicBlock *block, bool isObjTypeSpecia
             Assert(valueInfo);
             if (valueInfo->GetJsType())
             {
-                const Js::Type *type = valueInfo->GetJsType();
+                const JITType *type = valueInfo->GetJsType();
                 if (Js::DynamicType::Is(type->GetTypeId()))
                 {
-                    const Js::DynamicType *dynamicType = static_cast<const Js::DynamicType*>(type);
-                    if (dynamicType->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler())
+                    if (type->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler())
                     {
                         this->blockData.liveFields->Clear(symId);
                     }
@@ -2240,11 +2239,10 @@ GlobOpt::KillObjectHeaderInlinedTypeSyms(BasicBlock *block, bool isObjTypeSpecia
                 Js::EquivalentTypeSet *typeSet = valueInfo->GetJsTypeSet();
                 for (uint16 i = 0; i < typeSet->GetCount(); i++)
                 {
-                    const Js::Type *type = typeSet->GetType(i);
+                    const JITType *type = typeSet->GetType(i);
                     if (type && Js::DynamicType::Is(type->GetTypeId()))
                     {
-                        const Js::DynamicType *dynamicType = static_cast<const Js::DynamicType*>(type);
-                        if (dynamicType->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler())
+                        if (type->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler())
                         {
                             this->blockData.liveFields->Clear(symId);
                             break;
@@ -2337,7 +2335,7 @@ GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd
     if (!doEquivTypeCheck)
     {
         // We need a monomorphic type check here (e.g., final type opt, fixed field check on non-proto property).
-        Js::Type *opndType = opnd->GetType();
+        JITType *opndType = opnd->GetType();
 
         if (valueInfo == nullptr || (valueInfo->GetJsType() == nullptr && valueInfo->GetJsTypeSet() == nullptr))
         {
@@ -2354,7 +2352,7 @@ GlobOpt::ProcessPropOpInTypeCheckSeq(IR::Instr* instr, IR::PropertySymOpnd *opnd
         else if (valueInfo->GetJsType())
         {
             // We have a monomorphic type check upstream. Check against initial/final type.
-            const Js::Type *valueType = valueInfo->GetJsType();
+            const JITType *valueType = valueInfo->GetJsType();
             if (valueType == opndType)
             {
                 // The type on this instruction matches the live value in the value table, so there is no need to
@@ -2649,13 +2647,13 @@ GlobOpt::OptNewScObject(IR::Instr** instrPtr, Value* srcVal)
     }
 
     bool isCtorInlined = instr->m_opcode == Js::OpCode::NewScObjectNoCtor;
-    const Js::JitTimeConstructorCache* ctorCache = instr->IsProfiledInstr() ?
+    const JITTimeConstructorCache * ctorCache = instr->IsProfiledInstr() ?
         instr->m_func->GetConstructorCache(static_cast<Js::ProfileId>(instr->AsProfiledInstr()->u.profileId)) : nullptr;
 
     Assert(ctorCache == nullptr || srcVal->GetValueInfo()->IsVarConstant() && Js::JavascriptFunction::Is(srcVal->GetValueInfo()->AsVarConstant()->VarValue()));
-    Assert(ctorCache == nullptr || !ctorCache->typeIsFinal || ctorCache->ctorHasNoExplicitReturnValue);
+    Assert(ctorCache == nullptr || !ctorCache->IsTypeFinal() || ctorCache->CtorHasNoExplicitReturnValue());
 
-    if (ctorCache != nullptr && !ctorCache->skipNewScObject && (isCtorInlined || ctorCache->typeIsFinal))
+    if (ctorCache != nullptr && !ctorCache->SkipNewScObject() && (isCtorInlined || ctorCache->IsTypeFinal()))
     {
         GenerateBailAtOperation(instrPtr, IR::BailOutFailedCtorGuardCheck);
     }
@@ -2689,14 +2687,14 @@ GlobOpt::ValueNumberObjectType(IR::Opnd *dstOpnd, IR::Instr *instr)
             Assert(instr->GetBailOutKind() == IR::BailOutFailedCtorGuardCheck);
 
             bool isCtorInlined = instr->m_opcode == Js::OpCode::NewScObjectNoCtor;
-            const Js::JitTimeConstructorCache* ctorCache = instr->m_func->GetConstructorCache(static_cast<Js::ProfileId>(instr->AsProfiledInstr()->u.profileId));
-            Assert(ctorCache != nullptr && (isCtorInlined || ctorCache->typeIsFinal));
+            JITTimeConstructorCache * ctorCache = instr->m_func->GetConstructorCache(static_cast<Js::ProfileId>(instr->AsProfiledInstr()->u.profileId));
+            Assert(ctorCache != nullptr && (isCtorInlined || ctorCache->IsTypeFinal()));
 
             StackSym* objSym = dstOpnd->AsRegOpnd()->m_sym;
             StackSym* dstTypeSym = EnsureObjectTypeSym(objSym);
             Assert(this->FindValue(dstTypeSym) == nullptr);
 
-            SetObjectTypeFromTypeSym(dstTypeSym, ctorCache->type, nullptr);
+            SetObjectTypeFromTypeSym(dstTypeSym, ctorCache->GetType(), nullptr);
         }
     }
     else
@@ -2830,7 +2828,7 @@ GlobOpt::SetTypeCheckBailOut(IR::Opnd *opnd, IR::Instr *instr, BailOutInfo *bail
 }
 
 void
-GlobOpt::SetSingleTypeOnObjectTypeValue(Value* value, const Js::Type* type)
+GlobOpt::SetSingleTypeOnObjectTypeValue(Value* value, const JITType* type)
 {
     UpdateObjectTypeValue(value, type, true, nullptr, false);
 }
@@ -2842,7 +2840,7 @@ GlobOpt::SetTypeSetOnObjectTypeValue(Value* value, Js::EquivalentTypeSet* typeSe
 }
 
 void
-GlobOpt::UpdateObjectTypeValue(Value* value, const Js::Type* type, bool setType, Js::EquivalentTypeSet* typeSet, bool setTypeSet)
+GlobOpt::UpdateObjectTypeValue(Value* value, const JITType* type, bool setType, Js::EquivalentTypeSet* typeSet, bool setTypeSet)
 {
     Assert(value->GetValueInfo() != nullptr && value->GetValueInfo()->IsJsType());
     JsTypeValueInfo* valueInfo = value->GetValueInfo()->AsJsType();
@@ -2882,7 +2880,7 @@ GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, Value* value, BasicBlock* b
 }
 
 void
-GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const Js::Type *type, Js::EquivalentTypeSet * typeSet, BasicBlock* block, bool updateExistingValue)
+GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const JITType *type, Js::EquivalentTypeSet * typeSet, BasicBlock* block, bool updateExistingValue)
 {
     if (block == nullptr)
     {
@@ -2893,7 +2891,7 @@ GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const Js::Type *type, Js::E
 }
 
 void
-GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const Js::Type *type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData, bool updateExistingValue)
+GlobOpt::SetObjectTypeFromTypeSym(StackSym *typeSym, const JITType *type, Js::EquivalentTypeSet * typeSet, GlobOptBlockData *blockData, bool updateExistingValue)
 {
     Assert(typeSym != nullptr);
 
@@ -3097,11 +3095,11 @@ GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr)
         return;
     }
     JsTypeValueInfo * typeValueInfo = typeValue->GetValueInfo()->AsJsType();
-    const Js::Type * type = typeValueInfo->GetJsType();
+    const JITType * type = typeValueInfo->GetJsType();
     if (type)
     {
         if (Js::DynamicType::Is(type->GetTypeId()) &&
-            !static_cast<const Js::DynamicType*>(type)->GetTypeHandler()->GetIsLocked())
+            !type->GetTypeHandler()->IsLocked())
         {
             return;
         }
@@ -3114,7 +3112,7 @@ GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr)
         {
             type = typeSet->GetType(i);
             if (Js::DynamicType::Is(type->GetTypeId()) &&
-                !static_cast<const Js::DynamicType*>(type)->GetTypeHandler()->GetIsLocked())
+                !type->GetTypeHandler()->IsLocked())
             {
                 return;
             }

+ 17 - 32
lib/Backend/IR.cpp

@@ -92,7 +92,7 @@ Instr::ChangeEquivalentToMonoTypeCheckBailOut()
     this->SetBailOutKind(IR::EquivalentToMonoTypeCheckBailOutKind(this->GetBailOutKind()));
 }
 
-Js::Var
+intptr_t
 Instr::TryOptimizeInstrWithFixedDataProperty(IR::Instr **pInstr, GlobOpt * globopt)
 {
     IR::Instr *&instr = *pInstr;
@@ -103,7 +103,7 @@ Instr::TryOptimizeInstrWithFixedDataProperty(IR::Instr **pInstr, GlobOpt * globo
     IR::PropertySymOpnd * propSymOpnd = src1->AsSymOpnd()->AsPropertySymOpnd();
     if (propSymOpnd->HasFixedValue() && !propSymOpnd->IsPoly())
     {
-        Js::Var fixedValue = propSymOpnd->GetFieldValueAsFixedData();
+        intptr_t fixedValue = propSymOpnd->GetFieldValueAsFixedData();
         Assert(instr->IsProfiledInstr());
         ValueType valType = instr->AsProfiledInstr()->u.FldInfo().valueType;
         if (fixedValue && ((Js::TaggedInt::Is(fixedValue) && (valType.IsUninitialized() || valType.IsLikelyInt())) || PHASE_ON1(Js::FixDataVarPropsPhase)))
@@ -120,7 +120,7 @@ Instr::TryOptimizeInstrWithFixedDataProperty(IR::Instr **pInstr, GlobOpt * globo
                 instr = instr->ConvertToBailOutInstr(instr, !propSymOpnd->HasEquivalentTypeSet() ? IR::BailOutFailedFixedFieldTypeCheck : IR::BailOutFailedEquivalentFixedFieldTypeCheck);
             }
 
-            IR::Instr* loadInstr = IR::Instr::NewConstantLoad(dataValueDstOpnd, fixedValue, instr->m_func);
+            IR::Instr* loadInstr = IR::Instr::NewConstantLoad(dataValueDstOpnd, (intptr_t)fixedValue, valType, instr->m_func);
 
             OUTPUT_VERBOSE_TRACE(Js::UseFixedDataPropsPhase,
                 L"FixedFields: Replacing the source (fixed Data prop) with property id %s with 0x%x .\n",
@@ -131,7 +131,7 @@ Instr::TryOptimizeInstrWithFixedDataProperty(IR::Instr **pInstr, GlobOpt * globo
             return fixedValue;
         }
     }
-    return nullptr;
+    return 0;
 }
 
 ///----------------------------------------------------------------------------
@@ -3369,14 +3369,7 @@ bool Instr::CallsGetter(IR::PropertySymOpnd* methodOpnd)
         ((this->AsProfiledInstr()->u.FldInfo().flags & Js::FldInfo_FromAccessor) != 0);
 }
 
-IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, Js::Var varConst, Func* func)
-{
-    // TODO: (michhol OOP) remove this function
-    Assert(UNREACHED);
-    return nullptr;
-}
-
-IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, Js::TypeId type, Func* func)
+IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, ValueType type, Func* func)
 {
     IR::Opnd *srcOpnd = nullptr;
     IR::Instr *instr;
@@ -3416,12 +3409,9 @@ IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, J
         }
         else
         {
-            Assert(type < Js::TypeId::TypeIds_Limit);
 
             ValueType valueType;
-            switch (type)
-            {
-            case Js::TypeIds_String:
+            if(type.IsString())
             {
                 srcOpnd = IR::AddrOpnd::New(varConst, IR::AddrOpndKindDynamicVar, func, true);
                 instr = IR::Instr::New(Js::OpCode::LdStr, dstOpnd, srcOpnd, func);
@@ -3433,9 +3423,8 @@ IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, J
                 }
                 dstOpnd->SetValueType(ValueType::String);
                 srcOpnd->SetValueType(ValueType::String);
-                break;
             }
-            case Js::TypeIds_Number:
+            else if(type.IsNumber())
             {
                 // TODO (michhol): OOP JIT. we may need to unbox before sending over const table                
 
@@ -3467,20 +3456,17 @@ IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, J
                     
 #endif
                 }
-                break;
             }
-            case Js::TypeIds_Undefined:
-                valueType = ValueType::Undefined;
-                goto dynamicVar;
-            case Js::TypeIds_Null:
-                valueType = ValueType::Null;
-                goto dynamicVar;
-            case Js::TypeIds_Boolean:
-                valueType = ValueType::Boolean;
-                goto dynamicVar;
-            default:
-                valueType = ValueType::GetObject(ObjectType::Object);
-            dynamicVar:
+            else
+            {
+                if (type.IsUndefined() || type.IsNull() || type.IsBoolean())
+                {
+                    valueType = type;
+                }
+                else
+                {
+                    valueType = ValueType::GetObject(ObjectType::Object);
+                }
                 srcOpnd = IR::AddrOpnd::New(varConst, IR::AddrOpndKindDynamicVar, func, true);
                 instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, func);
                 if (dstOpnd->m_sym->IsSingleDef())
@@ -3489,7 +3475,6 @@ IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, J
                 }
                 dstOpnd->SetValueType(valueType);
                 srcOpnd->SetValueType(valueType);
-                break;
             }
         }
     }

+ 2 - 3
lib/Backend/IR.h

@@ -157,8 +157,7 @@ public:
     static Instr *  New(Js::OpCode opcode, Opnd *dstOpnd, Func *func);
     static Instr *  New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Func *func);
     static Instr *  New(Js::OpCode opcode, Opnd *dstOpnd, Opnd *src1Opnd, Opnd *src2Opnd, Func *func);
-    static Instr*   NewConstantLoad(IR::RegOpnd* dstOpnd, Js::Var varConst, Func *func);
-    static Instr*   NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, Js::TypeId type, Func *func);
+    static Instr*   NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, ValueType type, Func *func);
 
 public:
     bool            IsPlainInstr() const;
@@ -316,7 +315,7 @@ public:
     void            ResetAuxBailOut();
     void            UnlinkStartCallFromBailOutInfo(IR::Instr *endInstr) const;
     void            ChangeEquivalentToMonoTypeCheckBailOut();
-    Js::Var         TryOptimizeInstrWithFixedDataProperty(IR::Instr ** pInstr, GlobOpt* globopt);
+    intptr_t        TryOptimizeInstrWithFixedDataProperty(IR::Instr ** pInstr, GlobOpt* globopt);
     Opnd *          FindCallArgumentOpnd(const Js::ArgSlot argSlot, IR::Instr * *const ownerInstrRef = nullptr);
     void            CopyNumber(IR::Instr *instr) { this->SetNumber(instr->GetNumber()); }
 

+ 7 - 10
lib/Backend/IRBuilder.cpp

@@ -1420,7 +1420,7 @@ IRBuilder::BuildConstantLoads()
         Assert(this->RegIsConstant(reg));
         dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
 
-        IR::Instr *instr = IR::Instr::NewConstantLoad(dstOpnd, varConst, type, m_func);
+        IR::Instr *instr = IR::Instr::NewConstantLoad(dstOpnd, varConst, ValueType::FromTypeId(type, false), m_func);
         this->AddInstr(instr, Js::Constants::NoByteCodeOffset);
     }
 
@@ -2653,7 +2653,7 @@ IRBuilder::BuildUnsigned1(Js::OpCode newOpcode, uint32 offset, uint32 num)
             // See we are ending an outer loop and load the return IP to the ProfiledLoopEnd opcode
             // instead of following the normal branch
 
-            const JITLoopHeader * loopHeader = m_func->GetJITFunctionBody()->GetLoopHeaderData(num);
+            const JITLoopHeaderIDL * loopHeader = m_func->GetJITFunctionBody()->GetLoopHeaderData(num);
             if (m_func->GetJITFunctionBody()->GetLoopHeaderAddr(num) != m_func->m_workItem->GetLoopHeaderAddr() &&
                 JITTimeFunctionBody::LoopContains(loopHeader, m_func->m_workItem->GetLoopHeader()))
             {
@@ -3828,6 +3828,7 @@ IRBuilder::EnsureLoopBodyLoadSlot(SymID symId, bool isCatchObjectSym)
     IR::RegOpnd * dstOpnd = IR::RegOpnd::New(symDst, TyVar, m_func);
     IR::Instr * ldSlotInstr;
 
+#if 0 // OOP JIT, pass over symIdToValueTypeMap
     JsLoopBodyCodeGen* loopBodyCodeGen = (JsLoopBodyCodeGen*)m_func->m_workItem;
 
     ValueType symValueType;
@@ -3837,6 +3838,7 @@ IRBuilder::EnsureLoopBodyLoadSlot(SymID symId, bool isCatchObjectSym)
         ldSlotInstr->AsProfiledInstr()->u.FldInfo().valueType = symValueType;
     }
     else
+#endif
     {
         ldSlotInstr = IR::Instr::New(Js::OpCode::LdSlot, dstOpnd, fieldSymOpnd, m_func);
     }
@@ -7186,19 +7188,14 @@ IRBuilder::BuildAuxArrayOpnd(AuxArrayValue auxArrayType, uint32 offset, uint32 a
     switch (auxArrayType)
     {
     case AuxArrayValue::AuxPropertyIdArray:
-        return IR::AddrOpnd::New((Js::Var)Js::ByteCodeReader::ReadPropertyIdArray(auxArrayOffset, m_func->GetJnFunction(), extraSlots), IR::AddrOpndKindDynamicMisc, m_func);
     case AuxArrayValue::AuxIntArray:
-        return IR::AddrOpnd::New((Js::Var)Js::ByteCodeReader::ReadAuxArray<int32>(auxArrayOffset, m_func->GetJnFunction()), IR::AddrOpndKindDynamicMisc, m_func);
     case AuxArrayValue::AuxFloatArray:
-        return IR::AddrOpnd::New((Js::Var)Js::ByteCodeReader::ReadAuxArray<double>(auxArrayOffset, m_func->GetJnFunction()), IR::AddrOpndKindDynamicMisc, m_func);
     case AuxArrayValue::AuxVarsArray:
-        return IR::AddrOpnd::New((Js::Var)Js::ByteCodeReader::ReadAuxArray<Js::Var>(auxArrayOffset, m_func->GetJnFunction()), IR::AddrOpndKindDynamicMisc, m_func);
-    case AuxArrayValue::AuxVarArrayVarCount:
-        return IR::AddrOpnd::New((Js::Var)Js::ByteCodeReader::ReadVarArrayVarCount(auxArrayOffset, m_func->GetJnFunction()), IR::AddrOpndKindDynamicMisc, m_func);
     case AuxArrayValue::AuxFuncInfoArray:
-        return IR::AddrOpnd::New((Js::Var)Js::ByteCodeReader::ReadAuxArray<Js::FuncInfoEntry>(auxArrayOffset, m_func->GetJnFunction()), IR::AddrOpndKindDynamicMisc, m_func);
+    case AuxArrayValue::AuxVarArrayVarCount:
+        return IR::AddrOpnd::New(m_func->GetJITFunctionBody()->ReadAuxArray(auxArrayOffset), IR::AddrOpndKindDynamicMisc, m_func);
     default:
-        Assert(false);
+        Assert(UNREACHED);
         return nullptr;
     }
 }

+ 2 - 0
lib/Backend/IRBuilderAsmJs.cpp

@@ -2964,6 +2964,7 @@ IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(SymID symId, IRType type)
     StackSym * symDst = StackSym::FindOrCreate(symId, (Js::RegSlot)symId, m_func, fieldSymOpnd->GetType());
     IR::RegOpnd * dstOpnd = IR::RegOpnd::New(symDst, symDst->GetType(), m_func);
     IR::Instr * ldSlotInstr;
+#if 0 // TODO: OOP JIT, symIdToValueTypeMap do we actually need this for asm.js?
     JsLoopBodyCodeGen* loopBodyCodeGen = (JsLoopBodyCodeGen*)m_func->m_workItem;
     ValueType symValueType;
     if (loopBodyCodeGen->symIdToValueTypeMap && loopBodyCodeGen->symIdToValueTypeMap->TryGetValue(symId, &symValueType))
@@ -2972,6 +2973,7 @@ IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(SymID symId, IRType type)
         ldSlotInstr->AsProfiledInstr()->u.FldInfo().valueType = symValueType;
     }
     else
+#endif
     {
         ldSlotInstr = IR::Instr::New(Js::OpCode::LdSlot, dstOpnd, fieldSymOpnd, m_func);
     }

+ 25 - 23
lib/Backend/Inline.cpp

@@ -1164,7 +1164,7 @@ Inline::BuildInlinee(JITTimeFunctionBody* funcBody, const FunctionJITTimeInfo *
     Assert(callInstr->IsProfiledInstr());
     Js::ProfileId callSiteId = static_cast<Js::ProfileId>(callInstr->AsProfiledInstr()->u.profileId);
 
-    CodeGenWorkItemJITData * workItemData = JitAnewStruct(this->topFunc->m_alloc, CodeGenWorkItemJITData);
+    CodeGenWorkItemIDL * workItemData = JitAnewStruct(this->topFunc->m_alloc, CodeGenWorkItemIDL);
 
     workItemData->isJitInDebugMode = this->topFunc->IsJitInDebugMode();
     workItemData->type = JsFunctionType;
@@ -1172,7 +1172,7 @@ Inline::BuildInlinee(JITTimeFunctionBody* funcBody, const FunctionJITTimeInfo *
     workItemData->nativeDataAddr = this->topFunc->GetWorkItem()->GetWorkItemData()->nativeDataAddr;
     workItemData->loopNumber = Js::LoopHeader::NoLoop;
 
-    workItemData->jitData = (FunctionJITTimeData*)(inlineeData);
+    workItemData->jitData = (FunctionJITTimeDataIDL*)(inlineeData);
     JITTimeWorkItem * jitWorkItem = JitAnew(this->topFunc->m_alloc, JITTimeWorkItem, workItemData);
 
     //Js::EntryPointPolymorphicInlineCacheInfo * entryPointPolymorphicInlineCacheInfo = this->topFunc->GetWorkItem()->GetEntryPoint()->GetPolymorphicInlineCacheInfo();
@@ -1463,15 +1463,16 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, const Function
             Js::PropertyRecord const * const methodPropertyRecord = callerFunctionBody->GetScriptContext()->GetPropertyNameLocked(methodPropertyId);
             bool isProto = methodPropertyOpnd->IsLoadedFromProto();
             bool isAccessor = methodPropertyOpnd->UsesAccessor();
-            Js::DynamicObject* protoObject = isProto ? methodPropertyOpnd->GetProtoObject() : nullptr;
             Js::FunctionBody* fixedFunctionBody   = functionObject->GetFunctionInfo()->GetFunctionBody();
             const wchar_t* fixedFunctionNumbers   = fixedFunctionBody ? fixedFunctionBody->GetDebugNumberSet(debugStringBuffer2) : L"(null)";
             JITTimeFunctionBody* profileFunctionBody = inlineeInfo->GetBody();
             const wchar_t* profileFunctionName    = profileFunctionBody != nullptr ? profileFunctionBody->GetDisplayName() : L"<unknown>";
             const wchar_t* profileFunctionNumbers = profileFunctionBody ? inlineeInfo->GetDebugNumberSet(debugStringBuffer3) : L"(null)";
 
+#if 0 // TODO: OOP JIT, protoObject->GetType() ReadProcessMemory?
             if (PHASE_TRACE(Js::FixedMethodsPhase, callInstr->m_func))
             {
+                intptr_t protoObject = isProto ? methodPropertyOpnd->GetProtoObject() : 0;
                 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),
                     methodPropertyRecord->GetBuffer(), fixedFunctionNumbers, functionObject, functionObject->GetFunctionInfo(),
@@ -1479,6 +1480,7 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, const Function
                     methodPropertyOpnd->m_inlineCacheIndex, isProto ? L"proto" : isAccessor ? L"accessor" : L"local",
                     methodPropertyOpnd->GetType(), protoObject, protoObject != nullptr ? protoObject->GetType() : nullptr);
             }
+#endif
             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",
@@ -1549,7 +1551,7 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, const Function
 
     if (isCtor)
     {
-        Js::JitTimeConstructorCache* constructorCache = methodPropertyOpnd->GetCtorCache();
+        JITTimeConstructorCache* constructorCache = methodPropertyOpnd->GetCtorCache();
         if (constructorCache != nullptr && callInstr->IsProfiledInstr())
         {
 
@@ -1568,7 +1570,7 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, const Function
                     callerFunctionBody->GetDisplayName(), callerFunctionBody->GetDebugNumberSet(debugStringBuffer), Js::OpCodeUtil::GetOpCodeName(callInstr->m_opcode),
                     inlineeInfo != nullptr ? L"inlined" : L"called",
                     methodPropertyRecord->GetBuffer(), fixedFunctionName, fixedFunctionNumbers,
-                    constructorCache->skipNewScObject ? L" skip default object" : L"");
+                    constructorCache->SkipNewScObject() ? L" skip default object" : L"");
                 Output::Flush();
             }
 #endif
@@ -1578,15 +1580,15 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, const Function
             {
                 // Because we are storing flow sensitive info in the cache (guarded property operations),
                 // we must make sure the same cache cannot be used multiple times in the flow.
-                if (constructorCache->isUsed)
+                if (constructorCache->IsUsed())
                 {
                     // It's okay to allocate a JitTimeConstructorCache from the func's allocator (rather than recycler),
                     // because we only use these during JIT. We use the underlying runtime cache as a guard that must
                     // live after JIT, and these are added to the EntryPointInfo during work item creation and thus kept alive.
                     constructorCache = constructorCache->Clone(this->topFunc->m_alloc);
                 }
-                Assert(!constructorCache->isUsed);
-                constructorCache->isUsed = true;
+                Assert(!constructorCache->IsUsed());
+                constructorCache->SetUsed(true);
                 callInstr->m_func->SetConstructorCache(static_cast<Js::ProfileId>(callInstr->AsProfiledInstr()->u.profileId), constructorCache);
             }
         }
@@ -1652,22 +1654,22 @@ Inline::TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, const Function
     return true;
 }
 
-Js::Var
+intptr_t
 Inline::TryOptimizeInstrWithFixedDataProperty(IR::Instr *&instr)
 {
     if (PHASE_OFF(Js::UseFixedDataPropsPhase, instr->m_func) ||
         PHASE_OFF(Js::UseFixedDataPropsInInlinerPhase, instr->m_func))
     {
-        return nullptr;
+        return 0;
     }
     if (!instr->IsProfiledInstr() ||
         !instr->GetSrc1()->IsSymOpnd() || !instr->GetSrc1()->AsSymOpnd()->IsPropertySymOpnd())
     {
-        return nullptr;
+        return 0;
     }
     if (!OpCodeAttr::CanLoadFixedFields(instr->m_opcode))
     {
-        return nullptr;
+        return 0;
     }
     return instr->TryOptimizeInstrWithFixedDataProperty(&instr, nullptr);
 }
@@ -1817,7 +1819,7 @@ Inline::InlineBuiltInFunction(IR::Instr *callInstr, const FunctionJITTimeInfo *
         return callInstr->m_next;
     }
 
-    if (inlineCallOpCode == Js::OpCode::InlineFunctionApply && (!callInstr->m_func->GetHasStackArgs() || this->topFunc->GetJnFunction()->IsInlineApplyDisabled()))
+    if (inlineCallOpCode == Js::OpCode::InlineFunctionApply && (!callInstr->m_func->GetHasStackArgs() || this->topFunc->GetJITFunctionBody()->IsInlineApplyDisabled()))
     {
         INLINE_TESTTRACE(L"INLINING: Skip Inline: stack args of inlining is off\tInlinee: %s (#%d)\tCaller: %s (%s)\n",
             Js::JavascriptLibrary::GetNameForBuiltIn(builtInId), (int)builtInId,
@@ -2611,7 +2613,7 @@ Inline::InlineCallApplyTarget_Shared(IR::Instr *callInstr, StackSym* originalCal
     Js::ProfileId callSiteId = static_cast<Js::ProfileId>(callInstr->AsProfiledInstr()->u.profileId);
 
     // inlinee
-    CodeGenWorkItemJITData * workItemData = JitAnewStruct(this->topFunc->m_alloc, CodeGenWorkItemJITData);
+    CodeGenWorkItemIDL * workItemData = JitAnewStruct(this->topFunc->m_alloc, CodeGenWorkItemIDL);
 
     workItemData->isJitInDebugMode = this->topFunc->IsJitInDebugMode();
     workItemData->type = JsFunctionType;
@@ -2619,7 +2621,7 @@ Inline::InlineCallApplyTarget_Shared(IR::Instr *callInstr, StackSym* originalCal
     workItemData->nativeDataAddr = this->topFunc->GetWorkItem()->GetWorkItemData()->nativeDataAddr;
     workItemData->loopNumber = Js::LoopHeader::NoLoop;
 
-    workItemData->jitData = (FunctionJITTimeData*)(inlineeData);
+    workItemData->jitData = (FunctionJITTimeDataIDL*)(inlineeData);
     JITTimeWorkItem * jitWorkItem = JitAnew(this->topFunc->m_alloc, JITTimeWorkItem, workItemData);
 
     //Js::EntryPointPolymorphicInlineCacheInfo * entryPointPolymorphicInlineCacheInfo = this->topFunc->GetWorkItem()->GetEntryPoint()->GetPolymorphicInlineCacheInfo();
@@ -3352,7 +3354,7 @@ Inline::InlineGetterSetterFunction(IR::Instr *accessorInstr, const FunctionJITTi
     }
 
     // inlinee
-    CodeGenWorkItemJITData * workItemData = JitAnewStruct(this->topFunc->m_alloc, CodeGenWorkItemJITData);
+    CodeGenWorkItemIDL * workItemData = JitAnewStruct(this->topFunc->m_alloc, CodeGenWorkItemIDL);
 
     workItemData->isJitInDebugMode = this->topFunc->IsJitInDebugMode();
     workItemData->type = JsFunctionType;
@@ -3360,7 +3362,7 @@ Inline::InlineGetterSetterFunction(IR::Instr *accessorInstr, const FunctionJITTi
     workItemData->nativeDataAddr = this->topFunc->GetWorkItem()->GetWorkItemData()->nativeDataAddr;
     workItemData->loopNumber = Js::LoopHeader::NoLoop;
 
-    workItemData->jitData = (FunctionJITTimeData*)(inlineeData);
+    workItemData->jitData = (FunctionJITTimeDataIDL*)(inlineeData);
     JITTimeWorkItem * jitWorkItem = JitAnew(this->topFunc->m_alloc, JITTimeWorkItem, workItemData);
 
     //Js::EntryPointPolymorphicInlineCacheInfo * entryPointPolymorphicInlineCacheInfo = this->topFunc->GetWorkItem()->GetEntryPoint()->GetPolymorphicInlineCacheInfo();
@@ -3660,7 +3662,7 @@ Inline::InlineScriptFunction(IR::Instr *callInstr, const FunctionJITTimeInfo *co
         returnRegSlot = Js::Constants::NoRegister;
     }
 
-    CodeGenWorkItemJITData * workItemData = JitAnewStruct(this->topFunc->m_alloc, CodeGenWorkItemJITData);
+    CodeGenWorkItemIDL * workItemData = JitAnewStruct(this->topFunc->m_alloc, CodeGenWorkItemIDL);
 
     workItemData->isJitInDebugMode = this->topFunc->IsJitInDebugMode();
     workItemData->type = JsFunctionType;
@@ -3668,7 +3670,7 @@ Inline::InlineScriptFunction(IR::Instr *callInstr, const FunctionJITTimeInfo *co
     workItemData->nativeDataAddr = this->topFunc->GetWorkItem()->GetWorkItemData()->nativeDataAddr;
     workItemData->loopNumber = Js::LoopHeader::NoLoop;
 
-    workItemData->jitData = (FunctionJITTimeData*)(inlineeData);
+    workItemData->jitData = (FunctionJITTimeDataIDL*)(inlineeData);
     JITTimeWorkItem * jitWorkItem = JitAnew(this->topFunc->m_alloc, JITTimeWorkItem, workItemData);
 
     //Js::EntryPointPolymorphicInlineCacheInfo * entryPointPolymorphicInlineCacheInfo = this->topFunc->GetWorkItem()->GetEntryPoint()->GetPolymorphicInlineCacheInfo();
@@ -3742,7 +3744,7 @@ Inline::SplitConstructorCallCommon(
     // object allocation (bytecode instruction has the form [Profiled]NewScObject R6 = R6).
     IR::RegOpnd* createObjDst = nullptr;
     IR::Instr* createObjInstr = nullptr;
-    const Js::JitTimeConstructorCache* constructorCache;
+    const JITTimeConstructorCache* constructorCache;
     bool returnCreatedObject = false;
     bool skipNewScObj = false;
 
@@ -3750,8 +3752,8 @@ Inline::SplitConstructorCallCommon(
     {
         Js::ProfileId profiledCallSiteId = static_cast<Js::ProfileId>(newObjInstr->AsProfiledInstr()->u.profileId);
         constructorCache = newObjInstr->m_func->GetConstructorCache(profiledCallSiteId);
-        returnCreatedObject = constructorCache != nullptr && constructorCache->ctorHasNoExplicitReturnValue;
-        skipNewScObj = constructorCache != nullptr && constructorCache->skipNewScObject;
+        returnCreatedObject = constructorCache != nullptr && constructorCache->CtorHasNoExplicitReturnValue();
+        skipNewScObj = constructorCache != nullptr && constructorCache->SkipNewScObject();
         if (!skipNewScObj)
         {
             createObjDst = IR::RegOpnd::New(TyVar, callerFunc);
@@ -4097,7 +4099,7 @@ bool Inline::InlConstFold(IR::Instr *instr, IntConstType *pValue, __in_ecount_op
         else if (src1->AsSymOpnd()->IsPropertySymOpnd())
         {
             // See if we have a LdFld of a fixed field.
-            Js::Var var = TryOptimizeInstrWithFixedDataProperty(instr);
+            intptr_t var = TryOptimizeInstrWithFixedDataProperty(instr);
             if (!Js::TaggedInt::Is(var))
             {
                 return false;

+ 1 - 1
lib/Backend/Inline.h

@@ -35,7 +35,7 @@ private:
     void Optimize(Func *func, __in_ecount_opt(actuals) IR::Instr *argOuts[] = NULL, Js::ArgSlot actuals = (Js::ArgSlot) - 1, uint recursiveInlineDepth = 0);
     bool TryOptimizeCallInstrWithFixedMethod(IR::Instr *callInstr, const FunctionJITTimeInfo * inlineeInfo, bool isPolymorphic, bool isBuiltIn, bool isCtor, bool isInlined, bool& safeThis,
                                             bool dontOptimizeJustCheck = false, uint i = 0 /*i-th inlinee at a polymorphic call site*/);
-    Js::Var TryOptimizeInstrWithFixedDataProperty(IR::Instr *&instr);
+    intptr_t TryOptimizeInstrWithFixedDataProperty(IR::Instr *&instr);
     IR::Instr * InlineScriptFunction(IR::Instr *callInstr, const FunctionJITTimeInfo *const inlineeData, const StackSym *symThis, const Js::ProfileId profileId, bool* pIsInlined, uint recursiveInlineDepth);
 #ifdef ENABLE_DOM_FAST_PATH
     IR::Instr * InlineDOMGetterSetterFunction(IR::Instr *ldFldInstr, const FunctionJITTimeInfo *const inlineeData, const FunctionJITTimeInfo *const inlinerData);

+ 224 - 0
lib/Backend/JITObjTypeSpecFldInfo.cpp

@@ -0,0 +1,224 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+#include "Backend.h"
+
+JITObjTypeSpecFldInfo::JITObjTypeSpecFldInfo(ObjTypeSpecFldIDL * data) :
+    m_data(*data)
+{
+    CompileAssert(sizeof(ObjTypeSpecFldIDL) == sizeof(JITObjTypeSpecFldInfo));
+}
+
+bool
+JITObjTypeSpecFldInfo::UsesAuxSlot() const
+{
+    return GetFlags().usesAuxSlot;
+}
+
+bool
+JITObjTypeSpecFldInfo::UsesAccessor() const
+{
+    return GetFlags().usesAccessor;
+}
+
+bool
+JITObjTypeSpecFldInfo::IsRootObjectNonConfigurableFieldLoad() const
+{
+    return GetFlags().isRootObjectNonConfigurableFieldLoad;
+}
+
+bool
+JITObjTypeSpecFldInfo::HasEquivalentTypeSet() const
+{
+    return m_data.typeSet != nullptr;
+}
+
+bool
+JITObjTypeSpecFldInfo::DoesntHaveEquivalence() const
+{
+    return GetFlags().doesntHaveEquivalence;
+}
+
+bool
+JITObjTypeSpecFldInfo::IsPoly() const
+{
+    return GetFlags().isPolymorphic;
+}
+
+bool
+JITObjTypeSpecFldInfo::IsMono() const
+{
+    return !IsPoly();
+}
+
+bool
+JITObjTypeSpecFldInfo::IsBuiltIn() const
+{
+    return GetFlags().isBuiltIn;
+}
+
+bool
+JITObjTypeSpecFldInfo::IsLoadedFromProto() const
+{
+    return GetFlags().isLoadedFromProto;
+}
+
+bool
+JITObjTypeSpecFldInfo::HasFixedValue() const
+{
+    return GetFlags().hasFixedValue;
+}
+
+bool
+JITObjTypeSpecFldInfo::IsBeingStored() const
+{
+    return GetFlags().isBeingStored;
+}
+
+bool
+JITObjTypeSpecFldInfo::IsBeingAdded() const
+{
+    return GetFlags().isBeingAdded;
+}
+
+bool
+JITObjTypeSpecFldInfo::IsRootObjectNonConfigurableField() const
+{
+    return GetFlags().isRootObjectNonConfigurableField;
+}
+
+bool
+JITObjTypeSpecFldInfo::HasInitialType() const
+{
+    return IsMono() && !IsLoadedFromProto() && m_data.initialType != nullptr;
+}
+
+bool
+JITObjTypeSpecFldInfo::IsMonoObjTypeSpecCandidate() const
+{
+    return IsMono();
+}
+
+bool
+JITObjTypeSpecFldInfo::IsPolyObjTypeSpecCandidate() const
+{
+    return IsPoly();
+}
+
+Js::TypeId
+JITObjTypeSpecFldInfo::GetTypeId() const
+{
+    Assert(m_data.typeId != Js::TypeIds_Limit);
+    return (Js::TypeId)m_data.typeId;
+}
+
+Js::TypeId
+JITObjTypeSpecFldInfo::GetTypeId(uint i) const
+{
+    Assert(IsPoly());
+    return (Js::TypeId)m_data.fixedFieldInfoArray[i].type.typeId;
+}
+
+Js::PropertyId
+JITObjTypeSpecFldInfo::GetPropertyId() const
+{
+    return (Js::PropertyId)m_data.propertyId;
+}
+
+uint16
+JITObjTypeSpecFldInfo::GetSlotIndex() const
+{
+    return m_data.slotIndex;
+}
+
+uint16
+JITObjTypeSpecFldInfo::GetFixedFieldCount() const
+{
+    return m_data.fixedFieldCount;
+}
+
+uint
+JITObjTypeSpecFldInfo::GetObjTypeSpecFldId() const
+{
+    return m_data.id;
+}
+
+intptr_t
+JITObjTypeSpecFldInfo::GetProtoObject() const
+{
+    return m_data.protoObjectAddr;
+}
+
+intptr_t
+JITObjTypeSpecFldInfo::GetFieldValue(uint i) const
+{
+    Assert(IsPoly());
+    return m_data.fixedFieldInfoArray[i].fieldValue;
+}
+
+intptr_t
+JITObjTypeSpecFldInfo::GetPropertyGuardValueAddr() const
+{
+    return m_data.propertyGuardValueAddr;
+}
+
+intptr_t
+JITObjTypeSpecFldInfo::GetFieldValueAsFixedDataIfAvailable() const
+{
+    Assert(HasFixedValue() && GetFixedFieldCount() == 1);
+
+    return m_data.fixedFieldInfoArray[0].fieldValue;
+}
+
+JITTimeConstructorCache *
+JITObjTypeSpecFldInfo::GetCtorCache() const
+{
+    return (JITTimeConstructorCache*)m_data.ctorCache;
+}
+
+Js::EquivalentTypeSet *
+JITObjTypeSpecFldInfo::GetEquivalentTypeSet() const
+{
+    return (Js::EquivalentTypeSet *)m_data.typeSet;
+}
+
+JITType *
+JITObjTypeSpecFldInfo::GetType() const
+{
+    Assert(IsMono());
+    return (JITType *)&m_data.fixedFieldInfoArray[0].type;
+}
+
+JITType *
+JITObjTypeSpecFldInfo::GetType(uint i) const
+{
+    Assert(IsPoly());
+    return (JITType *)&m_data.fixedFieldInfoArray[i].type;
+}
+
+JITType *
+JITObjTypeSpecFldInfo::GetInitialType() const
+{
+    return (JITType *)m_data.initialType;
+}
+
+JITType *
+JITObjTypeSpecFldInfo::GetFirstEquivalentType() const
+{
+    Assert(HasEquivalentTypeSet());
+    return GetEquivalentTypeSet()->GetFirstType();
+}
+
+void
+JITObjTypeSpecFldInfo::SetIsBeingStored(bool value)
+{
+    ((Js::ObjTypeSpecFldInfoFlags*)&m_data.flags)->isBeingStored = true;
+}
+
+Js::ObjTypeSpecFldInfoFlags
+JITObjTypeSpecFldInfo::GetFlags() const
+{
+    return (Js::ObjTypeSpecFldInfoFlags)m_data.flags;
+}

+ 62 - 0
lib/Backend/JITObjTypeSpecFldInfo.h

@@ -0,0 +1,62 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+#pragma once
+
+class JITObjTypeSpecFldInfo
+{
+public:
+    JITObjTypeSpecFldInfo::JITObjTypeSpecFldInfo(ObjTypeSpecFldIDL * data);
+    bool UsesAuxSlot() const;
+    bool UsesAccessor() const;
+    bool IsRootObjectNonConfigurableFieldLoad() const;
+    bool HasEquivalentTypeSet() const;
+    bool DoesntHaveEquivalence() const;
+    bool IsPoly() const;
+    bool IsMono() const;
+    bool IsBuiltIn() const;
+    bool IsLoadedFromProto() const;
+    bool HasFixedValue() const;
+    bool IsBeingStored() const;
+    bool IsBeingAdded() const;
+    bool IsRootObjectNonConfigurableField() const;
+    bool HasInitialType() const;
+    bool IsMonoObjTypeSpecCandidate() const;
+    bool IsPolyObjTypeSpecCandidate() const;
+
+    Js::TypeId GetTypeId() const;
+    Js::TypeId GetTypeId(uint i) const;
+
+    Js::PropertyId GetPropertyId() const;
+    uint16 GetSlotIndex() const;
+    uint16 GetFixedFieldCount() const;
+
+    uint GetObjTypeSpecFldId() const;
+
+    intptr_t GetProtoObject() const;
+    intptr_t GetFieldValue(uint i) const;
+    intptr_t GetPropertyGuardValueAddr() const;
+    intptr_t GetFieldValueAsFixedDataIfAvailable() const;
+
+    JITTimeConstructorCache * GetCtorCache() const;
+
+    Js::EquivalentTypeSet * GetEquivalentTypeSet() const;
+    JITType * GetType() const;
+    JITType * GetType(uint i) const;
+    JITType * GetInitialType() const;
+    JITType * GetFirstEquivalentType() const;
+
+    void SetIsBeingStored(bool value); // REVIEW: this doesn't flow out of JIT, should it?
+
+    // TODO: OOP JIT, implement this
+    Js::JavascriptFunction * GetFieldValueAsFixedFunctionIfAvailable() { __debugbreak(); return nullptr; }
+    Js::JavascriptFunction * GetFieldValueAsFixedFunctionIfAvailable(uint i) { __debugbreak(); return nullptr; }
+    wchar_t* GetCacheLayoutString() { __debugbreak(); return nullptr; }
+    Js::FixedFieldInfo * GetFixedFieldInfoArray() { __debugbreak(); return nullptr; }
+private:
+    Js::ObjTypeSpecFldInfoFlags GetFlags() const;
+
+    ObjTypeSpecFldIDL m_data;
+};

+ 2 - 2
lib/Backend/JITOutput.cpp

@@ -5,7 +5,7 @@
 
 #include "Backend.h"
 
-JITOutput::JITOutput(JITOutputData * outputData) :
+JITOutput::JITOutput(JITOutputIDL * outputData) :
     m_outputData(outputData)
 {
     m_outputData->writeableEPData.hasJittedStackClosure = false;
@@ -142,7 +142,7 @@ JITOutput::FinalizeNativeCode(Func *func, EmitBufferAllocation * alloc)
     func->GetEmitBufferManager()->CompletePreviousAllocation(alloc);
 }
 
-JITOutputData *
+JITOutputIDL *
 JITOutput::GetOutputData()
 {
     return m_outputData;

+ 3 - 3
lib/Backend/JITOutput.h

@@ -8,7 +8,7 @@
 class JITOutput
 {
 public:
-    JITOutput(JITOutputData * outputData);
+    JITOutput(JITOutputIDL * outputData);
 
     void SetHasJITStackClosure();
 
@@ -31,7 +31,7 @@ public:
 
     void FinalizeNativeCode(Func *func, EmitBufferAllocation * alloc);
 
-    JITOutputData * GetOutputData();
+    JITOutputIDL * GetOutputData();
 private:
-    JITOutputData * m_outputData;
+    JITOutputIDL * m_outputData;
 };

+ 143 - 0
lib/Backend/JITTimeConstructorCache.cpp

@@ -0,0 +1,143 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+#include "Backend.h"
+
+JITTimeConstructorCache::JITTimeConstructorCache(const Js::JavascriptFunction* constructor, Js::ConstructorCache* runtimeCache)
+{
+    Assert(constructor != nullptr);
+    Assert(runtimeCache != nullptr);
+    m_data.runtimeCacheAddr = (intptr_t)runtimeCache;
+    m_data.runtimeCacheGuardAddr = (intptr_t)runtimeCache->GetAddressOfGuardValue();
+    m_data.slotCount = runtimeCache->content.slotCount;
+    m_data.inlineSlotCount = runtimeCache->content.inlineSlotCount;
+    m_data.skipNewScObject = runtimeCache->content.skipDefaultNewObject;
+    m_data.ctorHasNoExplicitReturnValue = runtimeCache->content.ctorHasNoExplicitReturnValue;
+    m_data.typeIsFinal = runtimeCache->content.typeIsFinal;
+    m_data.isUsed = false;
+
+    if (runtimeCache->IsNormal())
+    {
+        JITType::BuildFromJsType(runtimeCache->content.type, (JITType*)&m_data.type);
+    }
+}
+
+JITTimeConstructorCache::JITTimeConstructorCache(const JITTimeConstructorCache* other)
+{
+    Assert(other != nullptr);
+    Assert(other->GetRuntimeCacheAddr() != 0);
+    m_data.runtimeCacheAddr = other->GetRuntimeCacheAddr();
+    m_data.runtimeCacheGuardAddr = other->GetRuntimeCacheGuardAddr();
+    m_data.type = *(TypeIDL*)other->GetType();
+    m_data.slotCount = other->GetSlotCount();
+    m_data.inlineSlotCount = other->GetInlineSlotCount();
+    m_data.skipNewScObject = other->SkipNewScObject();
+    m_data.ctorHasNoExplicitReturnValue = other->CtorHasNoExplicitReturnValue();
+    m_data.typeIsFinal = other->IsTypeFinal();
+    m_data.isUsed = false;
+}
+
+JITTimeConstructorCache*
+JITTimeConstructorCache::Clone(JitArenaAllocator* allocator) const
+{
+    JITTimeConstructorCache* clone = Anew(allocator, JITTimeConstructorCache, this);
+    return clone;
+}
+const BVSparse<JitArenaAllocator>*
+JITTimeConstructorCache::GetGuardedPropOps() const
+{
+    return m_guardedPropOps;
+}
+
+void
+JITTimeConstructorCache::EnsureGuardedPropOps(JitArenaAllocator* allocator)
+{
+    if (m_guardedPropOps == nullptr)
+    {
+        m_guardedPropOps = Anew(allocator, BVSparse<JitArenaAllocator>, allocator);
+    }
+}
+
+void
+JITTimeConstructorCache::SetGuardedPropOp(uint propOpId)
+{
+    Assert(m_guardedPropOps != nullptr);
+    m_guardedPropOps->Set(propOpId);
+}
+
+void
+JITTimeConstructorCache::AddGuardedPropOps(const BVSparse<JitArenaAllocator>* propOps)
+{
+    Assert(m_guardedPropOps != nullptr);
+    m_guardedPropOps->Or(propOps);
+}
+
+intptr_t
+JITTimeConstructorCache::GetRuntimeCacheAddr() const
+{
+    return m_data.runtimeCacheAddr;
+}
+
+intptr_t
+JITTimeConstructorCache::GetRuntimeCacheGuardAddr() const
+{
+    return m_data.runtimeCacheGuardAddr;
+}
+
+JITType *
+JITTimeConstructorCache::GetType() const
+{
+    return (JITType*)&m_data.type;
+}
+
+int
+JITTimeConstructorCache::GetSlotCount() const
+{
+    return m_data.slotCount;
+}
+
+int16
+JITTimeConstructorCache::GetInlineSlotCount() const
+{
+    return m_data.inlineSlotCount;
+}
+
+bool
+JITTimeConstructorCache::SkipNewScObject() const
+{
+    return m_data.skipNewScObject != FALSE;
+}
+
+bool
+JITTimeConstructorCache::CtorHasNoExplicitReturnValue() const
+{
+    return m_data.ctorHasNoExplicitReturnValue != FALSE;
+}
+
+bool
+JITTimeConstructorCache::IsTypeFinal() const
+{
+    return m_data.typeIsFinal != FALSE;
+}
+
+bool
+JITTimeConstructorCache::IsUsed() const
+{
+    return m_data.isUsed != FALSE;
+}
+
+// TODO: OOP JIT, does this need to flow back?
+void
+JITTimeConstructorCache::SetUsed(bool val)
+{
+    m_data.isUsed = val;
+}
+
+JITTimeConstructorCacheIDL *
+JITTimeConstructorCache::GetData()
+{
+    return &m_data;
+}
+

+ 37 - 0
lib/Backend/JITTimeConstructorCache.h

@@ -0,0 +1,37 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+#pragma once
+
+class JITTimeConstructorCache
+{
+public:
+    JITTimeConstructorCache(const Js::JavascriptFunction* constructor, Js::ConstructorCache* runtimeCache);
+    JITTimeConstructorCache(const JITTimeConstructorCache* other);
+
+    JITTimeConstructorCache* Clone(JitArenaAllocator* allocator) const;
+    const BVSparse<JitArenaAllocator>* GetGuardedPropOps() const;
+    void EnsureGuardedPropOps(JitArenaAllocator* allocator);
+    void SetGuardedPropOp(uint propOpId);
+    void AddGuardedPropOps(const BVSparse<JitArenaAllocator>* propOps);
+
+    intptr_t GetRuntimeCacheAddr() const;
+    intptr_t GetRuntimeCacheGuardAddr() const;
+    JITType * GetType() const;
+    int GetSlotCount() const;
+    int16 GetInlineSlotCount() const;
+    bool SkipNewScObject() const;
+    bool CtorHasNoExplicitReturnValue() const;
+    bool IsTypeFinal() const;
+    bool IsUsed() const;
+    void SetUsed(bool val);
+
+    JITTimeConstructorCacheIDL * GetData();
+
+private:
+    JITTimeConstructorCacheIDL m_data;
+    BVSparse<JitArenaAllocator> * m_guardedPropOps;
+};
+
+#pragma once

+ 25 - 7
lib/Backend/JITTimeFunctionBody.cpp

@@ -5,10 +5,10 @@
 
 #include "Backend.h"
 
-JITTimeFunctionBody::JITTimeFunctionBody(FunctionBodyJITData * bodyData) :
+JITTimeFunctionBody::JITTimeFunctionBody(FunctionBodyDataIDL * bodyData) :
     m_bodyData(*bodyData)
 {
-    CompileAssert(sizeof(JITTimeFunctionBody) == sizeof(FunctionBodyJITData));
+    CompileAssert(sizeof(JITTimeFunctionBody) == sizeof(FunctionBodyDataIDL));
 }
 
 /* static */
@@ -16,7 +16,7 @@ void
 JITTimeFunctionBody::InitializeJITFunctionData(
     __in Recycler * recycler,
     __in Js::FunctionBody *functionBody,
-    __out FunctionBodyJITData * jitBody)
+    __out FunctionBodyDataIDL * jitBody)
 {
     Assert(functionBody != nullptr);
 
@@ -111,7 +111,7 @@ JITTimeFunctionBody::InitializeJITFunctionData(
     {
         jitBody->loopHeaderArrayAddr = (intptr_t)functionBody->GetLoopHeaderArrayPtr();
         jitBody->loopHeaderArrayLength = functionBody->GetLoopCount();
-        jitBody->loopHeaders = RecyclerNewArray(recycler, JITLoopHeader, functionBody->GetLoopCount());
+        jitBody->loopHeaders = RecyclerNewArray(recycler, JITLoopHeaderIDL, functionBody->GetLoopCount());
         for (uint i = 0; i < functionBody->GetLoopCount(); ++i)
         {
             jitBody->loopHeaders[i].startOffset = functionBody->GetLoopHeader(i)->startOffset;
@@ -149,6 +149,7 @@ JITTimeFunctionBody::InitializeJITFunctionData(
     jitBody->isStrictMode = functionBody->GetIsStrictMode();
     jitBody->isEval = functionBody->IsEval();
     jitBody->isGlobalFunc = functionBody->GetIsGlobalFunc();
+    jitBody->isInlineApplyDisabled = functionBody->IsInlineApplyDisabled();
     jitBody->doJITLoopBody = functionBody->DoJITLoopBody();
     jitBody->hasScopeObject = functionBody->HasScopeObject();
     jitBody->hasImplicitArgIns = functionBody->GetHasImplicitArgIns();
@@ -171,10 +172,11 @@ JITTimeFunctionBody::InitializeJITFunctionData(
 
     jitBody->nameLength = functionBody->GetDisplayNameLength();
     jitBody->displayName = (wchar_t *)functionBody->GetDisplayName();
+    jitBody->auxArrayBufferAddr = (intptr_t)(functionBody->GetAuxiliaryData() ? functionBody->GetAuxiliaryData()->GetBuffer() : nullptr);
 
     if (functionBody->GetIsAsmJsFunction())
     {
-        jitBody->asmJsData = RecyclerNew(recycler, AsmJsJITData);
+        jitBody->asmJsData = RecyclerNew(recycler, AsmJsDataIDL);
         Js::AsmJsFunctionInfo * asmFuncInfo = functionBody->GetAsmJsFunctionInfo();
         jitBody->asmJsData->intConstCount = asmFuncInfo->GetIntConstCount();
         jitBody->asmJsData->doubleConstCount = asmFuncInfo->GetDoubleConstCount();
@@ -550,6 +552,12 @@ JITTimeFunctionBody::IsGlobalFunc() const
     return m_bodyData.isGlobalFunc != FALSE;
 }
 
+bool
+JITTimeFunctionBody::IsInlineApplyDisabled() const
+{
+    return m_bodyData.isInlineApplyDisabled != FALSE;
+}
+
 bool
 JITTimeFunctionBody::IsNonTempLocalVar(uint32 varIndex) const
 {
@@ -722,7 +730,7 @@ JITTimeFunctionBody::GetLoopHeaderAddr(uint loopNum) const
     return baseAddr + (loopNum * sizeof(Js::LoopHeader));
 }
 
-const JITLoopHeader *
+const JITLoopHeaderIDL *
 JITTimeFunctionBody::GetLoopHeaderData(uint loopNum) const
 {
     Assert(loopNum < GetLoopCount());
@@ -749,7 +757,7 @@ JITTimeFunctionBody::HasProfileInfo() const
 
 /* static */
 bool
-JITTimeFunctionBody::LoopContains(const JITLoopHeader * loop1, const JITLoopHeader * loop2)
+JITTimeFunctionBody::LoopContains(const JITLoopHeaderIDL * loop1, const JITLoopHeaderIDL * loop2)
 {
     return (loop1->startOffset <= loop2->startOffset && loop2->endOffset <= loop1->endOffset);
 }
@@ -784,6 +792,16 @@ JITTimeFunctionBody::GetLdFldInlineeRuntimeData(const Js::InlineCacheIndex inlin
     return data != nullptr ? &data[inlineCacheIndex] : nullptr;
 }
 
+intptr_t
+JITTimeFunctionBody::ReadAuxArray(uint offset) const
+{
+    intptr_t auxArray = m_bodyData.auxArrayBufferAddr + offset;
+    // TODO: OOP JIT, add this assert back
+    //Assert(offset + auxArray->GetDataSize() <= functionBody->GetAuxiliaryData()->GetLength());
+    return auxArray;
+}
+
+
 void
 JITTimeFunctionBody::InitializeStatementMap(__out Js::SmallSpanSequence * statementMap) const
 {

+ 7 - 5
lib/Backend/JITTimeFunctionBody.h

@@ -13,12 +13,12 @@ class FunctionJITRuntimeInfo;
 class JITTimeFunctionBody
 {
 public:
-    JITTimeFunctionBody(FunctionBodyJITData * bodyData);
+    JITTimeFunctionBody(FunctionBodyDataIDL * bodyData);
 
     static void InitializeJITFunctionData(
         __in Recycler * recycler,
         __in Js::FunctionBody * functionBody,
-        __out FunctionBodyJITData * jitBody);
+        __out FunctionBodyDataIDL * jitBody);
 
     intptr_t GetAddr() const;
 
@@ -76,6 +76,7 @@ public:
     bool HasInlineCachesOnFunctionObject() const;
     bool DoInterruptProbe() const;
     bool IsGlobalFunc() const;
+    bool IsInlineApplyDisabled() const;
     bool IsNonTempLocalVar(uint32 varIndex) const;
     bool DoJITLoopBody() const;
     bool IsInlineSpreadDisabled() const;
@@ -96,7 +97,7 @@ public:
 
     intptr_t GetRootObject() const;
     intptr_t GetLoopHeaderAddr(uint loopNum) const;
-    const JITLoopHeader * GetLoopHeaderData(uint loopNum) const;
+    const JITLoopHeaderIDL * GetLoopHeaderData(uint loopNum) const;
 
     intptr_t GetScriptIdAddr() const;
     intptr_t GetProbeCountAddr() const;
@@ -109,10 +110,11 @@ public:
     const JITTimeProfileInfo * GetProfileInfo() const;
     bool HasProfileInfo() const;
 
-    static bool LoopContains(const JITLoopHeader * loop1, const JITLoopHeader * loop2);
+    static bool LoopContains(const JITLoopHeaderIDL * loop1, const JITLoopHeaderIDL * loop2);
 
     wchar_t* GetDisplayName() const;
 
+    intptr_t ReadAuxArray(uint offset) const;
     const FunctionJITRuntimeInfo *GetInlineeRuntimeData(const Js::ProfileId profiledCallSiteId) const;
     const FunctionJITRuntimeInfo *GetLdFldInlineeRuntimeData(const Js::InlineCacheIndex inlineCacheIndex) const;
 
@@ -121,5 +123,5 @@ private:
     Js::FunctionInfo::Attributes GetAttributes() const;
     Js::FunctionBody::FunctionBodyFlags GetFlags() const;
 
-    FunctionBodyJITData m_bodyData;
+    FunctionBodyDataIDL m_bodyData;
 };

+ 25 - 17
lib/Backend/JITTimeProfileInfo.cpp

@@ -5,10 +5,10 @@
 
 #include "BackEnd.h"
 
-JITTimeProfileInfo::JITTimeProfileInfo(ProfileData * profileData) :
+JITTimeProfileInfo::JITTimeProfileInfo(ProfileDataIDL * profileData) :
     m_profileData(*profileData)
 {
-    CompileAssert(sizeof(JITTimeProfileInfo) == sizeof(ProfileData));
+    CompileAssert(sizeof(JITTimeProfileInfo) == sizeof(ProfileDataIDL));
 }
 
 /* static */
@@ -16,38 +16,39 @@ void
 JITTimeProfileInfo::InitializeJITProfileData(
     __in Js::DynamicProfileInfo * profileInfo,
     __in Js::FunctionBody *functionBody,
-    __out ProfileData * data)
+    __out ProfileDataIDL * data)
 {
     if (profileInfo == nullptr)
     {
         return;
     }
-    CompileAssert(sizeof(LdElemData) == sizeof(Js::LdElemInfo));
+    CompileAssert(sizeof(LdElemIDL) == sizeof(Js::LdElemInfo));
 
     data->profiledLdElemCount = functionBody->GetProfiledLdElemCount();
-    data->ldElemData = (LdElemData*)profileInfo->GetLdElemInfo();
+    data->ldElemData = (LdElemIDL*)profileInfo->GetLdElemInfo();
 
-    CompileAssert(sizeof(StElemData) == sizeof(Js::StElemInfo));
+    CompileAssert(sizeof(StElemIDL) == sizeof(Js::StElemInfo));
     data->profiledStElemCount = functionBody->GetProfiledStElemCount();
-    data->stElemData = (StElemData*)profileInfo->GetStElemInfo();
+    data->stElemData = (StElemIDL*)profileInfo->GetStElemInfo();
 
-    CompileAssert(sizeof(ArrayCallSiteData) == sizeof(Js::ArrayCallSiteInfo));
+    CompileAssert(sizeof(ArrayCallSiteIDL) == sizeof(Js::ArrayCallSiteInfo));
     data->profiledArrayCallSiteCount = functionBody->GetProfiledArrayCallSiteCount();
-    data->arrayCallSiteData = (ArrayCallSiteData*)profileInfo->GetArrayCallSiteInfo();
+    data->arrayCallSiteData = (ArrayCallSiteIDL*)profileInfo->GetArrayCallSiteInfo();
+    data->arrayCallSiteDataAddr = (intptr_t)profileInfo->GetArrayCallSiteInfo();
 
-    CompileAssert(sizeof(FldData) == sizeof(Js::FldInfo));
+    CompileAssert(sizeof(FldIDL) == sizeof(Js::FldInfo));
     data->inlineCacheCount = functionBody->GetProfiledFldCount();
-    data->fldData = (FldData*)profileInfo->GetFldInfo();
+    data->fldData = (FldIDL*)profileInfo->GetFldInfo();
 
-    CompileAssert(sizeof(ThisData) == sizeof(Js::ThisInfo));
-    data->thisData = *reinterpret_cast<ThisData*>(&profileInfo->GetThisInfo());
+    CompileAssert(sizeof(ThisIDL) == sizeof(Js::ThisInfo));
+    data->thisData = *reinterpret_cast<ThisIDL*>(&profileInfo->GetThisInfo());
 
-    CompileAssert(sizeof(CallSiteData) == sizeof(Js::CallSiteInfo));
+    CompileAssert(sizeof(CallSiteIDL) == sizeof(Js::CallSiteInfo));
     data->profiledCallSiteCount = functionBody->GetProfiledCallSiteCount();
-    data->callSiteData = reinterpret_cast<CallSiteData*>(profileInfo->GetCallSiteInfo());
+    data->callSiteData = reinterpret_cast<CallSiteIDL*>(profileInfo->GetCallSiteInfo());
 
-    CompileAssert(sizeof(BVUnitData) == sizeof(BVUnit));
-    data->loopFlags = (BVFixedData*)profileInfo->GetLoopFlags();
+    CompileAssert(sizeof(BVUnitIDL) == sizeof(BVUnit));
+    data->loopFlags = (BVFixedIDL*)profileInfo->GetLoopFlags();
 
     CompileAssert(sizeof(ValueType) == sizeof(uint16));
 
@@ -124,6 +125,13 @@ JITTimeProfileInfo::GetArrayCallSiteInfo(Js::ProfileId index) const
     return &(reinterpret_cast<Js::ArrayCallSiteInfo*>(m_profileData.arrayCallSiteData)[index]);
 }
 
+intptr_t
+JITTimeProfileInfo::GetArrayCallSiteInfoAddr(Js::ProfileId index) const
+{
+    Assert(index < GetProfiledArrayCallSiteCount());
+    return m_profileData.arrayCallSiteDataAddr + index * sizeof(ArrayCallSiteIDL);
+}
+
 Js::FldInfo *
 JITTimeProfileInfo::GetFldInfo(uint fieldAccessId) const
 {

+ 4 - 3
lib/Backend/JITTimeProfileInfo.h

@@ -8,17 +8,18 @@
 class JITTimeProfileInfo
 {
 public:
-    JITTimeProfileInfo(ProfileData * profileData);
+    JITTimeProfileInfo(ProfileDataIDL * profileData);
 
     static void InitializeJITProfileData(
         __in Js::DynamicProfileInfo * profileInfo,
         __in Js::FunctionBody *functionBody,
-        __out ProfileData * data);
+        __out ProfileDataIDL * data);
 
     const Js::LdElemInfo * GetLdElemInfo(Js::ProfileId ldElemId) const;
     const Js::StElemInfo * GetStElemInfo(Js::ProfileId stElemId) const;
 
     Js::ArrayCallSiteInfo * GetArrayCallSiteInfo(Js::ProfileId index) const;
+    intptr_t GetArrayCallSiteInfoAddr(Js::ProfileId index) const;
     Js::FldInfo * GetFldInfo(uint fieldAccessId) const;
     Js::ThisInfo GetThisInfo() const;
     ValueType GetSlotLoad(Js::ProfileId slotLoadId) const;
@@ -110,5 +111,5 @@ private:
 
     Js::CallSiteInfo * GetCallSiteInfo() const;
 
-    ProfileData m_profileData;
+    ProfileDataIDL m_profileData;
 };

+ 4 - 5
lib/Backend/JITTimeWorkItem.cpp

@@ -5,8 +5,7 @@
 
 #include "Backend.h"
 
-
-JITTimeWorkItem::JITTimeWorkItem(CodeGenWorkItemJITData * workItemData) :
+JITTimeWorkItem::JITTimeWorkItem(CodeGenWorkItemIDL * workItemData) :
     m_workItemData(workItemData), m_jitBody(workItemData->jitData->bodyData)
 {
 }
@@ -53,7 +52,7 @@ JITTimeWorkItem::GetCallsCountAddress() const
     return m_workItemData->jitData->callsCountAddress;
 }
 
-const JITLoopHeader *
+const JITLoopHeaderIDL *
 JITTimeWorkItem::GetLoopHeader() const
 {
     return m_jitBody.GetLoopHeaderData(GetLoopNumber());
@@ -86,14 +85,14 @@ JITTimeWorkItem::GetJITFunctionBody()
     return &m_jitBody;
 }
 
-CodeGenWorkItemJITData *
+CodeGenWorkItemIDL *
 JITTimeWorkItem::GetWorkItemData()
 {
     return m_workItemData;
 }
 
 void
-JITTimeWorkItem::SetJITTimeData(FunctionJITTimeData * jitData)
+JITTimeWorkItem::SetJITTimeData(FunctionJITTimeDataIDL * jitData)
 {
     m_workItemData->jitData = jitData;
 }

+ 5 - 5
lib/Backend/JITTimeWorkItem.h

@@ -9,13 +9,13 @@
 class JITTimeWorkItem
 {
 public:
-    JITTimeWorkItem(CodeGenWorkItemJITData * workItemData);
+    JITTimeWorkItem(CodeGenWorkItemIDL * workItemData);
 
     CodeGenWorkItemType Type() const;
     ExecutionMode GetJitMode() const;
     uint GetLoopNumber() const;
 
-    const JITLoopHeader * GetLoopHeader() const;
+    const JITLoopHeaderIDL * GetLoopHeader() const;
     intptr_t GetLoopHeaderAddr() const;
 
     bool IsLoopBody() const;
@@ -29,13 +29,13 @@ public:
 
     JITTimeFunctionBody * GetJITFunctionBody();
 
-    CodeGenWorkItemJITData* GetWorkItemData();
+    CodeGenWorkItemIDL* GetWorkItemData();
 
-    void SetJITTimeData(FunctionJITTimeData * jitData);
+    void SetJITTimeData(FunctionJITTimeDataIDL * jitData);
     const FunctionJITTimeInfo * GetJITTimeInfo() const;
 
 private:
-    CodeGenWorkItemJITData * m_workItemData;
+    CodeGenWorkItemIDL * m_workItemData;
     JITTimeFunctionBody m_jitBody;
     Js::SmallSpanSequence m_statementMap;
 

+ 91 - 0
lib/Backend/JITType.cpp

@@ -0,0 +1,91 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+#include "Backend.h"
+
+JITType::JITType()
+{
+}
+
+JITType::JITType(TypeIDL * data) :
+    m_data(*data)
+{
+    CompileAssert(sizeof(JITType) == sizeof(TypeIDL));
+}
+
+/* static */
+void
+JITType::BuildFromJsType(__in Js::Type * jsType, __out JITType * jitType)
+{
+    TypeIDL * data = jitType->GetData();
+    data->addr = (intptr_t)jsType;
+    data->typeId = jsType->GetTypeId();
+    data->libAddr = (intptr_t)jsType->GetLibrary();
+    data->protoAddr = (intptr_t)jsType->GetPrototype();
+    data->entrypointAddr = (intptr_t)jsType->GetEntryPoint();
+    data->propertyCacheAddr = (intptr_t)jsType->GetPropertyCache();
+    if (Js::DynamicType::Is(jsType->GetTypeId()))
+    {
+        Js::DynamicType * dynamicType = static_cast<Js::DynamicType*>(jsType);
+
+        data->isShared = dynamicType->GetIsShared();
+
+        Js::DynamicTypeHandler * handler = dynamicType->GetTypeHandler();
+        data->handler.isObjectHeaderInlinedTypeHandler = handler->IsObjectHeaderInlinedTypeHandler();
+        data->handler.isLocked = handler->GetIsLocked();
+        data->handler.inlineSlotCapacity = handler->GetInlineSlotCapacity();
+        data->handler.offsetOfInlineSlots = handler->GetOffsetOfInlineSlots();
+        data->handler.slotCapacity = handler->GetSlotCapacity();
+    }
+}
+
+bool
+JITType::IsShared() const
+{
+    Assert(Js::DynamicType::Is(GetTypeId()));
+    return m_data.isShared != FALSE;
+}
+
+Js::TypeId
+JITType::GetTypeId() const
+{
+    return (Js::TypeId)m_data.typeId;
+}
+
+TypeIDL *
+JITType::GetData()
+{
+    return &m_data;
+}
+
+intptr_t
+JITType::GetAddr() const
+{
+    return m_data.addr;
+}
+
+intptr_t
+JITType::GetPrototypeAddr() const
+{
+    return m_data.protoAddr;
+}
+
+const JITTypeHandler*
+JITType::GetTypeHandler() const
+{
+    return (const JITTypeHandler*)&m_data.handler;
+}
+
+bool
+JITType::operator!=(const JITType& other) const
+{
+    return this->GetAddr() != other.GetAddr();
+}
+
+bool
+JITType::operator==(const JITType& other) const
+{
+    return this->GetAddr() == other.GetAddr();
+}

+ 33 - 0
lib/Backend/JITType.h

@@ -0,0 +1,33 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+#pragma once
+
+// forward declaration
+class JITTypeHandler;
+
+class JITType
+{
+public:
+    JITType();
+    JITType(TypeIDL * data);
+
+    bool IsShared() const;
+    Js::TypeId GetTypeId() const;
+    intptr_t GetPrototypeAddr() const;
+    intptr_t GetAddr() const;
+
+    const JITTypeHandler* GetTypeHandler() const;
+
+    TypeIDL * GetData();
+
+    static void BuildFromJsType(__in Js::Type * jsType, __out JITType * jitType);
+
+    bool operator!=(const JITType& bucket) const;
+    bool operator==(const JITType& bucket) const;
+
+private:
+    TypeIDL m_data;
+};

+ 58 - 0
lib/Backend/JITTypeHandler.cpp

@@ -0,0 +1,58 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+#include "BackEnd.h"
+
+JITTypeHandler::JITTypeHandler(TypeHandlerIDL * data)
+{
+    CompileAssert(sizeof(JITTypeHandler) == sizeof(TypeHandlerIDL));
+}
+
+bool
+JITTypeHandler::IsObjectHeaderInlinedTypeHandler() const
+{
+    return m_data.isObjectHeaderInlinedTypeHandler != FALSE;
+}
+
+bool
+JITTypeHandler::IsLocked() const
+{
+    return m_data.isLocked != FALSE;
+}
+
+uint16
+JITTypeHandler::GetInlineSlotCapacity() const
+{
+    return m_data.inlineSlotCapacity;
+}
+
+uint16
+JITTypeHandler::GetOffsetOfInlineSlots() const
+{
+    return m_data.offsetOfInlineSlots;
+}
+
+int
+JITTypeHandler::GetSlotCapacity() const
+{
+    return m_data.slotCapacity;
+}
+
+// TODO: OOP JIT, remove copy/paste code
+/* static */
+bool
+JITTypeHandler::IsTypeHandlerCompatibleForObjectHeaderInlining(const JITTypeHandler * oldTypeHandler, const JITTypeHandler * newTypeHandler)
+{
+    Assert(oldTypeHandler);
+    Assert(newTypeHandler);
+
+    return
+        oldTypeHandler->GetInlineSlotCapacity() == newTypeHandler->GetInlineSlotCapacity() ||
+        (
+            oldTypeHandler->IsObjectHeaderInlinedTypeHandler() &&
+            newTypeHandler->GetInlineSlotCapacity() ==
+            oldTypeHandler->GetInlineSlotCapacity() - Js::DynamicTypeHandler::GetObjectHeaderInlinableSlotCapacity()
+        );
+}

+ 24 - 0
lib/Backend/JITTypeHandler.h

@@ -0,0 +1,24 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+#pragma once
+
+class JITTypeHandler
+{
+public:
+    JITTypeHandler(TypeHandlerIDL * data);
+
+    bool IsObjectHeaderInlinedTypeHandler() const;
+    bool IsLocked() const;
+
+    uint16 GetInlineSlotCapacity() const;
+    uint16 GetOffsetOfInlineSlots() const;
+
+    int GetSlotCapacity() const;
+
+    static bool IsTypeHandlerCompatibleForObjectHeaderInlining(const JITTypeHandler * oldTypeHandler, const JITTypeHandler * newTypeHandler);
+private:
+    TypeHandlerIDL m_data;
+};

+ 106 - 113
lib/Backend/Lower.cpp

@@ -3559,15 +3559,16 @@ Lowerer::LowerNewScArray(IR::Instr *arrInstr)
 
         Js::ProfileId profileId = static_cast<Js::ProfileId>(arrInstr->AsProfiledInstr()->u.profileId);
         Js::ArrayCallSiteInfo *arrayInfo = arrInstr->m_func->GetProfileInfo()->GetArrayCallSiteInfo(profileId);
+        intptr_t arrayInfoAddr = arrInstr->m_func->GetProfileInfo()->GetArrayCallSiteInfoAddr(profileId);
 
 
         Assert(arrInstr->GetSrc1()->IsConstOpnd());
-        GenerateProfiledNewScArrayFastPath(arrInstr, arrayInfo, weakFuncRef, arrInstr->GetSrc1()->AsIntConstOpnd()->AsUint32());
+        GenerateProfiledNewScArrayFastPath(arrInstr, arrayInfo, arrayInfoAddr, weakFuncRef, arrInstr->GetSrc1()->AsIntConstOpnd()->AsUint32());
 
         if (arrInstr->GetDst() && arrInstr->GetDst()->GetValueType().IsLikelyNativeArray())
         {
             m_lowererMD.LoadHelperArgument(arrInstr, IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, m_func));
-            m_lowererMD.LoadHelperArgument(arrInstr, IR::AddrOpnd::New(arrayInfo, IR::AddrOpndKindDynamicArrayCallSiteInfo, m_func));
+            m_lowererMD.LoadHelperArgument(arrInstr, IR::AddrOpnd::New(arrayInfoAddr, IR::AddrOpndKindDynamicArrayCallSiteInfo, m_func));
             helperMethod = IR::HelperScrArr_ProfiledNewScArray;
         }
     }
@@ -3592,7 +3593,7 @@ BOOL Lowerer::IsSmallObject(uint32 length)
 }
 
 void
-Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t weakFuncRef, uint32 length)
+Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef, uint32 length)
 {
     if (PHASE_OFF(Js::ArrayCtorFastPathPhase, m_func) || CONFIG_FLAG(ForceES5Array))
     {
@@ -3613,7 +3614,7 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
         {
             return;
         }
-        GenerateArrayInfoIsNativeIntArrayTest(instr, arrayInfo, helperLabel);
+        GenerateArrayInfoIsNativeIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
         Assert(Js::JavascriptNativeIntArray::GetOffsetOfArrayFlags() + sizeof(uint16) == Js::JavascriptNativeIntArray::GetOffsetOfArrayCallSiteIndex());
         headOpnd = GenerateArrayAlloc<Js::JavascriptNativeIntArray>(instr, &size, arrayInfo, &isZeroed);
         const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);
@@ -3631,7 +3632,7 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
         {
             return;
         }
-        GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, helperLabel);
+        GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
         Assert(Js::JavascriptNativeFloatArray::GetOffsetOfArrayFlags() + sizeof(uint16) == Js::JavascriptNativeFloatArray::GetOffsetOfArrayCallSiteIndex());
         headOpnd = GenerateArrayAlloc<Js::JavascriptNativeFloatArray>(instr, &size, arrayInfo, &isZeroed);
         const IR::AutoReuseOpnd autoReuseHeadOpnd(headOpnd, func);
@@ -3676,18 +3677,18 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
 }
 
 void
-Lowerer::GenerateArrayInfoIsNativeIntArrayTest(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, IR::LabelInstr * helperLabel)
+Lowerer::GenerateArrayInfoIsNativeIntArrayTest(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, IR::LabelInstr * helperLabel)
 {
     Func * func = this->m_func;
-    InsertTestBranch(IR::MemRefOpnd::New(((char *)arrayInfo) + Js::ArrayCallSiteInfo::GetOffsetOfBits(), TyUint8, func),
+    InsertTestBranch(IR::MemRefOpnd::New(((char *)arrayInfoAddr) + Js::ArrayCallSiteInfo::GetOffsetOfBits(), TyUint8, func),
         IR::IntConstOpnd::New(Js::ArrayCallSiteInfo::NotNativeIntBit, TyUint8, func), Js::OpCode::BrNeq_A, helperLabel, instr);
 }
 
 void
-Lowerer::GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, IR::LabelInstr * helperLabel)
+Lowerer::GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, IR::LabelInstr * helperLabel)
 {
     Func * func = this->m_func;
-    InsertCompareBranch(IR::MemRefOpnd::New(((char *)arrayInfo) + Js::ArrayCallSiteInfo::GetOffsetOfBits(), TyUint8, func),
+    InsertCompareBranch(IR::MemRefOpnd::New(((char *)arrayInfoAddr) + Js::ArrayCallSiteInfo::GetOffsetOfBits(), TyUint8, func),
         IR::IntConstOpnd::New(Js::ArrayCallSiteInfo::NotNativeIntBit, TyUint8, func), Js::OpCode::BrNeq_A, helperLabel, instr);
 }
 
@@ -3812,7 +3813,7 @@ Lowerer::GenerateArrayAlloc(IR::Instr *instr, uint32 * psize, Js::ArrayCallSiteI
 }
 
 void
-Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t weakFuncRef, uint32 length)
+Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef, uint32 length)
 {
     if (PHASE_OFF(Js::ArrayCtorFastPathPhase, m_func))
     {
@@ -3828,7 +3829,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
 
     if (arrayInfo && arrayInfo->IsNativeIntArray())
     {
-        GenerateArrayInfoIsNativeIntArrayTest(instr, arrayInfo, helperLabel);
+        GenerateArrayInfoIsNativeIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
         Assert(Js::JavascriptNativeIntArray::GetOffsetOfArrayFlags() + sizeof(uint16) == Js::JavascriptNativeIntArray::GetOffsetOfArrayCallSiteIndex());
         headOpnd = GenerateArrayAlloc<Js::JavascriptNativeIntArray>(instr, &size, arrayInfo, &isZeroed);
 
@@ -3842,7 +3843,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
     }
     else if (arrayInfo && arrayInfo->IsNativeFloatArray())
     {
-        GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, helperLabel);
+        GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
         Assert(Js::JavascriptNativeFloatArray::GetOffsetOfArrayFlags() + sizeof(uint16) == Js::JavascriptNativeFloatArray::GetOffsetOfArrayCallSiteIndex());
         headOpnd = GenerateArrayAlloc<Js::JavascriptNativeFloatArray>(instr, &size, arrayInfo, &isZeroed);
 
@@ -3881,7 +3882,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
 }
 
 void
-Lowerer::GenerateProfiledNewScIntArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t weakFuncRef)
+Lowerer::GenerateProfiledNewScIntArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef)
 {
     // Helper will deal with ForceES5ARray
     if (PHASE_OFF(Js::ArrayLiteralFastPathPhase, m_func) || CONFIG_FLAG(ForceES5Array))
@@ -3897,7 +3898,7 @@ Lowerer::GenerateProfiledNewScIntArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
     Func * func = this->m_func;
     IR::LabelInstr * helperLabel = IR::LabelInstr::New(Js::OpCode::Label, func, true);
 
-    GenerateArrayInfoIsNativeIntArrayTest(instr, arrayInfo, helperLabel);
+    GenerateArrayInfoIsNativeIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
 
     IR::AddrOpnd * elementsOpnd = instr->GetSrc1()->AsAddrOpnd();
     Js::AuxArray<int32> * ints = (Js::AuxArray<int32> *)elementsOpnd->m_address;
@@ -3947,7 +3948,7 @@ Lowerer::GenerateProfiledNewScIntArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
 }
 
 void
-Lowerer::GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t weakFuncRef)
+Lowerer::GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef)
 {
     if (PHASE_OFF(Js::ArrayLiteralFastPathPhase, m_func) || CONFIG_FLAG(ForceES5Array))
     {
@@ -3964,7 +3965,7 @@ Lowerer::GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCall
 
     // If the array info hasn't mark as not int array yet, go to the helper and mark it.
     // It really is just for assert purpose in JavascriptNativeFloatArray::ToVarArray
-    GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, helperLabel);
+    GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(instr, arrayInfo, arrayInfoAddr, helperLabel);
 
     IR::AddrOpnd * elementsOpnd = instr->GetSrc1()->AsAddrOpnd();
     Js::AuxArray<double> * doubles = (Js::AuxArray<double> *)elementsOpnd->m_address;
@@ -4019,18 +4020,18 @@ Lowerer::LowerNewScIntArray(IR::Instr *arrInstr)
                 arrInstr->IsJitProfilingInstr()
                     ? arrInstr->AsJitProfilingInstr()->profileId
                     : static_cast<Js::ProfileId>(arrInstr->AsProfiledInstr()->u.profileId);
-            Js::ArrayCallSiteInfo *arrayInfo =
-                arrInstr->m_func->GetProfileInfo()->GetArrayCallSiteInfo(profileId);
+            Js::ArrayCallSiteInfo *arrayInfo = arrInstr->m_func->GetProfileInfo()->GetArrayCallSiteInfo(profileId);
+            intptr_t arrayInfoAddr = arrInstr->m_func->GetProfileInfo()->GetArrayCallSiteInfoAddr(profileId);
 
             // Only do fast-path if it isn't a JitProfiling instr and not copy-on-access array
             if (arrInstr->IsProfiledInstr()
                 && (PHASE_OFF1(Js::Phase::CopyOnAccessArrayPhase) || arrayInfo->isNotCopyOnAccessArray) && !PHASE_FORCE1(Js::Phase::CopyOnAccessArrayPhase))
             {
-                GenerateProfiledNewScIntArrayFastPath(arrInstr, arrayInfo, weakFuncRef);
+                GenerateProfiledNewScIntArrayFastPath(arrInstr, arrayInfo, arrayInfoAddr, weakFuncRef);
             }
 
             m_lowererMD.LoadHelperArgument(arrInstr, IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, m_func));
-            m_lowererMD.LoadHelperArgument(arrInstr, IR::AddrOpnd::New(arrayInfo, IR::AddrOpndKindDynamicArrayCallSiteInfo, m_func));
+            m_lowererMD.LoadHelperArgument(arrInstr, IR::AddrOpnd::New(arrayInfoAddr, IR::AddrOpndKindDynamicArrayCallSiteInfo, m_func));
             helperMethod = IR::HelperScrArr_ProfiledNewScIntArray;
         }
     }
@@ -4060,16 +4061,16 @@ Lowerer::LowerNewScFltArray(IR::Instr *arrInstr)
                     ? arrInstr->AsJitProfilingInstr()->profileId
                     : static_cast<Js::ProfileId>(arrInstr->AsProfiledInstr()->u.profileId);
 
-            Js::ArrayCallSiteInfo *arrayInfo =
-                arrInstr->m_func->GetProfileInfo()->GetArrayCallSiteInfo(profileId);
+            Js::ArrayCallSiteInfo *arrayInfo = arrInstr->m_func->GetProfileInfo()->GetArrayCallSiteInfo(profileId);
+            intptr_t arrayInfoAddr = arrInstr->m_func->GetProfileInfo()->GetArrayCallSiteInfoAddr(profileId);
 
             // Only do fast-path if it isn't a JitProfiling instr
             if (arrInstr->IsProfiledInstr()) {
-                GenerateProfiledNewScFloatArrayFastPath(arrInstr, arrayInfo, weakFuncRef);
+                GenerateProfiledNewScFloatArrayFastPath(arrInstr, arrayInfo, arrayInfoAddr, weakFuncRef);
             }
 
             m_lowererMD.LoadHelperArgument(arrInstr, IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, m_func));
-            m_lowererMD.LoadHelperArgument(arrInstr, IR::AddrOpnd::New(arrayInfo, IR::AddrOpndKindDynamicArrayCallSiteInfo, m_func));
+            m_lowererMD.LoadHelperArgument(arrInstr, IR::AddrOpnd::New(arrayInfoAddr, IR::AddrOpndKindDynamicArrayCallSiteInfo, m_func));
             helperMethod = IR::HelperScrArr_ProfiledNewScFltArray;
         }
     }
@@ -4491,7 +4492,7 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
         return false;
     }
 
-    Js::JitTimeConstructorCache* ctorCache;
+    JITTimeConstructorCache * ctorCache;
 
     if (newObjInstr->HasBailOutInfo())
     {
@@ -4503,8 +4504,8 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
 
         ctorCache = newObjInstr->m_func->GetConstructorCache(static_cast<Js::ProfileId>(newObjInstr->AsProfiledInstr()->u.profileId));
         Assert(ctorCache != nullptr);
-        Assert(!ctorCache->skipNewScObject);
-        Assert(!ctorCache->typeIsFinal || ctorCache->ctorHasNoExplicitReturnValue);
+        Assert(!ctorCache->SkipNewScObject());
+        Assert(!ctorCache->IsTypeFinal() || ctorCache->CtorHasNoExplicitReturnValue());
 
         LinkCtorCacheToGuardedProperties(ctorCache);
     }
@@ -4536,12 +4537,14 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
     Assert(ctorCache != nullptr);
 
     // We should only have cloned if the script contexts match.
-    Assert(newObjInstr->m_func->GetScriptContext() == ctorCache->scriptContext);
+    // TODO: oop jit, add ctorCache->scriptContext for tracing assert
+    // Assert(newObjInstr->m_func->GetScriptContextInfo()->GetAddr() == ctorCache->scriptContext);
 
     // Built-in constructors don't need a default new object.  Since we know which constructor we're calling, we can skip creating a default
     // object and call a specialized helper (or even constructor, directly) avoiding the checks in generic NewScObjectCommon.
-    if (ctorCache->skipNewScObject)
+    if (ctorCache->SkipNewScObject())
     {
+#if 0 // TODO: oop jit, add constructor info for tracing
         if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func) || PHASE_TESTTRACE(Js::FixedNewObjPhase, newObjInstr->m_func))
         {
             const Js::JavascriptFunction* ctor = ctorCache->constructor;
@@ -4557,6 +4560,7 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
                 ctorName, ctorBody ? ctorBody->GetDebugNumberSet(debugStringBuffer) : L"(null)");
             Output::Flush();
         }
+#endif
 
         // All built-in constructors share a special singleton cache that is never checked and never invalidated.  It cannot be used
         // as a guard to protect any property operations downstream from the constructor.  If this ever becomes a performance issue,
@@ -4569,8 +4573,9 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
         return true;
     }
 
-    AssertMsg(ctorCache->type != nullptr, "Why did we hard-code a mismatched, invalidated or polymorphic constructor cache?");
+    AssertMsg(ctorCache->GetType() != nullptr, "Why did we hard-code a mismatched, invalidated or polymorphic constructor cache?");
 
+#if 0 // TODO: oop jit, add constructor info for tracing
     if (PHASE_TRACE(Js::FixedNewObjPhase, newObjInstr->m_func) || PHASE_TESTTRACE(Js::FixedNewObjPhase, newObjInstr->m_func))
     {
         const Js::JavascriptFunction* constructor = ctorCache->constructor;
@@ -4597,13 +4602,14 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
         }
         Output::Flush();
     }
+#endif
 
     // If the constructor has no return statements, we can safely return the object that was created here.
     // No need to check what the constructor returned - it must be undefined.
-    returnNewScObj = ctorCache->ctorHasNoExplicitReturnValue;
+    returnNewScObj = ctorCache->CtorHasNoExplicitReturnValue();
 
     Assert(Js::ConstructorCache::GetSizeOfGuardValue() == static_cast<size_t>(TySize[TyMachPtr]));
-    IR::MemRefOpnd* guardOpnd = IR::MemRefOpnd::New(const_cast<void*>(ctorCache->runtimeCache->GetAddressOfGuardValue()), TyMachReg, this->m_func,
+    IR::MemRefOpnd* guardOpnd = IR::MemRefOpnd::New(ctorCache->GetRuntimeCacheGuardAddr(), TyMachReg, this->m_func,
         IR::AddrOpndKindDynamicGuardValueRef);
     IR::AddrOpnd* zeroOpnd = IR::AddrOpnd::NewNull(this->m_func);
     InsertCompareBranch(guardOpnd, zeroOpnd, Js::OpCode::BrEq_A, helperOrBailoutLabel, newObjInstr);
@@ -4621,16 +4627,16 @@ bool Lowerer::TryLowerNewScObjectWithFixedCtorCache(IR::Instr* newObjInstr, IR::
     }
     else
     {
-        const Js::DynamicType* newObjectType = ctorCache->type;
-        Assert(newObjectType->GetIsShared());
+        const JITType* newObjectType = ctorCache->GetType();
+        Assert(newObjectType->IsShared());
 
         IR::AddrOpnd* typeSrc = IR::AddrOpnd::New(const_cast<void *>(reinterpret_cast<const void *>(newObjectType)), IR::AddrOpndKindDynamicType, m_func);
 
         // For the next call:
         //     inlineSlotSize == Number of slots to allocate beyond the DynamicObject header
         //     slotSize - inlineSlotSize == Number of aux slots to allocate
-        int inlineSlotSize = ctorCache->inlineSlotCount;
-        int slotSize = ctorCache->slotCount;
+        int inlineSlotSize = ctorCache->GetInlineSlotCount();
+        int slotSize = ctorCache->GetSlotCount();
         if (newObjectType->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler())
         {
             Assert(inlineSlotSize >= Js::DynamicTypeHandler::GetObjectHeaderInlinableSlotCapacity());
@@ -4899,6 +4905,7 @@ Lowerer::LowerNewScObjArray(IR::Instr *newObjInstr)
 
     intptr_t weakFuncRef = 0;
     Js::ArrayCallSiteInfo *arrayInfo = nullptr;
+    intptr_t arrayInfoAddr = 0;
     Assert(newObjInstr->IsProfiledInstr());
 
     IR::RegOpnd *resultObjOpnd = newObjInstr->GetDst()->AsRegOpnd();
@@ -4910,6 +4917,7 @@ Lowerer::LowerNewScObjArray(IR::Instr *newObjInstr)
     if (profileId != Js::Constants::NoProfileId)
     {
         arrayInfo = func->GetProfileInfo()->GetArrayCallSiteInfo(profileId);
+        arrayInfoAddr = func->GetProfileInfo()->GetArrayCallSiteInfoAddr(profileId);
         Assert(arrayInfo);
         weakFuncRef = func->GetWeakFuncRef();
         Assert(weakFuncRef);
@@ -4921,11 +4929,11 @@ Lowerer::LowerNewScObjArray(IR::Instr *newObjInstr)
         intptr_t length = opndSrc1->GetImmediateValue(m_func);
         if (length >= 0 && length <= 8)
         {
-            GenerateProfiledNewScObjArrayFastPath(newObjInstr, arrayInfo, weakFuncRef, (uint32)length);
+            GenerateProfiledNewScObjArrayFastPath(newObjInstr, arrayInfo, arrayInfoAddr, weakFuncRef, (uint32)length);
         }
     }
 
-    IR::Opnd *profileOpnd = IR::AddrOpnd::New(arrayInfo, IR::AddrOpndKindDynamicArrayCallSiteInfo, func);
+    IR::Opnd *profileOpnd = IR::AddrOpnd::New(func->GetProfileInfo()->GetArrayCallSiteInfoAddr(profileId), IR::AddrOpndKindDynamicArrayCallSiteInfo, func);
     this->m_lowererMD.LoadNewScObjFirstArg(newObjInstr, profileOpnd);
 
     IR::JnHelperMethod helperMethod = IR::HelperScrArr_ProfiledNewInstance;
@@ -5007,20 +5015,22 @@ Lowerer::LowerNewScObjArrayNoArg(IR::Instr *newObjInstr)
     Assert(newObjInstr->IsProfiledInstr());
 
     intptr_t weakFuncRef = 0;
+    intptr_t arrayInfoAddr = 0;
     Js::ArrayCallSiteInfo *arrayInfo = nullptr;
     Js::ProfileId profileId = static_cast<Js::ProfileId>(newObjInstr->AsProfiledInstr()->u.profileId);
     if (profileId != Js::Constants::NoProfileId)
     {
         arrayInfo = func->GetProfileInfo()->GetArrayCallSiteInfo(profileId);
+        arrayInfoAddr = func->GetProfileInfo()->GetArrayCallSiteInfoAddr(profileId);
         Assert(arrayInfo);
         weakFuncRef = func->GetWeakFuncRef();
         Assert(weakFuncRef);
     }
 
-    GenerateProfiledNewScObjArrayFastPath(newObjInstr, arrayInfo, weakFuncRef, 0);
+    GenerateProfiledNewScObjArrayFastPath(newObjInstr, arrayInfo, arrayInfoAddr, weakFuncRef, 0);
 
     m_lowererMD.LoadHelperArgument(newObjInstr, IR::AddrOpnd::New(weakFuncRef, IR::AddrOpndKindDynamicFunctionBodyWeakRef, func));
-    m_lowererMD.LoadHelperArgument(newObjInstr, IR::AddrOpnd::New(arrayInfo, IR::AddrOpndKindDynamicArrayCallSiteInfo, func));
+    m_lowererMD.LoadHelperArgument(newObjInstr, IR::AddrOpnd::New(arrayInfoAddr, IR::AddrOpndKindDynamicArrayCallSiteInfo, func));
 
     LoadScriptContext(newObjInstr);
 
@@ -5869,7 +5879,7 @@ Lowerer::LowerAdjustObjType(IR::Instr * instrAdjustObjType)
     IR::RegOpnd  *baseOpnd = instrAdjustObjType->UnlinkSrc1()->AsRegOpnd();
 
     this->GenerateAdjustBaseSlots(
-        instrAdjustObjType, baseOpnd, (Js::Type*)initialTypeOpnd->m_address, (Js::Type*)finalTypeOpnd->m_address);
+        instrAdjustObjType, baseOpnd, (JITType*)initialTypeOpnd->m_metadata, (JITType*)finalTypeOpnd->m_metadata);
 
     this->m_func->PinTypeRef(finalTypeOpnd->m_address);
 
@@ -6749,7 +6759,7 @@ Lowerer::GenerateCachedTypeCheck(IR::Instr *instrChk, IR::PropertySymOpnd *prope
         (propertySymOpnd->IsPoly() || instrChk->HasTypeCheckBailOut());
     Assert(doEquivTypeCheck || !instrChk->HasEquivalentTypeCheckBailOut());
 
-    Js::Type* type = doEquivTypeCheck ? propertySymOpnd->GetFirstEquivalentType() : propertySymOpnd->GetType();
+    JITType* type = doEquivTypeCheck ? propertySymOpnd->GetFirstEquivalentType() : propertySymOpnd->GetType();
 
     Js::PropertyGuard* typeCheckGuard = doEquivTypeCheck ?
         (Js::PropertyGuard*)CreateEquivalentTypeGuardAndLinkToGuardedProperties(type, propertySymOpnd) :
@@ -6850,7 +6860,7 @@ Lowerer::GenerateCachedTypeCheck(IR::Instr *instrChk, IR::PropertySymOpnd *prope
 }
 
 void
-Lowerer::PinTypeRef(Js::Type* type, void* typeRef, IR::Instr* instr, Js::PropertyId propertyId)
+Lowerer::PinTypeRef(JITType* type, void* typeRef, IR::Instr* instr, Js::PropertyId propertyId)
 {
     this->m_func->PinTypeRef(typeRef);
 
@@ -6860,7 +6870,7 @@ Lowerer::PinTypeRef(Js::Type* type, void* typeRef, IR::Instr* instr, Js::Propert
         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->GetJITFunctionBody()->GetDisplayName(), this->m_func->GetDebugNumberSet(debugStringBuffer),
             Js::OpCodeUtil::GetOpCodeName(instr->m_opcode), GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer(), propertyId,
-            typeRef == type ? L"strong" : L"weak", typeRef, type);
+            (intptr_t)typeRef == type->GetAddr() ? L"strong" : L"weak", typeRef, type->GetAddr());
         Output::Flush();
     }
 }
@@ -6871,7 +6881,7 @@ Lowerer::GenerateCachedTypeWithoutPropertyCheck(IR::Instr *instrInsert, IR::Prop
     Assert(propertySymOpnd->IsMonoObjTypeSpecCandidate());
     Assert(propertySymOpnd->HasInitialType());
 
-    Js::Type* typeWithoutProperty = propertySymOpnd->GetInitialType();
+    JITType* typeWithoutProperty = propertySymOpnd->GetInitialType();
 
     // We should never add properties to objects of static types.
     Assert(Js::DynamicType::Is(typeWithoutProperty->GetTypeId()));
@@ -6907,7 +6917,7 @@ Lowerer::GenerateCachedTypeWithoutPropertyCheck(IR::Instr *instrInsert, IR::Prop
     }
     else
     {
-        expectedTypeOpnd = IR::AddrOpnd::New(typeWithoutProperty, IR::AddrOpndKindDynamicType, m_func, true);
+        expectedTypeOpnd = IR::AddrOpnd::New(typeWithoutProperty->GetAddr(), IR::AddrOpndKindDynamicType, m_func, true);
     }
 
     InsertCompareBranch(typeOpnd, expectedTypeOpnd, Js::OpCode::BrNeq_A, labelTypeCheckFailed, instrInsert);
@@ -6924,23 +6934,21 @@ Lowerer::GenerateFixedFieldGuardCheck(IR::Instr *insertPointInstr, IR::PropertyS
 }
 
 Js::JitTypePropertyGuard*
-Lowerer::CreateTypePropertyGuardForGuardedProperties(Js::Type* type, IR::PropertySymOpnd* propertySymOpnd)
+Lowerer::CreateTypePropertyGuardForGuardedProperties(JITType* type, IR::PropertySymOpnd* propertySymOpnd)
 {
     // We should always have a list of guarded properties.
     Assert(propertySymOpnd->GetGuardedPropOps() != nullptr);
 
     Js::JitTypePropertyGuard* guard = nullptr;
 
-    Js::EntryPointInfo* entryPointInfo = this->m_func->m_workItem->GetEntryPoint();
-
-    if (entryPointInfo->HasSharedPropertyGuards())
+    if (m_func->GetWorkItem()->GetJITTimeInfo()->HasSharedPropertyGuards())
     {
         // Consider (ObjTypeSpec): Because we allocate these guards from the JIT thread we can't share guards for the same type across multiple functions.
         // This leads to proliferation of property guards on the thread context.  The alternative would be to pre-allocate shared (by value) guards
         // from the thread context during work item creation.  We would create too many of them (because some types aren't actually used as guards),
         // but we could share a guard for a given type between functions.  This may ultimately be better.
 
-        LinkGuardToGuardedProperties(entryPointInfo, propertySymOpnd->GetGuardedPropOps(), [this, type, &guard](Js::PropertyId propertyId)
+        LinkGuardToGuardedProperties(propertySymOpnd->GetGuardedPropOps(), [this, type, &guard](Js::PropertyId propertyId)
         {
             if (DoLazyFixedTypeBailout(this->m_func))
             {
@@ -6950,7 +6958,7 @@ Lowerer::CreateTypePropertyGuardForGuardedProperties(Js::Type* type, IR::Propert
             {
                 if (guard == nullptr)
                 {
-                    guard = this->m_func->GetOrCreateSingleTypeGuard(type);
+                    guard = this->m_func->GetOrCreateSingleTypeGuard(type->GetAddr());
                 }
 
                 if (PHASE_TRACE(Js::ObjTypeSpecPhase, this->m_func) || PHASE_TRACE(Js::TracePropertyGuardsPhase, this->m_func))
@@ -6972,18 +6980,16 @@ Lowerer::CreateTypePropertyGuardForGuardedProperties(Js::Type* type, IR::Propert
 }
 
 Js::JitEquivalentTypeGuard*
-Lowerer::CreateEquivalentTypeGuardAndLinkToGuardedProperties(Js::Type* type, IR::PropertySymOpnd* propertySymOpnd)
+Lowerer::CreateEquivalentTypeGuardAndLinkToGuardedProperties(JITType* type, IR::PropertySymOpnd* propertySymOpnd)
 {
     // We should always have a list of guarded properties.
     Assert(propertySymOpnd->HasObjTypeSpecFldInfo() && propertySymOpnd->HasEquivalentTypeSet() && propertySymOpnd->GetGuardedPropOps());
 
     Js::JitEquivalentTypeGuard* guard = this->m_func->CreateEquivalentTypeGuard(type, propertySymOpnd->GetObjTypeSpecFldId());
 
-    Js::EntryPointInfo* entryPointInfo = this->m_func->m_workItem->GetEntryPoint();
-
-    if (entryPointInfo->HasSharedPropertyGuards())
+    if (m_func->GetWorkItem()->GetJITTimeInfo()->HasSharedPropertyGuards())
     {
-        LinkGuardToGuardedProperties(entryPointInfo, propertySymOpnd->GetGuardedPropOps(), [=](Js::PropertyId propertyId)
+        LinkGuardToGuardedProperties(propertySymOpnd->GetGuardedPropOps(), [=](Js::PropertyId propertyId)
         {
             if (PHASE_TRACE(Js::ObjTypeSpecPhase, this->m_func) || PHASE_TRACE(Js::TracePropertyGuardsPhase, this->m_func))
             {
@@ -7012,7 +7018,7 @@ Lowerer::CreateEquivalentTypeGuardAndLinkToGuardedProperties(Js::Type* type, IR:
     uint16 cachedTypeCount = typeSet->GetCount() < EQUIVALENT_TYPE_CACHE_SIZE ? typeSet->GetCount() : EQUIVALENT_TYPE_CACHE_SIZE;
     for (uint16 ti = 0; ti < cachedTypeCount; ti++)
     {
-        cache->types[ti] = typeSet->GetType(ti);
+        cache->types[ti] = (Js::Type*)typeSet->GetType(ti)->GetAddr();
     }
 
     // Populate property ID and slot index arrays on the guard's cache. We iterate over the
@@ -7030,7 +7036,7 @@ Lowerer::CreateEquivalentTypeGuardAndLinkToGuardedProperties(Js::Type* type, IR:
 
     FOREACH_BITSET_IN_SPARSEBV(propOpId, propOps)
     {
-        Js::ObjTypeSpecFldInfo* propOpInfo = this->m_func->GetGlobalObjTypeSpecFldInfo(propOpId);
+        JITObjTypeSpecFldInfo* propOpInfo = this->m_func->GetGlobalObjTypeSpecFldInfo(propOpId);
         Js::PropertyId propertyId = propOpInfo->GetPropertyId();
         Js::PropertyIndex propOpIndex = Js::Constants::NoSlot;
         bool hasFixedValue = propOpInfo->HasFixedValue();
@@ -7105,7 +7111,7 @@ Lowerer::CreateEquivalentTypeGuardAndLinkToGuardedProperties(Js::Type* type, IR:
 }
 
 bool
-Lowerer::LinkCtorCacheToGuardedProperties(Js::JitTimeConstructorCache* ctorCache)
+Lowerer::LinkCtorCacheToGuardedProperties(JITTimeConstructorCache* ctorCache)
 {
     // We do not always have guarded properties. If the constructor is empty and the subsequent code doesn't load or store any of
     // the constructed object's properties, or if all inline caches are empty then this ctor cache doesn't guard any properties.
@@ -7115,18 +7121,17 @@ Lowerer::LinkCtorCacheToGuardedProperties(Js::JitTimeConstructorCache* ctorCache
     }
 
     bool linked = false;
-    Js::EntryPointInfo* entryPointInfo = this->m_func->m_workItem->GetEntryPoint();
 
-    if (entryPointInfo->HasSharedPropertyGuards())
+    if (this->m_func->GetWorkItem()->GetJITTimeInfo()->HasSharedPropertyGuards())
     {
-        linked = LinkGuardToGuardedProperties(entryPointInfo, ctorCache->GetGuardedPropOps(), [=](Js::PropertyId propertyId)
+        linked = LinkGuardToGuardedProperties(ctorCache->GetGuardedPropOps(), [=](Js::PropertyId propertyId)
         {
             if (PHASE_TRACE(Js::ObjTypeSpecPhase, this->m_func) || PHASE_TRACE(Js::TracePropertyGuardsPhase, this->m_func))
             {
                 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->GetJITFunctionBody()->GetDisplayName(), this->m_func->GetDebugNumberSet(debugStringBuffer),
-                    ctorCache->runtimeCache, ctorCache->type, GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer(), propertyId);
+                    ctorCache->GetRuntimeCacheAddr(), ctorCache->GetType()->GetAddr(), GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer(), propertyId);
                 Output::Flush();
             }
 
@@ -7139,17 +7144,16 @@ Lowerer::LinkCtorCacheToGuardedProperties(Js::JitTimeConstructorCache* ctorCache
 
 template<typename LinkFunc>
 bool
-Lowerer::LinkGuardToGuardedProperties(Js::EntryPointInfo* entryPointInfo, const BVSparse<JitArenaAllocator>* guardedPropOps, LinkFunc link)
+Lowerer::LinkGuardToGuardedProperties(const BVSparse<JitArenaAllocator>* guardedPropOps, LinkFunc link)
 {
-    Assert(entryPointInfo != nullptr);
-    Assert(entryPointInfo->HasSharedPropertyGuards());
+    Assert(this->m_func->GetWorkItem()->GetJITTimeInfo()->HasSharedPropertyGuards());
     Assert(guardedPropOps != nullptr);
     bool linked = false;
 
     // For every entry in the bit vector, register the guard for the corresponding property ID.
     FOREACH_BITSET_IN_SPARSEBV(propertyOpId, guardedPropOps)
     {
-        Js::ObjTypeSpecFldInfo* propertyOpInfo = this->m_func->GetGlobalObjTypeSpecFldInfo(propertyOpId);
+        JITObjTypeSpecFldInfo* propertyOpInfo = this->m_func->GetGlobalObjTypeSpecFldInfo(propertyOpId);
         Js::PropertyId propertyId = propertyOpInfo->GetPropertyId();
 
         // It's okay for an equivalent type check to be registered as a guard against a property becoming read-only. This transpires if, there is
@@ -7166,28 +7170,14 @@ Lowerer::LinkGuardToGuardedProperties(Js::EntryPointInfo* entryPointInfo, const
             // See JavascriptOperators::CheckIfTypeIsEquivalent.
             Assert(!propertyOpInfo->IsPoly() || (!propertyOpInfo->HasFixedValue() || propertyOpInfo->IsLoadedFromProto() || propertyOpInfo->UsesAccessor()));
 
-            if (entryPointInfo->HasSharedPropertyGuard(propertyId))
+            if (this->m_func->GetWorkItem()->GetJITTimeInfo()->HasSharedPropertyGuard(propertyId))
             {
                 link(propertyId);
                 linked = true;
             }
             else
             {
-#if TRUE
                 AssertMsg(false, "Did we fail to create a shared property guard for a guarded property?");
-#else
-                if (PHASE_VERBOSE_TRACE(Js::ObjTypeSpecPhase, this->m_func) || PHASE_TRACE(Js::TracePropertyGuardsPhase, this->m_func))
-                {
-                    if (!this->m_func->m_workItem->GetEntryPoint()->HasSharedPropertyGuard(propertyId))
-                    {
-                        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->GetJITFunctionBody()->GetDisplayName(), this->m_func->GetDebugNumberSet(debugStringBuffer),
-                            GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer(), propertyId);
-                        Output::Flush();
-                    }
-                }
-#endif
             }
         }
     }
@@ -7199,14 +7189,14 @@ Lowerer::LinkGuardToGuardedProperties(Js::EntryPointInfo* entryPointInfo, const
 void
 Lowerer::GeneratePropertyGuardCheck(IR::Instr *insertPointInstr, IR::PropertySymOpnd *propertySymOpnd, IR::LabelInstr *labelBailOut)
 {
-    Js::PropertyGuard* guard = propertySymOpnd->GetPropertyGuard();
-    Assert(guard != nullptr);
+    intptr_t guard = propertySymOpnd->GetPropertyGuardValueAddr();
+    Assert(guard != 0);
 
     if (!DoLazyFixedDataBailout(this->m_func))
     {
         Assert(Js::PropertyGuard::GetSizeOfValue() == static_cast<size_t>(TySize[TyMachPtr]));
         IR::AddrOpnd* zeroOpnd = IR::AddrOpnd::NewNull(this->m_func);
-        IR::MemRefOpnd* guardOpnd = IR::MemRefOpnd::New((void*)guard->GetAddressOfValue(), TyMachPtr, this->m_func, IR::AddrOpndKindDynamicGuardValueRef);
+        IR::MemRefOpnd* guardOpnd = IR::MemRefOpnd::New(guard, TyMachPtr, this->m_func, IR::AddrOpndKindDynamicGuardValueRef);
         InsertCompareBranch(guardOpnd, zeroOpnd, Js::OpCode::BrEq_A, labelBailOut, insertPointInstr);
     }
     else
@@ -7259,14 +7249,14 @@ Lowerer::GenerateNonWritablePropertyCheck(IR::Instr *instrInsert, IR::PropertySy
     // Inline the check on the bit in the prototype object's type. If that check fails, call the helper.
     // If the helper finds a non-writable property, bail out, as we're counting on being able to add the property.
 
-    Js::Type *typeWithoutProperty = propertySymOpnd->GetInitialType();
+    JITType *typeWithoutProperty = propertySymOpnd->GetInitialType();
     Assert(typeWithoutProperty);
-    Js::RecyclableObject *protoObject = typeWithoutProperty->GetPrototype();
-    Assert(protoObject);
+    intptr_t protoAddr = typeWithoutProperty->GetPrototypeAddr();
+    Assert(protoAddr != 0);
 
     // s1 = MOV [proto->type].ptr
     IR::RegOpnd *typeOpnd = IR::RegOpnd::New(TyMachReg, this->m_func);
-    opnd = IR::MemRefOpnd::New((char*)protoObject + Js::RecyclableObject::GetOffsetOfType(), TyMachReg,
+    opnd = IR::MemRefOpnd::New((char*)protoAddr + Js::RecyclableObject::GetOffsetOfType(), TyMachReg,
         this->m_func, IR::AddrOpndKindDynamicObjectTypeRef);
     m_lowererMD.CreateAssign(typeOpnd, opnd, instrInsert);
 
@@ -7281,7 +7271,7 @@ Lowerer::GenerateNonWritablePropertyCheck(IR::Instr *instrInsert, IR::PropertySy
     instrInsert->InsertBefore(labelHelper);
 
     //     s2 = CALL DoProtoCheck, prototype
-    opnd = IR::AddrOpnd::New(protoObject, IR::AddrOpndKindDynamicVar, this->m_func, true);
+    opnd = IR::AddrOpnd::New(protoAddr, IR::AddrOpndKindDynamicVar, this->m_func, true);
     m_lowererMD.LoadHelperArgument(instrInsert, opnd);
 
     opnd = IR::HelperCallOpnd::New(IR::HelperCheckProtoHasNonWritable, this->m_func);
@@ -7297,7 +7287,7 @@ Lowerer::GenerateNonWritablePropertyCheck(IR::Instr *instrInsert, IR::PropertySy
 }
 
 void
-Lowerer::GenerateAdjustSlots(IR::Instr *instrInsert, IR::PropertySymOpnd *propertySymOpnd, Js::Type* initialType, Js::Type* finalType)
+Lowerer::GenerateAdjustSlots(IR::Instr *instrInsert, IR::PropertySymOpnd *propertySymOpnd, JITType* initialType, JITType* finalType)
 {
     IR::RegOpnd *baseOpnd = propertySymOpnd->CreatePropertyOwnerOpnd(m_func);
     bool adjusted = this->GenerateAdjustBaseSlots(instrInsert, baseOpnd, initialType, finalType);
@@ -7308,20 +7298,15 @@ Lowerer::GenerateAdjustSlots(IR::Instr *instrInsert, IR::PropertySymOpnd *proper
 }
 
 bool
-Lowerer::GenerateAdjustBaseSlots(IR::Instr *instrInsert, IR::RegOpnd *baseOpnd, Js::Type* initialType, Js::Type* finalType)
+Lowerer::GenerateAdjustBaseSlots(IR::Instr *instrInsert, IR::RegOpnd *baseOpnd, JITType* initialType, JITType* finalType)
 {
     // Possibly allocate new slot capacity to accommodate a type transition.
-    Js::DynamicType *oldType = static_cast<Js::DynamicType*>(initialType);
-    Assert(oldType);
-    Js::DynamicType *newType = static_cast<Js::DynamicType*>(finalType);
-    Assert(newType);
-
-    AssertMsg(Js::DynamicObject::IsTypeHandlerCompatibleForObjectHeaderInlining(oldType->GetTypeHandler(), newType->GetTypeHandler()),
+    AssertMsg(JITTypeHandler::IsTypeHandlerCompatibleForObjectHeaderInlining(initialType->GetTypeHandler(), finalType->GetTypeHandler()),
         "Incompatible typeHandler transition?");
-    int oldCount = oldType->GetTypeHandler()->GetSlotCapacity();
-    int newCount = newType->GetTypeHandler()->GetSlotCapacity();
-    Js::PropertyIndex inlineSlotCapacity = oldType->GetTypeHandler()->GetInlineSlotCapacity();
-    Js::PropertyIndex newInlineSlotCapacity = newType->GetTypeHandler()->GetInlineSlotCapacity();
+    int oldCount = initialType->GetTypeHandler()->GetSlotCapacity();
+    int newCount = finalType->GetTypeHandler()->GetSlotCapacity();
+    Js::PropertyIndex inlineSlotCapacity = initialType->GetTypeHandler()->GetInlineSlotCapacity();
+    Js::PropertyIndex newInlineSlotCapacity = finalType->GetTypeHandler()->GetInlineSlotCapacity();
 
     if (oldCount >= newCount || newCount <= inlineSlotCapacity)
     {
@@ -7356,7 +7341,7 @@ Lowerer::GenerateAdjustBaseSlots(IR::Instr *instrInsert, IR::RegOpnd *baseOpnd,
 }
 
 void
-Lowerer::GenerateFieldStoreWithTypeChange(IR::Instr * instrStFld, IR::PropertySymOpnd *propertySymOpnd, Js::Type* initialType, Js::Type* finalType)
+Lowerer::GenerateFieldStoreWithTypeChange(IR::Instr * instrStFld, IR::PropertySymOpnd *propertySymOpnd, JITType* initialType, JITType* finalType)
 {
     // Adjust instance slots, if necessary.
     this->GenerateAdjustSlots(instrStFld, propertySymOpnd, initialType, finalType);
@@ -10886,7 +10871,7 @@ Lowerer::LowerBailOnNotBuiltIn(IR::Instr       *instr,
     Assert(instr->GetSrc2()->IsIntConstOpnd());
     IR::Instr *prevInstr = instr->m_prev;
 
-    Js::JavascriptFunction ** builtInFuncs = this->m_func->GetScriptContext()->GetLibrary()->GetBuiltinFunctions();
+    intptr_t builtInFuncs = m_func->GetScriptContextInfo()->GetBuiltinFunctionsBaseAddr();
     Js::BuiltinFunction builtInIndex = instr->UnlinkSrc2()->AsIntConstOpnd()->AsInt32();
 
     IR::Opnd *builtIn = IR::MemRefOpnd::New((void*)(builtInFuncs + builtInIndex), TyMachReg, instr->m_func);
@@ -12168,10 +12153,18 @@ Lowerer::GenerateBailOut(IR::Instr * instr, IR::BranchInstr * branchInstr, IR::L
         collectRuntimeStatsLabel = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, true);
         instr->InsertBefore(collectRuntimeStatsLabel);
 
-        IR::MemRefOpnd *pIndexOpndForBailOutKind =
-            IR::MemRefOpnd::New((BYTE*)bailOutInfo->bailOutRecord + BailOutRecord::GetOffsetOfBailOutKind(), TyUint32, this->m_func, IR::AddrOpndKindDynamicBailOutKindRef);
+        int offset = ((NativeCodeData::DataChunk*)((char*)bailOutInfo->bailOutRecord - sizeof(NativeCodeData::DataChunk)))->offset;
+        auto addressRegOpnd = IR::RegOpnd::New(TyMachPtr, m_func);
+
+        Lowerer::InsertMove(
+            addressRegOpnd,
+            IR::MemRefOpnd::New((void*)m_func->GetWorkItem()->GetWorkItemData()->nativeDataAddr, TyMachPtr, m_func, IR::AddrOpndKindDynamicMisc),
+            instr);
+
+        IR::IndirOpnd * indexOpndForBailOutKind = IR::IndirOpnd::New(addressRegOpnd, (int)(offset + BailOutRecord::GetOffsetOfBailOutKind()), TyUint32, m_func);
+
         m_lowererMD.CreateAssign(
-            pIndexOpndForBailOutKind, IR::IntConstOpnd::New(instr->GetBailOutKind(), pIndexOpndForBailOutKind->GetType(), this->m_func), instr);
+            indexOpndForBailOutKind, IR::IntConstOpnd::New(instr->GetBailOutKind(), indexOpndForBailOutKind->GetType(), this->m_func), instr);
 
         // No point in doing this for BailOutFailedEquivalentTypeCheck or BailOutFailedEquivalentFixedFieldTypeCheck,
         // because the respective inline cache is already polymorphic, anyway.
@@ -12182,10 +12175,10 @@ Lowerer::GenerateBailOut(IR::Instr * instr, IR::BranchInstr * branchInstr, IR::L
             Assert(bailOutInfo->polymorphicCacheIndex != (uint)-1);
             Assert(bailOutInfo->bailOutRecord);
 
-            IR::MemRefOpnd *pIndexOpnd =
-                IR::MemRefOpnd::New((BYTE*)bailOutInfo->bailOutRecord + BailOutRecord::GetOffsetOfPolymorphicCacheIndex(), TyUint32, this->m_func);
+            IR::IndirOpnd * indexOpnd = IR::IndirOpnd::New(addressRegOpnd, (int)(offset + BailOutRecord::GetOffsetOfPolymorphicCacheIndex()), TyUint32, m_func);
+
             m_lowererMD.CreateAssign(
-                pIndexOpnd, IR::IntConstOpnd::New(bailOutInfo->polymorphicCacheIndex, TyUint32, this->m_func), instr);
+                indexOpnd, IR::IntConstOpnd::New(bailOutInfo->polymorphicCacheIndex, TyUint32, this->m_func), instr);
         }
 
         // GenerateBailOut should have replaced this as a label as we should have already lowered
@@ -21960,8 +21953,8 @@ IR::Opnd *
 Lowerer::LoadSlotArrayWithCachedProtoType(IR::Instr * instrInsert, IR::PropertySymOpnd *propertySymOpnd)
 {
     // Get the prototype object from the cache
-    Js::RecyclableObject *prototypeObject = propertySymOpnd->GetProtoObject();
-    Assert(prototypeObject != nullptr);
+    intptr_t prototypeObject = propertySymOpnd->GetProtoObject();
+    Assert(prototypeObject != 0);
 
     if (propertySymOpnd->UsesAuxSlot())
     {

+ 14 - 14
lib/Backend/Lower.h

@@ -123,20 +123,20 @@ private:
                         IR::LabelInstr* labelObjCheckFailed, IR::LabelInstr *labelTypeCheckFailed, IR::LabelInstr *labelSecondChance = nullptr);
     void            GenerateCachedTypeWithoutPropertyCheck(IR::Instr *instrInsert, IR::PropertySymOpnd *propertySymOpnd, IR::Opnd *typeOpnd, IR::LabelInstr *labelTypeCheckFailed);
     void            GenerateFixedFieldGuardCheck(IR::Instr *insertPointInstr, IR::PropertySymOpnd *propertySymOpnd, IR::LabelInstr *labelBailOut);
-    Js::JitTypePropertyGuard* CreateTypePropertyGuardForGuardedProperties(Js::Type* type, IR::PropertySymOpnd* propertySymOpnd);
-    Js::JitEquivalentTypeGuard* CreateEquivalentTypeGuardAndLinkToGuardedProperties(Js::Type* type, IR::PropertySymOpnd* propertySymOpnd);
-    bool            LinkCtorCacheToGuardedProperties(Js::JitTimeConstructorCache* cache);
+    Js::JitTypePropertyGuard* CreateTypePropertyGuardForGuardedProperties(JITType* type, IR::PropertySymOpnd* propertySymOpnd);
+    Js::JitEquivalentTypeGuard* CreateEquivalentTypeGuardAndLinkToGuardedProperties(JITType* type, IR::PropertySymOpnd* propertySymOpnd);
+    bool            LinkCtorCacheToGuardedProperties(JITTimeConstructorCache* cache);
     template<typename LinkFunc>
-    bool            LinkGuardToGuardedProperties(Js::EntryPointInfo* entryPointInfo, const BVSparse<JitArenaAllocator>* guardedPropOps, LinkFunc link);
+    bool            LinkGuardToGuardedProperties(const BVSparse<JitArenaAllocator>* guardedPropOps, LinkFunc link);
     void            GeneratePropertyGuardCheck(IR::Instr *insertPointInstr, IR::PropertySymOpnd *propertySymOpnd, IR::LabelInstr *labelBailOut);
     IR::Instr *     GeneratePropertyGuardCheckBailoutAndLoadType(IR::Instr *insertInstr);
     void            GenerateNonWritablePropertyCheck(IR::Instr *instrInsert, IR::PropertySymOpnd *propertySymOpnd, IR::LabelInstr *labelBailOut);
-    void            GenerateFieldStoreWithTypeChange(IR::Instr * instrStFld, IR::PropertySymOpnd *propertySymOpnd, Js::Type* initialType, Js::Type* finalType);
+    void            GenerateFieldStoreWithTypeChange(IR::Instr * instrStFld, IR::PropertySymOpnd *propertySymOpnd, JITType* initialType, JITType* finalType);
     void            GenerateDirectFieldStore(IR::Instr* instrStFld, IR::PropertySymOpnd* propertySymOpnd);
-    void            GenerateAdjustSlots(IR::Instr * instrStFld, IR::PropertySymOpnd *propertySymOpnd, Js::Type* initialType, Js::Type* finalType);
-    bool            GenerateAdjustBaseSlots(IR::Instr * instrStFld, IR::RegOpnd *baseOpnd, Js::Type* initialType, Js::Type* finalType);
+    void            GenerateAdjustSlots(IR::Instr * instrStFld, IR::PropertySymOpnd *propertySymOpnd, JITType* initialType, JITType* finalType);
+    bool            GenerateAdjustBaseSlots(IR::Instr * instrStFld, IR::RegOpnd *baseOpnd, JITType* initialType, JITType* finalType);
     void            GeneratePrototypeCacheInvalidateCheck(IR::PropertySymOpnd *propertySymOpnd, IR::Instr *instrStFld);
-    void            PinTypeRef(Js::Type* type, void* typeRef, IR::Instr* instr, Js::PropertyId propertyId);
+    void            PinTypeRef(JITType* type, void* typeRef, IR::Instr* instr, Js::PropertyId propertyId);
     IR::RegOpnd *   GenerateIsBuiltinRecyclableObject(IR::RegOpnd *regOpnd, IR::Instr *insertInstr, IR::LabelInstr *labelHelper, bool checkObjectAndDynamicObject = true, IR::LabelInstr *labelFastExternal = nullptr);
 
     void            EnsureStackFunctionListStackSym();
@@ -225,10 +225,10 @@ private:
 #ifdef ENABLE_DOM_FAST_PATH
     void            LowerFastInlineDOMFastPathGetter(IR::Instr* getterInstr);
 #endif
-    void            GenerateProfiledNewScIntArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t weakFuncRef);
-    void            GenerateArrayInfoIsNativeIntArrayTest(IR::Instr * instr,  Js::ArrayCallSiteInfo * arrayInfo, IR::LabelInstr * helperLabel);
-    void            GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t weakFuncRef);
-    void            GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(IR::Instr * instr,  Js::ArrayCallSiteInfo * arrayInfo, IR::LabelInstr * helperLabel);
+    void            GenerateProfiledNewScIntArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef);
+    void            GenerateArrayInfoIsNativeIntArrayTest(IR::Instr * instr,  Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, IR::LabelInstr * helperLabel);
+    void            GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef);
+    void            GenerateArrayInfoIsNativeFloatAndNotIntArrayTest(IR::Instr * instr,  Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, IR::LabelInstr * helperLabel);
     bool            IsEmitTempDst(IR::Opnd *opnd);
     bool            IsEmitTempSrc(IR::Opnd *opnd);
     bool            IsNullOrUndefRegOpnd(IR::RegOpnd *opnd) const;
@@ -480,8 +480,8 @@ private:
     template <typename ArrayType>
     IR::RegOpnd *   GenerateArrayAlloc(IR::Instr *instr, uint32 * psize, Js::ArrayCallSiteInfo * arrayInfo, bool * pIsHeadSegmentZeroed);
 
-    void            GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t weakFuncRef, uint32 length);
-    void            GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t weakFuncRef, uint32 length);
+    void            GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef, uint32 length);
+    void            GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteInfo * arrayInfo, intptr_t arrayInfoAddr, intptr_t weakFuncRef, uint32 length);
     void            GenerateMemInit(IR::RegOpnd * opnd, int32 offset, int32 value, IR::Instr * insertBeforeInstr, bool isZeroed = false);
     void            GenerateMemInit(IR::RegOpnd * opnd, int32 offset, uint32 value, IR::Instr * insertBeforeInstr, bool isZeroed = false);
     void            GenerateMemInitNull(IR::RegOpnd * opnd, int32 offset, IR::Instr * insertBeforeInstr, bool isZeroed = false);

+ 4 - 0
lib/Backend/NativeCodeData.cpp

@@ -65,11 +65,13 @@ NativeCodeData::AddFixupEntry(void* targetAddr, void* targetStartAddr, void* add
     entry->next = chunk->fixupList;
     chunk->fixupList = entry;
 
+#if DBG
     if (PHASE_TRACE1(Js::NativeCodeDataPhase))
     {
         Output::Print(L"NativeCodeData Add Fixup: %p(%p+%d, chunk:%p)  -->  %p(chunk:%p)  %S\n", 
             addrToFixup, startAddress, entry->addrOffset, (void*)chunk, targetAddr, (void*)targetChunk, chunk->dataType);
     }
+#endif
 }
 
 void
@@ -106,11 +108,13 @@ NativeCodeData::AddFixupEntryForPointerArray(void* startAddress, DataChunk * chu
         entry->next = chunk->fixupList;
         chunk->fixupList = entry;
 
+#if DBG
         if (PHASE_TRACE1(Js::NativeCodeDataPhase))
         {
             Output::Print(L"NativeCodeData Add Fixup: %p[%d](+%d, chunk:%p)  -->  %p(chunk:%p)  %S\n",
                 startAddress, i, entry->addrOffset, (void*)chunk, targetAddr, (void*)targetChunk, chunk->dataType);
         }
+#endif
     }
 }
 

+ 1 - 1
lib/Backend/NativeCodeData.h

@@ -162,12 +162,12 @@ public:
             chunk->fixupFunc = &Fixup;
 #if DBG
             chunk->dataType = typeid(T).name();
-#endif
             if (PHASE_TRACE1(Js::NativeCodeDataPhase))
             {
                 Output::Print(L"NativeCodeData Alloc: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n",
                     chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
             }
+#endif
 
             return dataBlock;
         }

+ 3 - 2
lib/Backend/NativeCodeGenerator.cpp

@@ -882,7 +882,7 @@ NativeCodeGenerator::CodeGen(PageAllocator * pageAllocator, CodeGenWorkItem* wor
                 auto funcEPInfo = (Js::FunctionEntryPointInfo*)epInfo;
                 workItem->GetJITData()->jitData->callsCountAddress = (uintptr_t)&funcEPInfo->callsCount;
             }
-            JITOutputData jitWriteData = {0};
+            JITOutputIDL jitWriteData = {0};
 
             threadContext->GetXProcNumberPageSegmentManager()->GetFreeSegment(workItem->GetJITData()->xProcNumberPageSegment);
 
@@ -893,6 +893,7 @@ NativeCodeGenerator::CodeGen(PageAllocator * pageAllocator, CodeGenWorkItem* wor
                 &jitWriteData);
             if (hr != S_OK)
             {
+                __debugbreak();
                 __fastfail((uint)-1);
             }
 
@@ -2201,7 +2202,7 @@ NativeCodeGenerator::GatherCodeGenData(
 
                                 if (!PHASE_OFF(Js::InlineApplyTargetPhase, functionBody) && (cacheType & Js::FldInfo_InlineCandidate))
                                 {
-                                    if (IsInlinee || objTypeSpecFldInfo->isBuiltIn)
+                                    if (IsInlinee || objTypeSpecFldInfo->IsBuiltin())
                                     {
                                         inlineApplyTarget = true;
                                     }

+ 29 - 26
lib/Backend/Opnd.cpp

@@ -727,7 +727,7 @@ PropertySymOpnd::New(PropertySym *propertySym, IRType type, Func *func)
 }
 
 void
-PropertySymOpnd::Init(uint inlineCacheIndex, intptr_t runtimeInlineCache, Js::PolymorphicInlineCache * runtimePolymorphicInlineCache, Js::ObjTypeSpecFldInfo* objTypeSpecFldInfo, byte polyCacheUtil)
+PropertySymOpnd::Init(uint inlineCacheIndex, intptr_t runtimeInlineCache, Js::PolymorphicInlineCache * runtimePolymorphicInlineCache, JITObjTypeSpecFldInfo* objTypeSpecFldInfo, byte polyCacheUtil)
 {
     this->m_inlineCacheIndex = inlineCacheIndex;
     this->m_runtimeInlineCache = runtimeInlineCache;
@@ -823,7 +823,7 @@ PropertySymOpnd::CopyInternalSub(Func *func)
 bool
 PropertySymOpnd::IsObjectHeaderInlined() const
 {
-    Js::Type *type = nullptr;
+    JITType *type = nullptr;
     if (this->IsMono())
     {
         type = this->GetType();
@@ -835,8 +835,7 @@ PropertySymOpnd::IsObjectHeaderInlined() const
 
     if (type && Js::DynamicType::Is(type->GetTypeId()))
     {
-        Js::DynamicType *dynamicType = static_cast<Js::DynamicType*>(type);
-        return dynamicType->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler();
+        return type->GetTypeHandler()->IsObjectHeaderInlinedTypeHandler();
     }
 
     return false;
@@ -845,29 +844,26 @@ PropertySymOpnd::IsObjectHeaderInlined() const
 bool
 PropertySymOpnd::ChangesObjectLayout() const
 {
-    Js::Type *finalType = this->GetFinalType();
+    JITType *finalType = this->GetFinalType();
     if (finalType == nullptr || !Js::DynamicType::Is(finalType->GetTypeId()))
     {
         return false;
     }
 
-    Js::Type *cachedType = this->IsMono() ? this->GetType() : this->GetFirstEquivalentType();
+    JITType *cachedType = this->IsMono() ? this->GetType() : this->GetFirstEquivalentType();
     Assert(cachedType && Js::DynamicType::Is(cachedType->GetTypeId()));
 
-    Js::DynamicTypeHandler * cachedTypeHandler = (static_cast<Js::DynamicType*>(cachedType))->GetTypeHandler();
-    Js::DynamicTypeHandler * finalTypeHandler = (static_cast<Js::DynamicType*>(finalType))->GetTypeHandler();
-
-    return cachedTypeHandler->GetInlineSlotCapacity() != finalTypeHandler->GetInlineSlotCapacity() ||
-        cachedTypeHandler->GetOffsetOfInlineSlots() != finalTypeHandler->GetOffsetOfInlineSlots();
+    return cachedType->GetTypeHandler()->GetInlineSlotCapacity() != finalType->GetTypeHandler()->GetInlineSlotCapacity() ||
+        cachedType->GetTypeHandler()->GetOffsetOfInlineSlots() != finalType->GetTypeHandler()->GetOffsetOfInlineSlots();
 }
 
 void
 PropertySymOpnd::UpdateSlotForFinalType()
 {
-    Js::Type *finalType = this->GetFinalType();
+    JITType *finalType = this->GetFinalType();
 
     Assert(this->IsMono() || this->checkedTypeSetIndex != (uint16)-1);
-    Js::Type *cachedType =
+    JITType *cachedType =
         this->IsMono() ? this->GetType() : this->GetEquivalentTypeSet()->GetType(checkedTypeSetIndex);
 
     Assert(finalType && Js::DynamicType::Is(finalType->GetTypeId()));
@@ -878,13 +874,11 @@ PropertySymOpnd::UpdateSlotForFinalType()
         return;
     }
 
-    Js::DynamicTypeHandler * cachedTypeHandler = (static_cast<Js::DynamicType*>(cachedType))->GetTypeHandler();
-    Js::DynamicTypeHandler * finalTypeHandler = (static_cast<Js::DynamicType*>(finalType))->GetTypeHandler();
-
-    Assert(cachedTypeHandler != finalTypeHandler);
+    // TODO: OOP JIT, add this assert back: need type handler address
+    // Assert(cachedType->GetTypeHandler() != finalType->GetTypeHandler());
 
-    if (cachedTypeHandler->GetInlineSlotCapacity() == finalTypeHandler->GetInlineSlotCapacity() &&
-        cachedTypeHandler->GetOffsetOfInlineSlots() == finalTypeHandler->GetOffsetOfInlineSlots())
+    if (cachedType->GetTypeHandler()->GetInlineSlotCapacity() == finalType->GetTypeHandler()->GetInlineSlotCapacity() &&
+        cachedType->GetTypeHandler()->GetOffsetOfInlineSlots() == finalType->GetTypeHandler()->GetOffsetOfInlineSlots())
     {
         // Nothing can change, since the variables aren't changing.
         return;
@@ -894,23 +888,23 @@ PropertySymOpnd::UpdateSlotForFinalType()
     uint16 index = this->GetSlotIndex();
     if (this->UsesAuxSlot())
     {
-        index += cachedTypeHandler->GetInlineSlotCapacity();
+        index += cachedType->GetTypeHandler()->GetInlineSlotCapacity();
     }
     else
     {
-        index -= cachedTypeHandler->GetOffsetOfInlineSlots() / sizeof(Js::Var);
+        index -= cachedType->GetTypeHandler()->GetOffsetOfInlineSlots() / sizeof(Js::Var);
     }
 
     // Figure out the slot index and aux-ness from the property index
-    if (index >= finalTypeHandler->GetInlineSlotCapacity())
+    if (index >= finalType->GetTypeHandler()->GetInlineSlotCapacity())
     {
         this->SetUsesAuxSlot(true);
-        index -= finalTypeHandler->GetInlineSlotCapacity();
+        index -= finalType->GetTypeHandler()->GetInlineSlotCapacity();
     }
     else
     {
         this->SetUsesAuxSlot(false);
-        index += finalTypeHandler->GetOffsetOfInlineSlots() / sizeof(Js::Var);
+        index += finalType->GetTypeHandler()->GetOffsetOfInlineSlots() / sizeof(Js::Var);
     }
     this->SetSlotIndex(index);
 }
@@ -1895,6 +1889,7 @@ AddrOpnd::New(Js::Var address, AddrOpndKind addrOpndKind, Func *func, bool dontE
     addrOpnd->m_type = addrOpnd->IsVar()? TyVar : TyMachPtr;
     addrOpnd->m_dontEncode = dontEncode;
     addrOpnd->m_isFunction = false;
+    addrOpnd->m_metadata = nullptr;
 
     if(address && addrOpnd->IsVar())
     {
@@ -2040,6 +2035,7 @@ AddrOpnd::CopyInternal(Func *func)
     newOpnd->m_address = m_address;
     newOpnd->m_valueType = m_valueType;
     newOpnd->m_isFunction = m_isFunction;
+    newOpnd->m_metadata = m_metadata;
     newOpnd->SetType(m_type);
     if (IsValueTypeFixed())
     {
@@ -2823,6 +2819,7 @@ Opnd::Dump(IRDumpFlags flags, Func *func)
             if (propertySymOpnd->GetGuardedPropOps() != nullptr)
             {
                 Output::Print(L",{");
+#if 0 // TODO: OOP JIT, fix this
                 if (func != nullptr)
                 {
                     int i = 0;
@@ -2833,7 +2830,7 @@ Opnd::Dump(IRDumpFlags flags, Func *func)
                         {
                             Output::Print(L",");
                         }
-                        const Js::ObjTypeSpecFldInfo* propertyOpInfo = func->GetTopFunc()->GetGlobalObjTypeSpecFldInfo(propertyOpId);
+                        const JITObjTypeSpecFldInfo* propertyOpInfo = func->GetTopFunc()->GetGlobalObjTypeSpecFldInfo(propertyOpId);
                         Output::Print(L"%s(%u)", func->GetScriptContext()->GetPropertyNameLocked(propertyOpInfo->GetPropertyId())->GetBuffer(), propertyOpId);
                         if (propertyOpInfo->IsLoadedFromProto())
                         {
@@ -2854,6 +2851,7 @@ Opnd::Dump(IRDumpFlags flags, Func *func)
                 {
                     Output::Print(L"(no func)");
                 }
+#endif
                 Output::Print(L"}");
             }
             if (propertySymOpnd->GetWriteGuards() != nullptr)
@@ -3356,7 +3354,8 @@ Opnd::GetAddrDescription(__out_ecount(count) wchar_t *const description, const s
 
         case IR::AddrOpndKindDynamicFunctionBodyWeakRef:
             DumpAddress(address, printToConsole, skipMaskedAddress);
-            DumpFunctionInfo(&buffer, &n, ((RecyclerWeakReference<Js::FunctionBody> *)address)->FastGet(), printToConsole, L"FunctionBodyWeakRef");
+            // TODO: OOP JIT
+            //DumpFunctionInfo(&buffer, &n, ((RecyclerWeakReference<Js::FunctionBody> *)address)->FastGet(), printToConsole, L"FunctionBodyWeakRef");
             break;
 
         case IR::AddrOpndKindDynamicFunctionEnvironmentRef:
@@ -3384,6 +3383,7 @@ Opnd::GetAddrDescription(__out_ecount(count) wchar_t *const description, const s
         case IR::AddrOpndKindDynamicObjectTypeRef:
             DumpAddress(address, printToConsole, skipMaskedAddress);
             {
+#if 0 // TODO: OOP JIT, fix this
                 Js::RecyclableObject * dynamicObject = (Js::RecyclableObject *)((intptr_t)address - Js::RecyclableObject::GetOffsetOfType());
                 if (Js::JavascriptFunction::Is(dynamicObject))
                 {
@@ -3391,6 +3391,7 @@ Opnd::GetAddrDescription(__out_ecount(count) wchar_t *const description, const s
                         printToConsole, L"FunctionObjectTypeRef");
                 }
                 else
+#endif
                 {
                     WriteToBuffer(&buffer, &n, L" (ObjectTypeRef)");
                 }
@@ -3399,6 +3400,7 @@ Opnd::GetAddrDescription(__out_ecount(count) wchar_t *const description, const s
 
         case IR::AddrOpndKindDynamicType:
             DumpAddress(address, printToConsole, skipMaskedAddress);
+#if 0 // TODO: OOP JIT, fix this
             {
                 Js::TypeId typeId = ((Js::Type*)address)->GetTypeId();
                 switch (typeId)
@@ -3429,6 +3431,7 @@ Opnd::GetAddrDescription(__out_ecount(count) wchar_t *const description, const s
                     break;
                 }
             }
+#endif
             break;
 
         case AddrOpndKindDynamicFrameDisplay:

+ 19 - 24
lib/Backend/Opnd.h

@@ -505,7 +505,7 @@ public:
 
 private:
     static PropertySymOpnd * New(PropertySym *propertySym, IRType type, Func *func);
-    void Init(uint inlineCacheIndex, intptr_t runtimeInlineCache, Js::PolymorphicInlineCache * runtimePolymorphicInlineCache, Js::ObjTypeSpecFldInfo* objTypeSpecFldInfo, byte polyCacheUtil);
+    void Init(uint inlineCacheIndex, intptr_t runtimeInlineCache, Js::PolymorphicInlineCache * runtimePolymorphicInlineCache, JITObjTypeSpecFldInfo* objTypeSpecFldInfo, byte polyCacheUtil);
 #if DBG
     virtual bool      DbgIsPropertySymOpnd() const override { return true; }
 #endif
@@ -514,9 +514,9 @@ public:
     intptr_t m_runtimeInlineCache;
     Js::PolymorphicInlineCache* m_runtimePolymorphicInlineCache;
 private:
-    Js::ObjTypeSpecFldInfo* objTypeSpecFldInfo;
+    JITObjTypeSpecFldInfo* objTypeSpecFldInfo;
 public:
-    Js::Type* finalType;
+    JITType* finalType;
     BVSparse<JitArenaAllocator>* guardedPropOps;
     BVSparse<JitArenaAllocator>* writeGuards;
     byte m_polyCacheUtil;
@@ -574,7 +574,7 @@ public:
         return this->objTypeSpecFldInfo != nullptr;
     }
 
-    void SetObjTypeSpecFldInfo(Js::ObjTypeSpecFldInfo *const objTypeSpecFldInfo)
+    void SetObjTypeSpecFldInfo(JITObjTypeSpecFldInfo *const objTypeSpecFldInfo)
     {
         this->objTypeSpecFldInfo = objTypeSpecFldInfo;
 
@@ -609,7 +609,7 @@ public:
         return false;
     }
 
-    Js::ObjTypeSpecFldInfo* GetObjTypeSpecInfo() const
+    JITObjTypeSpecFldInfo* GetObjTypeSpecInfo() const
     {
         return this->objTypeSpecFldInfo;
     }
@@ -710,12 +710,6 @@ public:
         return HasObjTypeSpecFldInfo() && this->objTypeSpecFldInfo->IsBeingAdded();
     }
 
-    void SetIsBeingAdded(bool value)
-    {
-        Assert(HasObjTypeSpecFldInfo());
-        this->objTypeSpecFldInfo->SetIsBeingAdded(value);
-    }
-
     bool IsRootObjectNonConfigurableField() const
     {
         return HasObjTypeSpecFldInfo() && this->objTypeSpecFldInfo->IsRootObjectNonConfigurableField();
@@ -756,7 +750,7 @@ public:
         return this->objTypeSpecFldInfo->GetPropertyId();
     }
 
-    Js::DynamicObject* GetProtoObject() const
+    intptr_t GetProtoObject() const
     {
         Assert(HasObjTypeSpecFldInfo());
         return this->objTypeSpecFldInfo->GetProtoObject();
@@ -774,13 +768,13 @@ public:
         return this->objTypeSpecFldInfo->GetFieldValueAsFixedFunctionIfAvailable(i);
     }
 
-    Js::Var GetFieldValueAsFixedData() const
+    intptr_t GetFieldValueAsFixedData() const
     {
         Assert(HasObjTypeSpecFldInfo());
         return this->objTypeSpecFldInfo->GetFieldValueAsFixedDataIfAvailable();
     }
 
-    Js::Var GetFieldValue(uint i)
+    intptr_t GetFieldValue(uint i) const
     {
         Assert(HasObjTypeSpecFldInfo());
         return this->objTypeSpecFldInfo->GetFieldValue(i);
@@ -798,16 +792,16 @@ public:
         return this->objTypeSpecFldInfo->GetFixedFieldCount();
     }
 
-    Js::JitTimeConstructorCache* GetCtorCache() const
+    JITTimeConstructorCache * GetCtorCache() const
     {
         Assert(HasObjTypeSpecFldInfo());
         return this->objTypeSpecFldInfo->GetCtorCache();
     }
 
-    Js::PropertyGuard* GetPropertyGuard() const
+    intptr_t GetPropertyGuardValueAddr() const
     {
         Assert(HasObjTypeSpecFldInfo());
-        return this->objTypeSpecFldInfo->GetPropertyGuard();
+        return this->objTypeSpecFldInfo->GetPropertyGuardValueAddr();
     }
 
     bool IsTypeCheckSeqCandidate() const
@@ -1042,12 +1036,12 @@ public:
         return this->finalType != nullptr;
     }
 
-    Js::Type * GetFinalType() const
+    JITType * GetFinalType() const
     {
         return this->finalType;
     }
 
-    void SetFinalType(Js::Type* type)
+    void SetFinalType(JITType* type)
     {
         Assert(type != nullptr);
         this->finalType = type;
@@ -1108,7 +1102,7 @@ public:
 
     bool IsObjTypeSpecCandidate() const
     {
-        return HasObjTypeSpecFldInfo() && this->objTypeSpecFldInfo->IsObjTypeSpecCandidate();
+        return HasObjTypeSpecFldInfo();
     }
 
     bool IsMonoObjTypeSpecCandidate() const
@@ -1133,13 +1127,13 @@ public:
         return this->objTypeSpecFldInfo->GetTypeId(i);
     }
 
-    Js::Type * GetType() const
+    JITType * GetType() const
     {
         Assert(HasObjTypeSpecFldInfo());
         return this->objTypeSpecFldInfo->GetType();
     }
 
-    Js::Type * GetType(uint i) const
+    JITType * GetType(uint i) const
     {
         Assert(HasObjTypeSpecFldInfo());
         return this->objTypeSpecFldInfo->GetType(i);
@@ -1151,7 +1145,7 @@ public:
         return this->objTypeSpecFldInfo->HasInitialType();
     }
 
-    Js::Type * GetInitialType() const
+    JITType * GetInitialType() const
     {
         Assert(HasObjTypeSpecFldInfo());
         return this->objTypeSpecFldInfo->GetInitialType();
@@ -1163,7 +1157,7 @@ public:
         return this->objTypeSpecFldInfo->GetEquivalentTypeSet();
     }
 
-    Js::Type * GetFirstEquivalentType() const
+    JITType * GetFirstEquivalentType() const
     {
         Assert(HasObjTypeSpecFldInfo());
         return this->objTypeSpecFldInfo->GetFirstEquivalentType();
@@ -1368,6 +1362,7 @@ public:
     AddrOpndKind            GetAddrOpndKind() const { return addrOpndKind; }
     void                    SetAddress(Js::Var address, AddrOpndKind addrOpndKind);
 public:
+    void *                  m_metadata;
     Js::Var                 m_address;
     bool                    m_dontEncode: 1;
     bool                    m_isFunction: 1;

+ 7 - 1
lib/Backend/ScriptContextInfo.cpp

@@ -5,7 +5,7 @@
 
 #include "Backend.h"
 
-ScriptContextInfo::ScriptContextInfo(ScriptContextData * contextData) :
+ScriptContextInfo::ScriptContextInfo(ScriptContextDataIDL * contextData) :
     m_contextData(*contextData),
     m_isPRNGSeeded(false),
     m_activeJITCount(0)
@@ -164,6 +164,12 @@ ScriptContextInfo::GetRecyclerAddr() const
     return m_contextData.recyclerAddr;
 }
 
+intptr_t
+ScriptContextInfo::GetBuiltinFunctionsBaseAddr() const
+{
+    return m_contextData.builtinFunctionsBaseAddr;
+}
+
 intptr_t
 ScriptContextInfo::GetAddr() const
 {

+ 3 - 2
lib/Backend/ScriptContextInfo.h

@@ -10,7 +10,7 @@ typedef JsUtil::BaseDictionary<intptr_t, IR::JnHelperMethod, HeapAllocator, Powe
 class ScriptContextInfo
 {
 public:
-    ScriptContextInfo(ScriptContextData * contextData);
+    ScriptContextInfo(ScriptContextDataIDL * contextData);
     intptr_t GetNullAddr() const;
     intptr_t GetUndefinedAddr() const;
     intptr_t GetTrueAddr() const;
@@ -36,6 +36,7 @@ public:
     intptr_t GetLibraryAddr() const;
     intptr_t GetNumberAllocatorAddr() const;
     intptr_t GetRecyclerAddr() const;
+    intptr_t GetBuiltinFunctionsBaseAddr() const;
 
     intptr_t GetAddr() const;
 
@@ -51,7 +52,7 @@ public:
     void EndJIT();
     bool IsJITActive();
 private:
-    ScriptContextData m_contextData;
+    ScriptContextDataIDL m_contextData;
     // TODO: OOP JIT, set this when we initialize PRNG
     bool m_isPRNGSeeded;
 

+ 3 - 3
lib/Backend/ThreadContextInfo.cpp

@@ -4,7 +4,7 @@
 //-------------------------------------------------------------------------------------------------------
 #include "Backend.h"
 
-ThreadContextInfo::ThreadContextInfo(ThreadContextData * data) :
+ThreadContextInfo::ThreadContextInfo(ThreadContextDataIDL * data) :
     m_threadContextData(*data),
     m_policyManager(true),
     m_pageAlloc(&m_policyManager, Js::Configuration::Global.flags, PageAllocatorType_BGJIT,
@@ -275,13 +275,13 @@ ThreadContextInfo::GetDebugScriptIdWhenSetAddr() const
 ptrdiff_t
 ThreadContextInfo::GetChakraBaseAddressDifference() const
 {
-    return m_jitChakraBaseAddress - GetRuntimeChakraBaseAddress();
+    return GetRuntimeChakraBaseAddress() - m_jitChakraBaseAddress;
 }
 
 ptrdiff_t
 ThreadContextInfo::GetCRTBaseAddressDifference() const
 {
-    return m_jitCRTBaseAddress - GetRuntimeCRTBaseAddress();
+    return GetRuntimeCRTBaseAddress() - m_jitCRTBaseAddress;
 }
 
 bool

+ 5 - 4
lib/Backend/ThreadContextInfo.h

@@ -9,7 +9,7 @@
 class ThreadContextInfo
 {
 public:
-    ThreadContextInfo(ThreadContextData * data);
+    ThreadContextInfo(ThreadContextDataIDL * data);
 
     intptr_t GetNullFrameDisplayAddr() const;
     intptr_t GetStrictNullFrameDisplayAddr() const;
@@ -78,15 +78,16 @@ private:
     AllocationPolicyManager m_policyManager;
     CodeGenAllocators m_codeGenAlloc;
 
-    ThreadContextData m_threadContextData;
+    ThreadContextDataIDL m_threadContextData;
 
     intptr_t m_jitChakraBaseAddress;
     intptr_t m_jitCRTBaseAddress;
     bool m_isAllJITCodeInPreReservedRegion;
 };
 
+// TODO: OOP JIT, is there any issue when crossing over 2^31/2^63?
 #define SHIFT_ADDR(context, address) \
-    (intptr_t)address - context->GetChakraBaseAddressDifference()
+    (intptr_t)address + context->GetChakraBaseAddressDifference()
 
 #define SHIFT_CRT_ADDR(context, address) \
-    (intptr_t)address - context->GetCRTBaseAddressDifference()
+    (intptr_t)address + context->GetCRTBaseAddressDifference()

+ 4 - 4
lib/JITClient/JITManager.cpp

@@ -194,7 +194,7 @@ JITManager::DisconnectRpcServer()
 
 HRESULT
 JITManager::InitializeThreadContext(
-    __in ThreadContextData * data,
+    __in ThreadContextDataIDL * data,
     __out intptr_t * threadContextInfoAddress)
 {
     HRESULT hr = E_FAIL;
@@ -231,7 +231,7 @@ JITManager::CleanupThreadContext(
 
 HRESULT
 JITManager::InitializeScriptContext(
-    __in ScriptContextData * data,
+    __in ScriptContextDataIDL * data,
     __out intptr_t * scriptContextInfoAddress)
 {
     HRESULT hr = E_FAIL;
@@ -287,10 +287,10 @@ JITManager::FreeAllocation(
 
 HRESULT
 JITManager::RemoteCodeGenCall(
-    __in CodeGenWorkItemJITData *workItemData,
+    __in CodeGenWorkItemIDL *workItemData,
     __in intptr_t threadContextInfoAddress,
     __in intptr_t scriptContextInfoAddress,
-    __out JITOutputData *jitData)
+    __out JITOutputIDL *jitData)
 {
     HRESULT hr = E_FAIL;
     RpcTryExcept

+ 4 - 4
lib/JITClient/JITManager.h

@@ -13,14 +13,14 @@ public:
     void DisconnectRpcServer();
 
     HRESULT InitializeThreadContext(
-        __in ThreadContextData * data,
+        __in ThreadContextDataIDL * data,
         __out intptr_t *threadContextInfoAddress);
 
     HRESULT CleanupThreadContext(
         __in intptr_t threadContextInfoAddress);
 
     HRESULT InitializeScriptContext(
-        __in ScriptContextData * data,
+        __in ScriptContextDataIDL * data,
         __out intptr_t *scriptContextInfoAddress);
 
     HRESULT CleanupScriptContext(
@@ -31,10 +31,10 @@ public:
         __in intptr_t address);
 
     HRESULT RemoteCodeGenCall(
-        __in CodeGenWorkItemJITData *workItemData,
+        __in CodeGenWorkItemIDL *workItemData,
         __in intptr_t threadContextInfoAddress,
         __in intptr_t scriptContextInfoAddress,
-        __out JITOutputData *jitData);
+        __out JITOutputIDL *jitData);
 
 private:
 

+ 153 - 83
lib/JITIDL/ChakraJIT.idl

@@ -8,102 +8,162 @@ import "wtypes.idl";
 // TODO: OOP JIT, how do we make this better?
 const int VTABLE_COUNT = 40;
 
-typedef struct ObjTypeSpecFldData
+typedef struct TypeHandlerIDL
 {
-    // TODO: OOP JIT we may want to copy some of the data in these pointers
-    __int3264 protoObject;
-    __int3264 propertyGuard;
-    __int3264 typeSet;
-    __int3264 initialType;
-    __int3264 ctorCache;
-    __int3264 fixedFieldInfoArray;
+    boolean isObjectHeaderInlinedTypeHandler;
+    boolean isLocked;
+
+    unsigned short inlineSlotCapacity;
+    unsigned short offsetOfInlineSlots;
+
+    int slotCapacity;
+} TypeHandlerIDL;
+
+typedef struct TypeIDL
+{
+    unsigned char flags;
+    boolean isShared;
 
-    int propertyId;
     int typeId;
-    unsigned int id;
 
+    __int3264 libAddr;
+    __int3264 protoAddr;
+    __int3264 entrypointAddr;
+    __int3264 propertyCacheAddr;
+    __int3264 addr;
+
+    TypeHandlerIDL handler;
+} TypeIDL;
+
+typedef struct EquivalentTypeSetIDL
+{
+    boolean sortedAndDuplicatesRemoved;
+    unsigned short count;
+    [size_is(count)] TypeIDL ** types;
+} EquivalentTypeSetIDL;
+
+typedef struct FixedFieldIDL
+{
+    boolean nextHasSameFixedField;
+    TypeIDL type;
+    __int3264 fieldValue;
+} FixedFieldIDL;
+
+typedef struct JITTimeConstructorCacheIDL
+{
+    boolean skipNewScObject;
+    boolean ctorHasNoExplicitReturnValue;
+    boolean typeIsFinal;
+    boolean isUsed;
+
+    short inlineSlotCount;
+
+    int slotCount;
+
+    TypeIDL type;
+
+    __int3264 runtimeCacheAddr;
+    __int3264 runtimeCacheGuardAddr;
+} JITTimeConstructorCacheIDL;
+
+typedef struct ObjTypeSpecFldIDL
+{
+    // TODO: OOP JIT we may want to copy some of the data in these pointers
     unsigned short flags;
     unsigned short slotIndex;
     unsigned short fixedFieldCount;
-} ObjTypeSpecFldData;
-
-typedef struct BVUnitData
+    int propertyId;
+    int typeId;
+    unsigned int id;
+    __int3264 protoObjectAddr;
+    __int3264 propertyGuardValueAddr;
+    EquivalentTypeSetIDL * typeSet;
+    TypeIDL * initialType;
+    JITTimeConstructorCacheIDL * ctorCache;
+    [size_is(fixedFieldCount)] FixedFieldIDL * fixedFieldInfoArray;
+} ObjTypeSpecFldIDL;
+
+typedef struct BVUnitIDL
 {
     unsigned __int3264 word;
-} BVUnitData;
+} BVUnitIDL;
 
-typedef struct BVFixedData
+typedef struct BVFixedIDL
 {
     unsigned int len;
-    [size_is(len)] BVUnitData data[*];
-} BVFixedData;
+    [size_is(len)] BVUnitIDL data[*];
+} BVFixedIDL;
 
-typedef struct CallSiteData
+typedef struct CallSiteIDL
 {
     unsigned short bitFields;
     unsigned short returnType;
     unsigned int ldFldInlineCacheId;
     unsigned int sourceId;
     unsigned int functionId;
-} CallSiteData;
+} CallSiteIDL;
 
-typedef struct ThisData
+typedef struct ThisIDL
 {
     unsigned short valueType;
     byte thisType;
-} ThisData;
+} ThisIDL;
 
-typedef struct FldData
+typedef struct FldIDL
 {
     unsigned short valueType;
     byte flags;
     byte polymorphicInlineCacheUtilization;
-} FldData;
+} FldIDL;
 
-typedef struct ArrayCallSiteData
+typedef struct ArrayCallSiteIDL
 {
     byte bits;
     unsigned int functionNumber;
     unsigned short callSiteNumber;
-} ArrayCallSiteData;
+} ArrayCallSiteIDL;
 
-typedef struct LdElemData
+typedef struct LdElemIDL
 {
     unsigned short arrayType;
     unsigned short elemType;
     byte bits;
-} LdElemData;
+} LdElemIDL;
 
-typedef struct StElemData
+typedef struct StElemIDL
 {
     unsigned short arrayType;
     byte bits;
-} StElemData;
+} StElemIDL;
 
-typedef struct ProfileData
+typedef struct ProfileDataIDL
 {
+    byte implicitCallFlags;
+
     int flags;
 
-    BVFixedData * loopFlags;
+    ThisIDL thisData;
+
+    BVFixedIDL * loopFlags;
 
     unsigned short profiledLdElemCount;
-    [size_is(profiledLdElemCount)] LdElemData * ldElemData;
+    [size_is(profiledLdElemCount)] LdElemIDL * ldElemData;
 
     unsigned short profiledStElemCount;
-    [size_is(profiledStElemCount)] StElemData * stElemData;
+    [size_is(profiledStElemCount)] StElemIDL * stElemData;
 
     unsigned short profiledArrayCallSiteCount;
-    [size_is(profiledArrayCallSiteCount)] ArrayCallSiteData * arrayCallSiteData;
+    [size_is(profiledArrayCallSiteCount)] ArrayCallSiteIDL * arrayCallSiteData;
 
     // TODO: michhol OOP JIT, share counts with body
     unsigned int inlineCacheCount;
-    [size_is(inlineCacheCount)] FldData * fldData;
+    [size_is(inlineCacheCount)] FldIDL * fldData;
 
     unsigned short profiledSlotCount;
     [size_is(profiledSlotCount)] unsigned short * slotData;
 
     unsigned short profiledCallSiteCount;
-    [size_is(profiledCallSiteCount)] CallSiteData * callSiteData;
+    [size_is(profiledCallSiteCount)] CallSiteIDL * callSiteData;
 
     unsigned short profiledReturnTypeCount;
     [size_is(profiledReturnTypeCount)] unsigned short * returnTypeData;
@@ -120,13 +180,10 @@ typedef struct ProfileData
     unsigned int loopCount;
     [size_is(loopCount)] byte * loopImplicitCallFlags;
 
-    ThisData thisData;
-
-    byte implicitCallFlags;
+    __int3264 arrayCallSiteDataAddr;
+} ProfileDataIDL;
 
-} ProfileData;
-
-typedef struct ThreadContextData
+typedef struct ThreadContextDataIDL
 {
     boolean isThreadBound;
     __int3264 processHandle;
@@ -141,9 +198,9 @@ typedef struct ThreadContextData
     __int3264 debugStepTypeAddr;
     __int3264 debugFrameAddressAddr;
     __int3264 debugScriptIdWhenSetAddr;
-} ThreadContextData;
+} ThreadContextDataIDL;
 
-typedef struct ScriptContextData
+typedef struct ScriptContextDataIDL
 {
     boolean isRecyclerVerifyEnabled;
     unsigned int recyclerVerifyPad;
@@ -174,27 +231,28 @@ typedef struct ScriptContextData
     __int3264 floatArraySetElementFastPathVtableAddr;
     __int3264 numberAllocatorAddr;
     __int3264 recyclerAddr;
-} ScriptContextData;
+    __int3264 builtinFunctionsBaseAddr;
+} ScriptContextDataIDL;
 
-typedef struct SmallSpanSequenceData
+typedef struct SmallSpanSequenceIDL
 {
     int baseValue;
     unsigned int statementLength;
     [size_is(statementLength)] unsigned int * statementBuffer;
     unsigned int actualOffsetLength; // REVIEW: are lengths the same?
     [size_is(actualOffsetLength)] unsigned int * actualOffsetList;
-} SmallSpanSequenceData;
+} SmallSpanSequenceIDL;
 
-typedef struct JITLoopHeader
+typedef struct JITLoopHeaderIDL
 {
     boolean isNested;
     boolean isInTry;
     unsigned int interpretCount;
     unsigned int startOffset;
     unsigned int endOffset;
-} JITLoopHeader;
+} JITLoopHeaderIDL;
 
-typedef struct AsmJsJITData
+typedef struct AsmJsDataIDL
 {
     boolean isHeapBufferConst;
     boolean usesHeapBuffer;
@@ -219,16 +277,16 @@ typedef struct AsmJsJITData
     int floatByteOffset;
     int simdByteOffset;
     int totalSizeInBytes;
-} AsmJsJITData;
+} AsmJsDataIDL;
 
-typedef struct FunctionJITRuntimeData
+typedef struct FunctionJITRuntimeIDL
 {
     unsigned int clonedCacheCount;
     [size_is(clonedCacheCount)] __int3264 * clonedInlineCaches;
-} FunctionJITRuntimeData;
+} FunctionJITRuntimeIDL;
 
 // FunctionBody fields, read only in JIT, gathered in foreground
-typedef struct FunctionBodyJITData
+typedef struct FunctionBodyDataIDL
 {
     byte flags;
 
@@ -244,6 +302,7 @@ typedef struct FunctionBodyJITData
     boolean inlineCachesOnFunctionObject;
     boolean doInterruptProbe;
     boolean isGlobalFunc;
+    boolean isInlineApplyDisabled;
     boolean doJITLoopBody;
     boolean disableInlineSpread;
     boolean hasNestedLoop;
@@ -276,7 +335,7 @@ typedef struct FunctionBodyJITData
     unsigned int recursiveCallSiteCount;
     unsigned int isInstInlineCacheCount; // TODO: only used in Assert
 
-    SmallSpanSequenceData statementMap;
+    SmallSpanSequenceIDL statementMap;
 
     unsigned int byteCodeLength;
     [size_is(byteCodeLength)] byte * byteCodeBuffer;
@@ -291,7 +350,7 @@ typedef struct FunctionBodyJITData
     [size_is(inlineCacheCount)] __int3264 * inlineCaches;
 
     unsigned int loopHeaderArrayLength;
-    [size_is(loopHeaderArrayLength)] JITLoopHeader * loopHeaders;
+    [size_is(loopHeaderArrayLength)] JITLoopHeaderIDL * loopHeaders;
 
     unsigned int referencedPropertyIdCount;
     [size_is(referencedPropertyIdCount)] int * referencedPropertyIdMap;
@@ -300,11 +359,11 @@ typedef struct FunctionBodyJITData
     [size_is(nameLength)] wchar_t * displayName;
 
     unsigned int runtimeDataCount; // only needed for topfunc?
-    [size_is(runtimeDataCount)] FunctionJITRuntimeData * profiledRuntimeData;
+    [size_is(runtimeDataCount)] FunctionJITRuntimeIDL * profiledRuntimeData;
 
-    ProfileData * profileData;
+    ProfileDataIDL * profileData;
 
-    AsmJsJITData * asmJsData;
+    AsmJsDataIDL * asmJsData;
 
     __int3264 loopHeaderArrayAddr;
     __int3264 functionBodyAddr;
@@ -315,25 +374,26 @@ typedef struct FunctionBodyJITData
     __int3264 regAllocLoadCountAddr;
     __int3264 callCountStatsAddr;
     __int3264 nestedFuncArrayAddr;
-} FunctionBodyJITData;
+    __int3264 auxArrayBufferAddr;
+} FunctionBodyDataIDL;
 
 // EntryPointInfo fields, read/write in JIT
-typedef struct EntryPointInfoJITWriteData
+typedef struct EntryPointInfoOutputIDL
 {
     boolean hasJittedStackClosure;
     int localVarSlotsOffset; // FunctionEntryPointInfo only
     int localVarChangedOffset; // FunctionEntryPointInfo only
     unsigned int frameHeight;
-} EntryPointInfoJITWriteData;
+} EntryPointInfoOutputIDL;
 
 // FunctionBody fields, written to from JIT
-typedef struct FunctionBodyJITWriteData
+typedef struct FunctionBodyOutputIDL
 {
     boolean hasBailoutInstr;
     unsigned short argUsedForBranch;
-} FunctionBodyJITWriteData;
+} FunctionBodyOutputIDL;
 
-typedef struct FunctionJITTimeData
+typedef struct FunctionJITTimeDataIDL
 {
     boolean isAggressiveInliningEnabled;
     boolean isInlined;
@@ -341,18 +401,27 @@ typedef struct FunctionJITTimeData
     __int3264 functionInfoAddr;
     __int3264 callsCountAddress;
     __int3264 weakFuncRef;
-    FunctionBodyJITData * bodyData; // TODO: oop jit, can these repeat, should we share?
+    FunctionBodyDataIDL * bodyData; // TODO: oop jit, can these repeat, should we share?
+
+    BVFixedIDL * inlineesBv;
 
-    BVFixedData * inlineesBv;
+    unsigned int sharedPropGuardCount;
+    [size_is(sharedPropGuardCount)] int * sharedPropertyGuards;
+
+
+    unsigned int globalObjTypeSpecFldInfoCount;
+    [size_is(globalObjTypeSpecFldInfoCount)] ObjTypeSpecFldIDL ** globalObjTypeSpecFldInfoArray;
 
     unsigned int inlineeCount;
-    [size_is(inlineeCount)] struct FunctionJITTimeData ** inlinees;
+    [size_is(inlineeCount)] struct FunctionJITTimeDataIDL ** inlinees;
     unsigned int ldFldInlineeCount;
-    [size_is(ldFldInlineeCount)] struct FunctionJITTimeData ** ldFldInlinees;
+    [size_is(ldFldInlineeCount)] struct FunctionJITTimeDataIDL ** ldFldInlinees;
+
     // ldFldInlineeCount == inlineCacheCount
-    [size_is(ldFldInlineeCount)] ObjTypeSpecFldData ** objTypeSpecFldInfoArray;
-    struct FunctionJITTimeData * next;
-} FunctionJITTimeData;
+    [size_is(ldFldInlineeCount)] ObjTypeSpecFldIDL ** objTypeSpecFldInfoArray;
+
+    struct FunctionJITTimeDataIDL * next;
+} FunctionJITTimeDataIDL;
 
 typedef struct XProcNumberPageSegment
 {
@@ -370,8 +439,9 @@ typedef struct XProcNumberPageSegment
 } XProcNumberPageSegment;
 
 // CodeGenWorkItem fields, read only in JIT
-typedef struct CodeGenWorkItemJITData
+typedef struct CodeGenWorkItemIDL
 {
+    boolean hasSharedPropGuards;
     boolean isJitInDebugMode;  // Whether JIT is in debug mode for this work item.
     byte type;
     char jitMode;
@@ -379,9 +449,9 @@ typedef struct CodeGenWorkItemJITData
     unsigned int loopNumber;
     XProcNumberPageSegment xProcNumberPageSegment;
 
-    FunctionJITTimeData * jitData;
+    FunctionJITTimeDataIDL * jitData;
     __int3264 nativeDataAddr;
-} CodeGenWorkItemJITData;
+} CodeGenWorkItemIDL;
 
 typedef struct NativeDataFixupEntry
 {
@@ -413,15 +483,15 @@ typedef struct NativeDataBuffer
 } NativeDataBuffer;
 
 // Fields that JIT modifies
-typedef struct JITOutputData
+typedef struct JITOutputIDL
 {
     boolean isInPrereservedRegion;
 
     unsigned short pdataCount;
     unsigned short xdataSize;
 
-    EntryPointInfoJITWriteData writeableEPData;
-    FunctionBodyJITWriteData writeableBodyData;
+    EntryPointInfoOutputIDL writeableEPData;
+    FunctionBodyOutputIDL writeableBodyData;
 
     unsigned int codeSize;
 
@@ -435,7 +505,7 @@ typedef struct JITOutputData
     
     unsigned int inlineeFrameOffsetArrayOffset;
     unsigned int inlineeFrameOffsetArrayCount;
-} JITOutputData;
+} JITOutputIDL;
 
 [
     uuid(ead694ed-2243-44cb-a9dc-85d3ba934dab),
@@ -447,7 +517,7 @@ interface IChakraJIT
 
     HRESULT InitializeThreadContext(
         [in] handle_t binding,
-        [in] ThreadContextData * threadData,
+        [in] ThreadContextDataIDL * threadData,
         [out] __int3264 * threadContextInfoAddress);
 
     HRESULT CleanupThreadContext(
@@ -456,7 +526,7 @@ interface IChakraJIT
 
     HRESULT InitializeScriptContext(
         [in] handle_t binding,
-        [in] ScriptContextData * scriptContextData,
+        [in] ScriptContextDataIDL * scriptContextData,
         [out] __int3264 * scriptContextInfoAddress);
 
     HRESULT CleanupScriptContext(
@@ -472,7 +542,7 @@ interface IChakraJIT
         [in] handle_t binding,
         [in] __int3264 threadContextInfoAddress,
         [in] __int3264 scriptContextInfoAddress,
-        [in] CodeGenWorkItemJITData * workItemData,
-        [out] JITOutputData * jitData);
+        [in] CodeGenWorkItemIDL * workItemData,
+        [out] JITOutputIDL * jitData);
 
 }

+ 4 - 4
lib/JITServer/JITServer.cpp

@@ -85,7 +85,7 @@ ServerShutdown(/* [in] */ handle_t binding)
 HRESULT
 ServerInitializeThreadContext(
     /* [in] */ handle_t binding,
-    /* [in] */ __RPC__in ThreadContextData * threadContextData,
+    /* [in] */ __RPC__in ThreadContextDataIDL * threadContextData,
     /* [out] */ __RPC__out __int3264 *threadContextRoot)
 {
     AUTO_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow));
@@ -116,7 +116,7 @@ ServerCleanupThreadContext(
 HRESULT
 ServerInitializeScriptContext(
     /* [in] */ handle_t binding,
-    /* [in] */ __RPC__in ScriptContextData * scriptContextData,
+    /* [in] */ __RPC__in ScriptContextDataIDL * scriptContextData,
     /* [out] */ __RPC__out __int3264 * scriptContextInfoAddress)
 {
     AUTO_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow));
@@ -153,8 +153,8 @@ ServerRemoteCodeGen(
     /* [in] */ handle_t binding,
     /* [in] */ __int3264 threadContextInfoAddress,
     /* [in] */ __int3264 scriptContextInfoAddress,
-    /* [in] */ CodeGenWorkItemJITData *workItemData,
-    /* [out] */ JITOutputData *jitData)
+    /* [in] */ CodeGenWorkItemIDL *workItemData,
+    /* [out] */ JITOutputIDL *jitData)
 {
     UNREFERENCED_PARAMETER(binding);
     AUTO_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow));

+ 2 - 2
lib/Runtime/Base/FunctionBody.cpp

@@ -8246,11 +8246,11 @@ namespace Js
                 bool isNeeded = TryGetSharedPropertyGuard(propertyId, sharedPropertyGuard);
                 bool isValid = isNeeded ? sharedPropertyGuard->IsValid() : false;
                 int entryCacheIndex = 0;
-                while (entry->caches[entryCacheIndex] != nullptr)
+                while (entry->caches[entryCacheIndex] != 0)
                 {
                     if (isNeeded)
                     {
-                        Js::ConstructorCache* cache = entry->caches[entryCacheIndex];
+                        Js::ConstructorCache* cache = (Js::ConstructorCache*)(entry->caches[entryCacheIndex]);
                         // We use the shared cache here to make sure the conditions we assumed didn't change while we were JIT-ing.
                         // If they did, we proactively invalidate the cache here, so that we bail out if we try to call this code.
                         if (isValid)

+ 10 - 9
lib/Runtime/Base/FunctionBody.h

@@ -118,10 +118,10 @@ namespace Js
     class JitTypePropertyGuard : public Js::JitIndexedPropertyGuard
     {
     public:
-        JitTypePropertyGuard(Js::Type* type, int index):
-            JitIndexedPropertyGuard(reinterpret_cast<intptr_t>(type), index) {}
+        JitTypePropertyGuard(intptr_t typeAddr, int index):
+            JitIndexedPropertyGuard(typeAddr, index) {}
 
-        Js::Type* GetType() const { return reinterpret_cast<Js::Type*>(this->GetValue()); }
+        intptr_t GetTypeAddr() const { return this->GetValue(); }
 
         void Fixup(NativeCodeData::DataChunk* chunkList)
         {
@@ -184,7 +184,7 @@ namespace Js
     struct CtorCacheGuardTransferEntry
     {
         PropertyId propertyId;
-        ConstructorCache* caches[0];
+        intptr_t caches[0];
 
         CtorCacheGuardTransferEntry(): propertyId(Js::Constants::NoProperty) {}
     };
@@ -223,14 +223,14 @@ namespace Js
         uint32 objTypeSpecFldId;
 
     public:
-        JitEquivalentTypeGuard(Type* type, int index, uint32 objTypeSpecFldId):
-            JitIndexedPropertyGuard(reinterpret_cast<intptr_t>(type), index), cache(nullptr), objTypeSpecFldId(objTypeSpecFldId) {}
+        JitEquivalentTypeGuard(intptr_t typeAddr, int index, uint32 objTypeSpecFldId):
+            JitIndexedPropertyGuard(typeAddr, index), cache(nullptr), objTypeSpecFldId(objTypeSpecFldId) {}
 
-        Js::Type* GetType() const { return reinterpret_cast<Js::Type*>(this->GetValue()); }
+        intptr_t GetTypeAddr() const { return this->GetValue(); }
 
-        void SetType(const Js::Type* type)
+        void SetTypeAddr(const intptr_t typeAddr)
         {
-            this->SetValue(reinterpret_cast<intptr_t>(type));
+            this->SetValue(typeAddr);
         }
 
         uint32 GetObjTypeSpecFldId() const
@@ -906,6 +906,7 @@ namespace Js
         Js::PropertyGuard* RegisterSharedPropertyGuard(Js::PropertyId propertyId, ScriptContext* scriptContext);
         bool HasSharedPropertyGuards() { return this->sharedPropertyGuards != nullptr; }
         bool HasSharedPropertyGuard(Js::PropertyId propertyId);
+        const SharedPropertyGuardDictionary * GetSharedPropertyGuards() const { return sharedPropertyGuards; }
         bool TryGetSharedPropertyGuard(Js::PropertyId propertyId, Js::PropertyGuard*& guard);
         void RecordTypeGuards(int propertyGuardCount, TypeGuardTransferEntry* typeGuardTransferRecord, size_t typeGuardTransferPlusSize);
         void RecordCtorCacheGuards(CtorCacheGuardTransferEntry* ctorCacheTransferRecord, size_t ctorCacheTransferPlusSize);

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

@@ -407,7 +407,7 @@ namespace Js
 
         void InitializeRemoteScriptContext()
         {
-            ScriptContextData contextData;
+            ScriptContextDataIDL contextData;
             contextData.nullAddr = (intptr_t)GetLibrary()->GetNull();
             contextData.undefinedAddr = (intptr_t)GetLibrary()->GetUndefined();
             contextData.trueAddr = (intptr_t)GetLibrary()->GetTrue();

+ 1 - 1
lib/Runtime/Base/ThreadContext.cpp

@@ -1818,7 +1818,7 @@ ThreadContext::SetJITConnectionInfo(DWORD processId, UUID connectionId)
     // TODO: OOP JIT, check hresults
     m_codeGenManager.ConnectRpcServer(m_jitProcessId, m_jitConnectionId);
     // TODO: OOP JIT, do we need to do this initialization in a different place?
-    ThreadContextData contextData;
+    ThreadContextDataIDL contextData;
     HANDLE targetHandle;
     HANDLE jitProcHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, m_jitProcessId);
     BOOL succeeded = DuplicateHandle(

+ 2 - 2
lib/Runtime/Language/FunctionCodeGenJitTimeData.cpp

@@ -20,7 +20,7 @@ namespace Js
         if (GetFunctionInfo()->HasBody())
         {
             Recycler * recycler = functionInfo->GetFunctionProxy()->GetScriptContext()->GetRecycler();
-            this->bodyData = RecyclerNewStructZ(recycler, FunctionBodyJITData);
+            this->bodyData = RecyclerNewStructZ(recycler, FunctionBodyDataIDL);
             JITTimeFunctionBody::InitializeJITFunctionData(recycler, GetFunctionBody(), this->bodyData);
         }
     }
@@ -30,7 +30,7 @@ namespace Js
         return this->functionInfo;
     }
 
-    FunctionBodyJITData *FunctionCodeGenJitTimeData::GetJITBody() const
+    FunctionBodyDataIDL *FunctionCodeGenJitTimeData::GetJITBody() const
     {
         return this->bodyData;
     }

+ 7 - 4
lib/Runtime/Language/FunctionCodeGenJitTimeData.h

@@ -6,7 +6,7 @@
 
 #if ENABLE_NATIVE_CODEGEN
 // forward ref
-struct FunctionBodyJITData;
+struct FunctionBodyDataIDL;
 
 namespace Js
 {
@@ -16,7 +16,7 @@ namespace Js
     class FunctionCodeGenJitTimeData
     {
     private:
-        FunctionBodyJITData * bodyData;
+        FunctionBodyDataIDL * bodyData;
         FunctionInfo *const functionInfo;
 
         // Point's to an entry point if the work item needs the entry point alive- null for cases where the entry point isn't used
@@ -64,8 +64,8 @@ namespace Js
 
         FunctionInfo *GetFunctionInfo() const;
         FunctionBody *GetFunctionBody() const;
-        FunctionBodyJITData *GetJITBody() const;
-        FunctionCodeGenJitTimeData *GetNext() const { return next; };
+        FunctionBodyDataIDL *GetJITBody() const;
+        FunctionCodeGenJitTimeData *GetNext() const { return next; }
 
         const ObjTypeSpecFldInfoArray* GetObjTypeSpecFldInfoArray() const { return &this->objTypeSpecFldInfoArray; }
         ObjTypeSpecFldInfoArray* GetObjTypeSpecFldInfoArray() { return &this->objTypeSpecFldInfoArray; }
@@ -102,6 +102,9 @@ namespace Js
         // This can return null, if the functionInfo doesn't match.
         const FunctionCodeGenJitTimeData *GetJitTimeDataFromFunctionInfo(FunctionInfo *polyFunctionInfo) const;
 
+        uint GetGlobalObjTypeSpecFldInfoCount() const { return this->globalObjTypeSpecFldInfoCount; }
+        ObjTypeSpecFldInfo** GetGlobalObjTypeSpecFldInfoArray() const {return this->globalObjTypeSpecFldInfoArray; }
+
         ObjTypeSpecFldInfo* GetGlobalObjTypeSpecFldInfo(uint propertyInfoId) const
         {
             Assert(this->globalObjTypeSpecFldInfoArray != nullptr && propertyInfoId < this->globalObjTypeSpecFldInfoCount);

+ 2 - 2
lib/Runtime/Language/InlineCache.cpp

@@ -909,7 +909,7 @@ namespace Js
     }
 #endif
 
-    bool EquivalentTypeSet::Contains(const Js::Type * type, uint16* pIndex) const
+    bool EquivalentTypeSet::Contains(const JITType * type, uint16* pIndex) const
     {
         for (uint16 ti = 0; ti < this->count; ti++)
         {
@@ -1010,7 +1010,7 @@ namespace Js
             uint16 j = i;
             while (j > 0 && (this->types[j - 1] > this->types[j]))
             {
-                Type* tmp = this->types[j];
+                JITType * tmp = this->types[j];
                 this->types[j] = this->types[j - 1];
                 this->types[j - 1] = tmp;
             }

+ 14 - 6
lib/Runtime/Language/InlineCache.h

@@ -17,6 +17,10 @@
 #define PolymorphicInlineCacheShift 6 // On 64 bit architectures, the least 6 significant bits of a DynamicTypePointer is 0
 #endif
 
+// TODO: OOP JIT, move equiv set to backend?
+// forward decl
+class JITType;
+
 namespace Js
 {
     enum CacheType : byte
@@ -524,12 +528,12 @@ namespace Js
     class EquivalentTypeSet
     {
     private:
-        Type** types;
-        uint16 count;
         bool sortedAndDuplicatesRemoved;
+        uint16 count;
+        JITType ** types;
 
     public:
-        EquivalentTypeSet(Type** types, uint16 count)
+        EquivalentTypeSet(JITType ** types, uint16 count)
             : types(types), count(count), sortedAndDuplicatesRemoved(false) {}
 
         uint16 GetCount() const
@@ -537,22 +541,26 @@ namespace Js
             return this->count;
         }
 
-        Type* GetFirstType() const
+        JITType * GetFirstType() const
         {
             return GetType(0);
         }
 
-        Type* GetType(uint16 index) const
+        JITType * GetType(uint16 index) const
         {
             Assert(this->types != nullptr && this->count > 0 && index < this->count);
             return this->types[index];
         }
+        JITType ** GetTypes() const
+        {
+            return this->types;
+        }
 
         bool GetSortedAndDuplicatesRemoved() const
         {
             return this->sortedAndDuplicatesRemoved;
         }
-        bool Contains(const Js::Type * type, uint16 * pIndex = nullptr) const;
+        bool Contains(const JITType * type, uint16 * pIndex = nullptr) const;
 
         static bool AreIdentical(EquivalentTypeSet * left, EquivalentTypeSet * right);
         static bool IsSubsetOf(EquivalentTypeSet * left, EquivalentTypeSet * right);

+ 3 - 3
lib/Runtime/Language/JavascriptOperators.cpp

@@ -7911,7 +7911,7 @@ CommonNumber:
             return false;
         }
 
-        if (guard->GetType()->GetScriptContext() != type->GetScriptContext())
+        if (((Js::Type*)guard->GetTypeAddr())->GetScriptContext() != type->GetScriptContext())
         {
             // Can't cache cross-context objects
             return false;
@@ -7929,7 +7929,7 @@ CommonNumber:
         if (type == equivTypes[0] || type == equivTypes[1] || type == equivTypes[2] || type == equivTypes[3] ||
             type == equivTypes[4] || type == equivTypes[5] || type == equivTypes[6] || type == equivTypes[7])
         {
-            guard->SetType(type);
+            guard->SetTypeAddr((intptr_t)type);
             return true;
         }
 
@@ -8053,7 +8053,7 @@ CommonNumber:
             }
         }
 
-        guard->SetType(type);
+        guard->SetTypeAddr((intptr_t)type);
         return true;
     }
 

+ 12 - 7
lib/Runtime/Language/ObjTypeSpecFldInfo.cpp

@@ -4,6 +4,9 @@
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeLanguagePch.h"
 
+#include "JITType.h"
+#include "JITTimeConstructorCache.h"
+
 #if ENABLE_NATIVE_CODEGEN
 namespace Js
 {
@@ -58,7 +61,7 @@ namespace Js
         bool usesAuxSlot = false;
         DynamicObject* prototypeObject = nullptr;
         PropertyGuard* propertyGuard = nullptr;
-        JitTimeConstructorCache* ctorCache = nullptr;
+        JITTimeConstructorCache* ctorCache = nullptr;
         Var fieldValue = nullptr;
         bool keepFieldValue = false;
         bool isFieldValueFixed = false;
@@ -232,7 +235,7 @@ namespace Js
 
                         // We must keep the runtime cache alive as long as this entry point exists and may try to dereference it.
                         entryPoint->RegisterConstructorCache(runtimeConstructorCache, recycler);
-                        ctorCache = RecyclerNew(recycler, JitTimeConstructorCache, functionObject, runtimeConstructorCache);
+                        ctorCache = RecyclerNew(recycler, JITTimeConstructorCache, functionObject, runtimeConstructorCache);
 
                         if (PHASE_TRACE(Js::FixedNewObjPhase, functionBody))
                         {
@@ -323,8 +326,9 @@ namespace Js
         if (forcePoly)
         {
             uint16 typeCount = 1;
-            Js::Type** types = RecyclerNewArray(recycler, Js::Type*, typeCount);
-            types[0] = type;
+            JITType** types = RecyclerNewArray(recycler, JITType*, typeCount);
+            types[0] = RecyclerNew(recycler, JITType);
+            JITType::BuildFromJsType(type, types[0]);
             EquivalentTypeSet* typeSet = RecyclerNew(recycler, EquivalentTypeSet, types, typeCount);
 
             info = RecyclerNew(recycler, ObjTypeSpecFldInfo,
@@ -638,6 +642,7 @@ namespace Js
         Assert(jitTransferData != nullptr);
         if (areEquivalent || areStressEquivalent)
         {
+            JITType** types = RecyclerNewArray(recycler, JITType*, typeCount);
             for (uint16 i = 0; i < typeCount; i++)
             {
                 jitTransferData->AddJitTimeTypeRef(localTypes[i], recycler);
@@ -655,10 +660,10 @@ namespace Js
                         }
                     }
                 }
+                // TODO: OOP JIT, consider putting these inline
+                types[i] = RecyclerNew(recycler, JITType);
+                JITType::BuildFromJsType(localTypes[i], types[i]);
             }
-
-            Js::Type** types = RecyclerNewArray(recycler, Js::Type*, typeCount);
-            memcpy(types, localTypes, typeCount * sizeof(Js::Type*));
             typeSet = RecyclerNew(recycler, EquivalentTypeSet, types, typeCount);
         }
 

+ 85 - 164
lib/Runtime/Language/ObjTypeSpecFldInfo.h

@@ -6,92 +6,12 @@
 #pragma once
 
 #if ENABLE_NATIVE_CODEGEN
-namespace Js
-{
-    struct JitTimeConstructorCache
-    {
-        // TODO (FixedNewObj): Consider making these private and provide getters to ensure the values are not changed.
-        const JavascriptFunction* constructor;
-        ConstructorCache* runtimeCache;
-
-        const ScriptContext* scriptContext;
-        const DynamicType* type;
-        BVSparse<JitArenaAllocator>* guardedPropOps;
-        int slotCount;
-        int16 inlineSlotCount;
-
-        bool skipNewScObject;
-        bool ctorHasNoExplicitReturnValue;
-        bool typeIsFinal;
-        bool isUsed;
-
-    public:
-        JitTimeConstructorCache(const JavascriptFunction* constructor, ConstructorCache* runtimeCache)
-        {
-            Assert(constructor != nullptr);
-            Assert(runtimeCache != nullptr);
-            this->constructor = constructor;
-            this->runtimeCache = runtimeCache;
-            this->type = runtimeCache->content.type;
-            this->guardedPropOps = nullptr;
-            this->scriptContext = runtimeCache->content.scriptContext;
-            this->slotCount = runtimeCache->content.slotCount;
-            this->inlineSlotCount = runtimeCache->content.inlineSlotCount;
-            this->skipNewScObject = runtimeCache->content.skipDefaultNewObject;
-            this->ctorHasNoExplicitReturnValue = runtimeCache->content.ctorHasNoExplicitReturnValue;
-            this->typeIsFinal = runtimeCache->content.typeIsFinal;
-            this->isUsed = false;
-        }
 
-        JitTimeConstructorCache(const JitTimeConstructorCache* other)
-        {
-            Assert(other != nullptr);
-            Assert(other->constructor != nullptr);
-            Assert(other->runtimeCache != nullptr);
-            this->constructor = other->constructor;
-            this->runtimeCache = other->runtimeCache;
-            this->type = other->type;
-            this->guardedPropOps = nullptr;
-            this->scriptContext = other->scriptContext;
-            this->slotCount = other->slotCount;
-            this->inlineSlotCount = other->inlineSlotCount;
-            this->skipNewScObject = other->skipNewScObject;
-            this->ctorHasNoExplicitReturnValue = other->ctorHasNoExplicitReturnValue;
-            this->typeIsFinal = other->typeIsFinal;
-            this->isUsed = false;
-        }
-
-        JitTimeConstructorCache* Clone(JitArenaAllocator* allocator)
-        {
-            JitTimeConstructorCache* clone = Anew(allocator, JitTimeConstructorCache, this);
-            return clone;
-        }
+// forward declaration
+class JITTimeConstructorCache;
 
-        const BVSparse<JitArenaAllocator>* GetGuardedPropOps() const
-        {
-            return this->guardedPropOps;
-        }
-
-        void EnsureGuardedPropOps(JitArenaAllocator* allocator)
-        {
-            if (this->guardedPropOps == nullptr)
-            {
-                this->guardedPropOps = Anew(allocator, BVSparse<JitArenaAllocator>, allocator);
-            }
-        }
-
-        void SetGuardedPropOp(uint propOpId)
-        {
-            Assert(this->guardedPropOps != nullptr);
-            this->guardedPropOps->Set(propOpId);
-        }
-
-        void AddGuardedPropOps(const BVSparse<JitArenaAllocator>* propOps)
-        {
-            Assert(this->guardedPropOps != nullptr);
-            this->guardedPropOps->Or(propOps);
-        }
-    };
+namespace Js
+{
 
 #define InitialObjTypeSpecFldInfoFlagValue 0x01
 
@@ -102,6 +22,33 @@ namespace Js
         bool nextHasSameFixedField; // set to true if the next entry in the FixedFieldInfo array on ObjTypeSpecFldInfo has the same type
     };
 
+    // Union with uint16 flags for fast default initialization
+    union ObjTypeSpecFldInfoFlags
+    {
+        struct
+        {
+            bool falseReferencePreventionBit : 1;
+            bool isPolymorphic : 1;
+            bool isRootObjectNonConfigurableField : 1;
+            bool isRootObjectNonConfigurableFieldLoad : 1;
+            bool usesAuxSlot : 1;
+            bool isLocal : 1;
+            bool isLoadedFromProto : 1;
+            bool usesAccessor : 1;
+            bool hasFixedValue : 1;
+            bool keepFieldValue : 1;
+            bool isBeingStored : 1;
+            bool isBeingAdded : 1;
+            bool doesntHaveEquivalence : 1;
+            bool isBuiltIn : 1;
+        };
+        struct
+        {
+            uint16 flags;
+        };
+        ObjTypeSpecFldInfoFlags(uint16 flags) : flags(flags) { }
+    };
+
     class ObjTypeSpecFldInfo
     {
     private:
@@ -109,39 +56,14 @@ namespace Js
         PropertyGuard* propertyGuard;
         EquivalentTypeSet* typeSet;
         Type* initialType;
-        JitTimeConstructorCache* ctorCache;
+        JITTimeConstructorCache* ctorCache;
         FixedFieldInfo* fixedFieldInfoArray;
 
         PropertyId propertyId;
         Js::TypeId typeId;
         uint id;
 
-        // Union with uint16 flags for fast default initialization
-        union
-        {
-            struct
-            {
-                bool falseReferencePreventionBit : 1;
-                bool isPolymorphic : 1;
-                bool isRootObjectNonConfigurableField : 1;
-                bool isRootObjectNonConfigurableFieldLoad : 1;
-                bool usesAuxSlot : 1;
-                bool isLocal : 1;
-                bool isLoadedFromProto : 1;
-                bool usesAccessor : 1;
-                bool hasFixedValue : 1;
-                bool keepFieldValue : 1;
-                bool isBeingStored : 1;
-                bool isBeingAdded : 1;
-                bool doesntHaveEquivalence : 1;
-                bool isBuiltIn : 1;
-            };
-            struct
-            {
-                uint16 flags;
-            };
-        };
-
+        ObjTypeSpecFldInfoFlags flags;
         uint16 slotIndex;
 
         uint16 fixedFieldCount; // currently used only for fields that are functions
@@ -155,42 +77,42 @@ namespace Js
         ObjTypeSpecFldInfo(uint id, TypeId typeId, Type* initialType,
             bool usesAuxSlot, bool isLoadedFromProto, bool usesAccessor, bool isFieldValueFixed, bool keepFieldValue, bool isBuiltIn,
             uint16 slotIndex, PropertyId propertyId, DynamicObject* protoObject, PropertyGuard* propertyGuard,
-            JitTimeConstructorCache* ctorCache, FixedFieldInfo* fixedFieldInfoArray) :
+            JITTimeConstructorCache* ctorCache, FixedFieldInfo* fixedFieldInfoArray) :
             id(id), typeId(typeId), typeSet(nullptr), initialType(initialType), flags(InitialObjTypeSpecFldInfoFlagValue),
             slotIndex(slotIndex), propertyId(propertyId), protoObject(protoObject), propertyGuard(propertyGuard),
             ctorCache(ctorCache), fixedFieldInfoArray(fixedFieldInfoArray)
         {
-            this->isPolymorphic = false;
-            this->usesAuxSlot = usesAuxSlot;
-            this->isLocal = !isLoadedFromProto && !usesAccessor;
-            this->isLoadedFromProto = isLoadedFromProto;
-            this->usesAccessor = usesAccessor;
-            this->hasFixedValue = isFieldValueFixed;
-            this->keepFieldValue = keepFieldValue;
-            this->isBeingAdded = initialType != nullptr;
-            this->doesntHaveEquivalence = true; // doesn't mean anything for data from a monomorphic cache
-            this->isBuiltIn = isBuiltIn;
+            this->flags.isPolymorphic = false;
+            this->flags.usesAuxSlot = usesAuxSlot;
+            this->flags.isLocal = !isLoadedFromProto && !usesAccessor;
+            this->flags.isLoadedFromProto = isLoadedFromProto;
+            this->flags.usesAccessor = usesAccessor;
+            this->flags.hasFixedValue = isFieldValueFixed;
+            this->flags.keepFieldValue = keepFieldValue;
+            this->flags.isBeingAdded = initialType != nullptr;
+            this->flags.doesntHaveEquivalence = true; // doesn't mean anything for data from a monomorphic cache
+            this->flags.isBuiltIn = isBuiltIn;
             this->fixedFieldCount = 1;
         }
 
         ObjTypeSpecFldInfo(uint id, TypeId typeId, Type* initialType, EquivalentTypeSet* typeSet,
             bool usesAuxSlot, bool isLoadedFromProto, bool usesAccessor, bool isFieldValueFixed, bool keepFieldValue, bool doesntHaveEquivalence, bool isPolymorphic,
             uint16 slotIndex, PropertyId propertyId, DynamicObject* protoObject, PropertyGuard* propertyGuard,
-            JitTimeConstructorCache* ctorCache, FixedFieldInfo* fixedFieldInfoArray, uint16 fixedFieldCount) :
+            JITTimeConstructorCache* ctorCache, FixedFieldInfo* fixedFieldInfoArray, uint16 fixedFieldCount) :
             id(id), typeId(typeId), typeSet(typeSet), initialType(initialType), flags(InitialObjTypeSpecFldInfoFlagValue),
             slotIndex(slotIndex), propertyId(propertyId), protoObject(protoObject), propertyGuard(propertyGuard),
             ctorCache(ctorCache), fixedFieldInfoArray(fixedFieldInfoArray)
         {
-            this->isPolymorphic = isPolymorphic;
-            this->usesAuxSlot = usesAuxSlot;
-            this->isLocal = !isLoadedFromProto && !usesAccessor;
-            this->isLoadedFromProto = isLoadedFromProto;
-            this->usesAccessor = usesAccessor;
-            this->hasFixedValue = isFieldValueFixed;
-            this->keepFieldValue = keepFieldValue;
-            this->isBeingAdded = initialType != nullptr;
-            this->doesntHaveEquivalence = doesntHaveEquivalence;
-            this->isBuiltIn = false;
+            this->flags.isPolymorphic = isPolymorphic;
+            this->flags.usesAuxSlot = usesAuxSlot;
+            this->flags.isLocal = !isLoadedFromProto && !usesAccessor;
+            this->flags.isLoadedFromProto = isLoadedFromProto;
+            this->flags.usesAccessor = usesAccessor;
+            this->flags.hasFixedValue = isFieldValueFixed;
+            this->flags.keepFieldValue = keepFieldValue;
+            this->flags.isBeingAdded = initialType != nullptr;
+            this->flags.doesntHaveEquivalence = doesntHaveEquivalence;
+            this->flags.isBuiltIn = false;
             this->fixedFieldCount = fixedFieldCount;
         }
 
@@ -207,88 +129,88 @@ namespace Js
 
         bool IsMono() const
         {
-            return !this->isPolymorphic;
+            return !this->flags.isPolymorphic;
         }
 
         bool IsPoly() const
         {
-            return this->isPolymorphic;
+            return this->flags.isPolymorphic;
         }
 
         bool UsesAuxSlot() const
         {
-            return this->usesAuxSlot;
+            return this->flags.usesAuxSlot;
+        }
+
+        bool IsBuiltin() const
+        {
+            return this->flags.isBuiltIn;
         }
 
         void SetUsesAuxSlot(bool value)
         {
-            this->usesAuxSlot = value;
+            this->flags.usesAuxSlot = value;
         }
 
         bool IsLoadedFromProto() const
         {
-            return this->isLoadedFromProto;
+            return this->flags.isLoadedFromProto;
         }
 
         bool IsLocal() const
         {
-            return this->isLocal;
+            return this->flags.isLocal;
         }
 
         bool UsesAccessor() const
         {
-            return this->usesAccessor;
+            return this->flags.usesAccessor;
         }
 
         bool HasFixedValue() const
         {
-            return this->hasFixedValue;
+            return this->flags.hasFixedValue;
         }
 
         void SetHasFixedValue(bool value)
         {
-            this->hasFixedValue = value;
+            this->flags.hasFixedValue = value;
         }
 
         bool IsBeingStored() const
         {
-            return this->isBeingStored;
+            return this->flags.isBeingStored;
         }
 
         void SetIsBeingStored(bool value)
         {
-            this->isBeingStored = value;
+            this->flags.isBeingStored = value;
         }
 
         bool IsBeingAdded() const
         {
-            return this->isBeingAdded;
-        }
-
-        void SetIsBeingAdded(bool value)
-        {
-            this->isBeingAdded = value;
+            return this->flags.isBeingAdded;
         }
 
         bool IsRootObjectNonConfigurableField() const
         {
-            return this->isRootObjectNonConfigurableField;
+            return this->flags.isRootObjectNonConfigurableField;
         }
 
         bool IsRootObjectNonConfigurableFieldLoad() const
         {
-            return this->isRootObjectNonConfigurableField && this->isRootObjectNonConfigurableFieldLoad;
+            return this->flags.isRootObjectNonConfigurableField && this->flags.isRootObjectNonConfigurableFieldLoad;
         }
 
         void SetRootObjectNonConfigurableField(bool isLoad)
         {
-            this->isRootObjectNonConfigurableField = true;
-            this->isRootObjectNonConfigurableFieldLoad = isLoad;
+            this->flags.isRootObjectNonConfigurableField = true;
+            this->flags.isRootObjectNonConfigurableFieldLoad = isLoad;
         }
 
         bool DoesntHaveEquivalence() const
         {
-            return this->doesntHaveEquivalence;
+            return this->flags.doesntHaveEquivalence;
         }
 
         void ClearFlags()
@@ -301,6 +223,11 @@ namespace Js
             this->flags = flags | 0x01;
         }
 
+        uint16 GetFlags() const
+        {
+            return this->flags.flags;
+        }
+
         uint16 GetSlotIndex() const
         {
             return this->slotIndex;
@@ -354,10 +281,10 @@ namespace Js
 
         bool GetKeepFieldValue() const
         {
-            return this->keepFieldValue;
+            return this->flags.keepFieldValue;
         }
 
-        Js::JitTimeConstructorCache* GetCtorCache() const
+        JITTimeConstructorCache* GetCtorCache() const
         {
             return this->ctorCache;
         }
@@ -417,19 +344,13 @@ namespace Js
             return this->initialType;
         }
 
-        bool HasEquivalentTypeSet() const
-        {
-            Assert(IsObjTypeSpecCandidate());
-            return this->typeSet != nullptr;
-        }
-
         Js::EquivalentTypeSet * GetEquivalentTypeSet() const
         {
             Assert(IsObjTypeSpecCandidate());
             return this->typeSet;
         }
 
-        Js::Type * GetFirstEquivalentType() const
+        JITType * GetFirstEquivalentType() const
         {
             Assert(IsObjTypeSpecCandidate() && this->typeSet);
             return this->typeSet->GetFirstType();

+ 3 - 0
lib/Runtime/Library/JavascriptLibrary.cpp

@@ -3704,6 +3704,9 @@ namespace Js
         case JavascriptBuiltInFunction::JavascriptRegExp_Exec:
             return BuiltinFunction::RegExp_Exec;
 
+        case JavascriptBuiltInFunction::GlobalObject_ParseInt:
+            return BuiltinFunction::GlobalObject_ParseInt;
+
         default:
             return BuiltinFunction::None;
         }