2
0
Эх сурвалжийг харах

1. BuiltIn JS loading to load one object at a time
2. Make the process more easily extensible
3. Related re-factoring for efficiency

rhuanjl 5 жил өмнө
parent
commit
e36738055f

+ 9 - 32
lib/Runtime/Base/JnDirectFields.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -11,8 +12,8 @@
 
 //
 // NOTE: After modifying this file you might observe unit test failures, especially jd/Debugger unit test failures.
-// This can be caused by the build-generated bytecode files for the Intl.js and JsBuiltin.js becoming invalidated.
-// Run RegenAllByteCode.cmd to update bytecode. (Note: this will build and regen all variants and may take some time.)
+// This can be caused by the build-generated bytecode files in Library/InJavascript becoming invalidated.
+// Run regenByteCode.py to update bytecode. (Note: this will build and regen all variants and may take some time.)
 //
 
 #if !defined(ENTRY_INTERNAL_SYMBOL)
@@ -274,8 +275,6 @@ ENTRY(match)
 ENTRY(message)
 ENTRY(MIN_SAFE_INTEGER)
 ENTRY(MIN_VALUE)
-ENTRY(moveFirst)
-ENTRY(moveNext)
 ENTRY(NaN)
 ENTRY(name)
 ENTRY(next)
@@ -416,9 +415,6 @@ ENTRY(valueOf)
 ENTRY(values)
 ENTRY(WeakMap)
 ENTRY(WeakSet)
-ENTRY(WinRTError) // remove this upon next bytecode regen
-ENTRY(write)
-ENTRY(writeln)
 ENTRY(setNonUserCodeExceptions)
 ENTRY(debuggerEnabled)
 ENTRY(enumerable)
@@ -651,33 +647,14 @@ ENTRY(toLength)
 ENTRY(toInteger)
 ENTRY(arraySpeciesCreate)
 ENTRY(arrayCreateDataPropertyOrThrow)
-ENTRY(Array_values)
-ENTRY(Array_keys)
-ENTRY(Array_entries)
-ENTRY(Array_indexOf)
-ENTRY(Array_sort)
-ENTRY(Array_filter)
-ENTRY(Array_flat)
-ENTRY(Array_flatMap)
-ENTRY(Array_forEach)
-ENTRY(Array_some)
-ENTRY(Array_every)
-ENTRY(Array_includes)
-ENTRY(Array_reduce)
-ENTRY(Object_fromEntries)
-ENTRY(Math_min)
-ENTRY(Math_max)
-ENTRY(FunctionKind)
 
 // EngineInterfaceObject built-ins
-ENTRY(builtInJavascriptArrayEntryFilter)
-ENTRY(builtInJavascriptArrayEntryForEach)
-ENTRY(builtInJavascriptArrayEntryIndexOf)
-ENTRY(builtInJavascriptArrayEntrySome)
-ENTRY(builtInJavascriptArrayEntryEvery)
-ENTRY(builtInJavascriptArrayEntryIncludes)
-ENTRY(builtInMathMin)
-ENTRY(builtInMathMax)
+ENTRY(builtInArray_prototype_filter)
+ENTRY(builtInArray_prototype_forEach)
+ENTRY(builtInArray_prototype_indexOf)
+ENTRY(builtInArray_prototype_reduce)
+ENTRY(builtInMath_object_min)
+ENTRY(builtInMath_object_max)
 ENTRY(EngineInterface)
 ENTRY(builtInCallInstanceFunction)
 

+ 2 - 1
lib/Runtime/Debug/TTRuntimeInfoTracker.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeDebugPch.h"
@@ -792,7 +793,7 @@ namespace TTD
 #ifdef ENABLE_JS_BUILTINS
         if (ctx->IsJsBuiltInEnabled())
         {
-            ctx->GetLibrary()->EnsureBuiltInEngineIsReady();
+            ctx->GetLibrary()->EnsureArrayBuiltInsAreReady();
         }
 #endif
         this->EnqueueRootPathObject(_u("_arrayIteratorPrototype"), ctx->GetLibrary()->GetArrayIteratorPrototype());

+ 2 - 1
lib/Runtime/Language/JavascriptOperators.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeLanguagePch.h"
@@ -1565,7 +1566,7 @@ CommonNumber:
 #endif
 
 #ifdef ENABLE_JS_BUILTINS
-        scriptContext->GetLibrary()->EnsureBuiltInEngineIsReady();
+        scriptContext->GetLibrary()->EnsureArrayBuiltInsAreReady();
 #endif
 
         RecyclableObject* function = GetIteratorFunction(aRight, scriptContext);

+ 4 - 6
lib/Runtime/Library/Chakra.Runtime.Library.vcxproj

@@ -170,10 +170,6 @@
     <ClInclude Include="PropertyRecordUsageCache.h" />
     <ClInclude Include="CustomExternalIterator.h" />
     <ClInclude Include="JsBuiltInEngineInterfaceExtensionObject.h" />
-    <ClInclude Include="JsBuiltIn\JsBuiltIn.js.bc.32b.h" />
-    <ClInclude Include="JsBuiltIn\JsBuiltIn.js.bc.64b.h" />
-    <ClInclude Include="JsBuiltIn\JsBuiltIn.js.nojit.bc.32b.h" />
-    <ClInclude Include="JsBuiltIn\JsBuiltIn.js.nojit.bc.64b.h" />
     <ClInclude Include="ExternalLibraryBase.h" />
     <ClInclude Include="IntlEngineInterfaceExtensionObject.h" />
     <ClInclude Include="IntlExtensionObjectBuiltIns.h" />
@@ -194,8 +190,10 @@
     <ClInclude Include="EngineInterfaceObject.h" />
     <ClInclude Include="ES5ArrayIndexStaticEnumerator.h" />
     <ClInclude Include="HostObjectBase.h" />
-    <ClInclude Include="InJavascript\Intl.js.bc.32b.h" />
-    <ClInclude Include="InJavascript\Intl.js.bc.64b.h" />
+    <ClInclude Include="InJavascript\JsBuiltIn.bc.32b.h" />
+    <ClInclude Include="InJavascript\JsBuiltIn.bc.64b.h" />
+    <ClInclude Include="InJavascript\JsBuiltIn.nojit.bc.32b.h" />
+    <ClInclude Include="InJavascript\JsBuiltIn.nojit.bc.64b.h" />
     <ClInclude Include="JavascriptArrayIndexEnumeratorBase.h" />
     <ClInclude Include="JavascriptArrayIndexStaticEnumerator.h" />
     <ClInclude Include="JavascriptArrayIterator.h" />

+ 4 - 6
lib/Runtime/Library/Chakra.Runtime.Library.vcxproj.filters

@@ -125,8 +125,10 @@
     <ClInclude Include="EngineInterfaceObject.h" />
     <ClInclude Include="ES5ArrayIndexEnumerator.h" />
     <ClInclude Include="HostObjectBase.h" />
-    <ClInclude Include="InJavascript\Intl.js.bc.32b.h" />
-    <ClInclude Include="InJavascript\Intl.js.bc.64b.h" />
+    <ClInclude Include="InJavascript\JsBuiltIn.bc.32b.h" />
+    <ClInclude Include="InJavascript\JsBuiltIn.bc.64b.h" />
+    <ClInclude Include="InJavascript\JsBuiltIn.nojit.bc.32b.h" />
+    <ClInclude Include="InJavascript\JsBuiltIn.nojit.bc.64b.h" />
     <ClInclude Include="JavascriptArrayIndexEnumerator.h" />
     <ClInclude Include="JavascriptArrayIterator.h" />
     <ClInclude Include="JavascriptAsyncFromSyncIterator.h" />
@@ -231,10 +233,6 @@
     <ClInclude Include="JSONStringifier.h" />
     <ClInclude Include="JSONStringBuilder.h" />
     <ClInclude Include="JsBuiltInEngineInterfaceExtensionObject.h" />
-    <ClInclude Include="JsBuiltIn\JsBuiltIn.js.bc.32b.h" />
-    <ClInclude Include="JsBuiltIn\JsBuiltIn.js.bc.64b.h" />
-    <ClInclude Include="JsBuiltIn\JsBuiltIn.js.nojit.bc.32b.h" />
-    <ClInclude Include="JsBuiltIn\JsBuiltIn.js.nojit.bc.64b.h" />
     <ClInclude Include="PropertyRecordUsageCache.h" />
     <ClInclude Include="..\LibraryFunction.h" />
     <ClInclude Include="IntlExtensionObjectBuiltIns.h" />

+ 23 - 0
lib/Runtime/Library/EngineInterfaceObject.h

@@ -1,11 +1,34 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
 
 #if defined(ENABLE_INTL_OBJECT) || defined(ENABLE_JS_BUILTINS)
 
+
+#pragma warning(push)
+#pragma warning(disable:4309) // truncation of constant value
+#pragma warning(disable:4838) // conversion from 'int' to 'const char' requires a narrowing conversion
+
+#if DISABLE_JIT
+#if TARGET_64
+#include "InJavascript/JsBuiltIn.nojit.bc.64b.h"
+#else
+#include "InJavascript/JsBuiltIn.nojit.bc.32b.h"
+#endif // TARGET_64
+#else
+#if TARGET_64
+#include "InJavascript/JsBuiltIn.bc.64b.h"
+#else
+#include "InJavascript/JsBuiltIn.bc.32b.h"
+#endif // TARGET_64
+#endif // DISABLE_JIT
+
+#pragma warning(pop)
+
+
 namespace Js
 {
     class WindowsGlobalizationAdapter;

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

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -71,7 +72,6 @@ GlobalBuiltIn(JavascriptObject, PreventExtensions)
 GlobalBuiltIn(JavascriptArray, Push) // TODO(jahorto): consider deleting (trivially implementable in JS)
 GlobalBuiltIn(JavascriptArray, Join)
 GlobalBuiltIn(JavascriptArray, Map)
-GlobalBuiltIn(JavascriptArray, Reduce)
 GlobalBuiltIn(JavascriptArray, Slice)
 GlobalBuiltIn(JavascriptArray, Concat)
 

+ 7 - 6
lib/Runtime/Library/InJavascript/Intl.js

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -70,7 +71,7 @@
     var Math = setPrototype({
         abs: platform.builtInMathAbs,
         floor: platform.builtInMathFloor,
-        max: platform.builtInMathMax,
+        max: platform.builtInMath_object_max,
         pow: platform.builtInMathPow
     }, null);
 
@@ -85,8 +86,8 @@
         _objectDefineProperty(obj, prop, setPrototype(attributes, null));
     };
 
-    var ArrayInstanceForEach = platform.builtInJavascriptArrayEntryForEach;
-    var ArrayInstanceIndexOf = platform.builtInJavascriptArrayEntryIndexOf;
+    var ArrayInstanceForEach = platform.builtInArray_prototype_forEach;
+    var ArrayInstanceIndexOf = platform.builtInArray_prototype_indexOf;
     var ArrayInstancePush = platform.builtInJavascriptArrayEntryPush;
     var ArrayInstanceJoin = platform.builtInJavascriptArrayEntryJoin;
 
@@ -116,10 +117,10 @@
         join(array, sep) { return callInstanceFunc(ArrayInstanceJoin, array, sep); },
         arrayIndexOf(array, el, from) { return callInstanceFunc(ArrayInstanceIndexOf, array, el, from); },
         map(array, func) { return callInstanceFunc(platform.builtInJavascriptArrayEntryMap, array, func); },
-        reduce(array, func, init) { return callInstanceFunc(platform.builtInJavascriptArrayEntryReduce, array, func, init); },
+        reduce(array, func, init) { return callInstanceFunc(platform.builtInArray_prototype_reduce, array, func, init); },
         slice(array, start, end) { return callInstanceFunc(platform.builtInJavascriptArrayEntrySlice, array, start, end); },
         concat(array, ...els) { return callInstanceFunc(platform.builtInJavascriptArrayEntryConcat, array, ...els); },
-        filter(array, func) { return callInstanceFunc(platform.builtInJavascriptArrayEntryFilter, array, func); },
+        filter(array, func) { return callInstanceFunc(platform.builtInArray_prototype_filter, array, func); },
         unique(array) { return _.filter(array, (v, i) => _.arrayIndexOf(array, v) === i); },
 
         keys: platform.builtInJavascriptObjectEntryKeys,
@@ -136,7 +137,7 @@
         abs: platform.builtInMathAbs,
         // Make _.floor more like ECMA262 #sec-mathematical-operations' floor by normalizing -0
         floor(x) { return x === 0 ? 0 : platform.builtInMathFloor(x) },
-        max: platform.builtInMathMax,
+        max: platform.builtInMath_object_max,
         pow: platform.builtInMathPow,
 
         isFinite: platform.builtInGlobalObjectEntryIsFinite,

+ 7 - 24
lib/Runtime/Library/IntlEngineInterfaceExtensionObject.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeLibraryPch.h"
@@ -119,26 +120,6 @@ PROJECTED_ENUMS(PROJECTED_ENUM)
 #undef PROJECTED_ENUM
 #undef ENUM_VALUE
 
-#pragma warning(push)
-#pragma warning(disable:4309) // truncation of constant value
-#pragma warning(disable:4838) // conversion from 'int' to 'const char' requires a narrowing conversion
-
-#if DISABLE_JIT
-#if TARGET_64
-#include "InJavascript/Intl.js.nojit.bc.64b.h"
-#else
-#include "InJavascript/Intl.js.nojit.bc.32b.h"
-#endif
-#else
-#if TARGET_64
-#include "InJavascript/Intl.js.bc.64b.h"
-#else
-#include "InJavascript/Intl.js.bc.32b.h"
-#endif
-#endif
-
-#pragma warning(pop)
-
 #define IfFailAssertAndThrowHr(op) \
     if (FAILED(hr=(op))) \
     { \
@@ -529,9 +510,6 @@ namespace Js
         }
         JavascriptLibrary* library = scriptContext->GetLibrary();
 
-        // Ensure JsBuiltIns are initialized before initializing Intl which uses some of them.
-        library->EnsureBuiltInEngineIsReady();
-
         DynamicObject* commonObject = library->GetEngineInterfaceObject()->GetCommonNativeInterfaces();
         if (scriptContext->IsIntlEnabled())
         {
@@ -722,7 +700,7 @@ PROJECTED_ENUMS(PROJECTED_ENUM)
             SRCINFO *hsi = scriptContext->AddHostSrcInfo(&si);
             uint32 flags = fscrIsLibraryCode | (CONFIG_FLAG(CreateFunctionProxy) && !scriptContext->IsProfiling() ? fscrAllowFunctionProxy : 0);
 
-            HRESULT hr = Js::ByteCodeSerializer::DeserializeFromBuffer(scriptContext, flags, (LPCUTF8)nullptr, hsi, (byte*)Library_Bytecode_Intl, nullptr, &this->intlByteCode);
+            HRESULT hr = Js::ByteCodeSerializer::DeserializeFromBuffer(scriptContext, flags, (LPCUTF8)nullptr, hsi, (byte*)js::Library_Bytecode_Intl, nullptr, &this->intlByteCode);
 
             IfFailAssertMsgAndThrowHr(hr, "Failed to deserialize Intl.js bytecode - very probably the bytecode needs to be rebuilt.");
 
@@ -732,6 +710,11 @@ PROJECTED_ENUMS(PROJECTED_ENUM)
 
     void IntlEngineInterfaceExtensionObject::InjectIntlLibraryCode(_In_ ScriptContext * scriptContext, DynamicObject* intlObject, IntlInitializationType intlInitializationType)
     {
+
+        // Ensure JsBuiltIns are initialized before initializing Intl which uses some of them.
+        scriptContext->GetLibrary()->EnsureArrayBuiltInsAreReady();
+        scriptContext->GetLibrary()->EnsureMathBuiltInsAreReady();
+
         JavascriptExceptionObject *pExceptionObject = nullptr;
 #ifdef INTL_WINGLOB
         WindowsGlobalizationAdapter* globAdapter = GetWindowsGlobalizationAdapter(scriptContext);

+ 36 - 46
lib/Runtime/Library/JavascriptLibrary.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -1904,6 +1905,33 @@ namespace Js
         return true;
     }
 
+#ifdef ENABLE_JS_BUILTINS
+    void EnsureBuiltInEngineIsReady(JsBuiltInFile file, ScriptContext* scriptContext)
+    {
+        if (scriptContext->IsJsBuiltInEnabled())
+        {
+            if (scriptContext->VerifyAlive())  // Can't initialize if scriptContext closed, will need to run script
+            {
+                EngineInterfaceObject* engineInterfaceObject = scriptContext->GetLibrary()->GetEngineInterfaceObject();
+                Assert(engineInterfaceObject != nullptr);
+                JsBuiltInEngineInterfaceExtensionObject* builtInExtension =
+                    static_cast<JsBuiltInEngineInterfaceExtensionObject*>(engineInterfaceObject->GetEngineExtension(EngineInterfaceExtensionKind_JsBuiltIn));
+                builtInExtension->InjectJsBuiltInLibraryCode(scriptContext, file);
+            }
+        }
+    }
+    
+    void JavascriptLibrary::EnsureArrayBuiltInsAreReady()
+    {
+        EnsureBuiltInEngineIsReady(JsBuiltInFile::Array_prototype, scriptContext);
+    }
+
+    void JavascriptLibrary::EnsureMathBuiltInsAreReady()
+    {
+        EnsureBuiltInEngineIsReady(JsBuiltInFile::Math_object, scriptContext);
+    }
+#endif
+
     bool JavascriptLibrary::IsDefaultArrayValuesFunction(RecyclableObject * function, ScriptContext *scriptContext)
     {
 #ifdef ENABLE_JS_BUILTINS
@@ -1912,7 +1940,7 @@ namespace Js
             ScriptFunction * scriptFunction = JavascriptOperators::TryFromVar<ScriptFunction>(function);
             if (scriptFunction)
             {
-                scriptContext->GetLibrary()->EnsureBuiltInEngineIsReady();
+                EnsureBuiltInEngineIsReady(JsBuiltInFile::Array_prototype, scriptContext);
                 return scriptFunction->GetFunctionProxy()->IsJsBuiltInCode();
             }
         }
@@ -1944,7 +1972,7 @@ namespace Js
             }
             else
             {
-                this->EnsureBuiltInEngineIsReady();
+                EnsureBuiltInEngineIsReady(JsBuiltInFile::Array_prototype, scriptContext);
             }
 #endif
         }
@@ -1964,7 +1992,7 @@ namespace Js
             }
             else
             {
-                this->EnsureBuiltInEngineIsReady();
+                EnsureBuiltInEngineIsReady(JsBuiltInFile::Array_prototype, scriptContext);
             }
 #endif
         }
@@ -1984,7 +2012,7 @@ namespace Js
             }
             else
             {
-                this->EnsureBuiltInEngineIsReady();
+                EnsureBuiltInEngineIsReady(JsBuiltInFile::Array_prototype, scriptContext);
             }
 #endif
         }
@@ -2052,7 +2080,7 @@ namespace Js
 #ifdef ENABLE_JS_BUILTINS
         if (scriptContext->IsJsBuiltInEnabled())
         {
-            library->EnsureBuiltInEngineIsReady();
+            EnsureBuiltInEngineIsReady(JsBuiltInFile::Array_prototype, scriptContext);
         }
         else
 #endif
@@ -2284,7 +2312,7 @@ namespace Js
 #ifdef ENABLE_JS_BUILTINS
         if (scriptContext->IsJsBuiltInEnabled())
         {
-            library->EnsureBuiltInEngineIsReady();
+            EnsureBuiltInEngineIsReady(JsBuiltInFile::Array_prototype, scriptContext);
         }
 #endif
 
@@ -3203,7 +3231,7 @@ namespace Js
 #ifdef ENABLE_JS_BUILTINS
         if (scriptContext->IsJsBuiltInEnabled())
         {
-            library->EnsureBuiltInEngineIsReady();
+            EnsureBuiltInEngineIsReady(JsBuiltInFile::Math_object, scriptContext);
         }
         else
 #endif
@@ -4140,7 +4168,7 @@ namespace Js
 #ifdef ENABLE_JS_BUILTINS
         if (scriptContext->IsJsBuiltInEnabled())
         {
-            library->EnsureBuiltInEngineIsReady();
+            EnsureBuiltInEngineIsReady(JsBuiltInFile::Object_constructor, scriptContext);
         }
 #endif
 
@@ -5171,44 +5199,6 @@ namespace Js
 
 #ifdef ENABLE_JS_BUILTINS
 
-    bool JavascriptLibrary::InitializeBuiltInObject(DynamicObject* builtInObject, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode)
-    {
-        typeHandler->Convert(builtInObject, mode,  /*initSlotCapacity*/ 2);
-
-        if (builtInObject->GetScriptContext()->IsJsBuiltInEnabled())
-        {
-            auto builtInInitializer = [&](JsBuiltInEngineInterfaceExtensionObject* builtInExtension, ScriptContext * scriptContext) -> void
-            {
-                builtInExtension->InjectJsBuiltInLibraryCode(scriptContext);
-            };
-            builtInObject->GetLibrary()->InitializeBuiltInForPrototypes(builtInInitializer);
-        }
-        return true;
-    }
-
-    void JavascriptLibrary::EnsureBuiltInEngineIsReady()
-    {
-        if (scriptContext->IsJsBuiltInEnabled())
-        {
-            auto builtInInitializer = [&](JsBuiltInEngineInterfaceExtensionObject* builtInExtension, ScriptContext * scriptContext) -> void
-            {
-                builtInExtension->InjectJsBuiltInLibraryCode(scriptContext);
-            };
-            scriptContext->GetLibrary()->InitializeBuiltInForPrototypes(builtInInitializer);
-        }
-    }
-
-    template <class Fn>
-    void JavascriptLibrary::InitializeBuiltInForPrototypes(Fn fn)
-    {
-        if (scriptContext->VerifyAlive())  // Can't initialize if scriptContext closed, will need to run script
-        {
-            Assert(engineInterfaceObject != nullptr);
-            JsBuiltInEngineInterfaceExtensionObject* builtInExtension = static_cast<JsBuiltInEngineInterfaceExtensionObject*>(GetEngineInterfaceObject()->GetEngineExtension(EngineInterfaceExtensionKind_JsBuiltIn));
-            fn(builtInExtension, scriptContext);
-        }
-    }
-
     bool JavascriptLibrary::InitializeChakraLibraryObject(DynamicObject * chakraLibraryObject, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode)
     {
         JavascriptLibrary* library = chakraLibraryObject->GetLibrary();

+ 3 - 6
lib/Runtime/Library/JavascriptLibrary.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
@@ -692,13 +693,9 @@ namespace Js
 #endif
 
 #ifdef ENABLE_JS_BUILTINS
-        template <class Fn>
-        void InitializeBuiltInForPrototypes(Fn fn);
-
-        void EnsureBuiltInEngineIsReady();
-
+        void EnsureArrayBuiltInsAreReady();
+        void EnsureMathBuiltInsAreReady();
         static bool __cdecl InitializeChakraLibraryObject(DynamicObject* chakraLibraryObject, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode);
-        static bool __cdecl InitializeBuiltInObject(DynamicObject* builtInEngineObject, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode);
 
 #endif
 

+ 130 - 151
lib/Runtime/Library/JsBuiltInEngineInterfaceExtensionObject.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeLibraryPch.h"
@@ -12,26 +13,6 @@
 #include "errstr.h"
 #include "ByteCode/ByteCodeDumper.h"
 
-#pragma warning(push)
-#pragma warning(disable:4309) // truncation of constant value
-#pragma warning(disable:4838) // conversion from 'int' to 'const char' requires a narrowing conversion
-
-#if DISABLE_JIT
-#if TARGET_64
-#include "JsBuiltIn/JsBuiltIn.js.nojit.bc.64b.h"
-#else
-#include "JsBuiltIn/JsBuiltIn.js.nojit.bc.32b.h"
-#endif // TARGET_64
-#else
-#if TARGET_64
-#include "JsBuiltIn/JsBuiltIn.js.bc.64b.h"
-#else
-#include "JsBuiltIn/JsBuiltIn.js.bc.32b.h"
-#endif // TARGET_64
-#endif // DISABLE_JIT
-
-#pragma warning(pop)
-
 #define IfFailAssertMsgAndThrowHr(op, msg) \
     if (FAILED(hr=(op))) \
     { \
@@ -39,46 +20,18 @@
     JavascriptError::MapAndThrowError(scriptContext, hr); \
     } \
 
-#define FUNCTIONKIND_VALUES(VALUE) \
-VALUE(Array, values, Prototype) \
-VALUE(Array, keys, Prototype) \
-VALUE(Array, entries, Prototype) \
-VALUE(Array, indexOf, Prototype) \
-VALUE(Array, filter, Prototype) \
-VALUE(Array, flat, Prototype) \
-VALUE(Array, flatMap, Prototype) \
-VALUE(Array, forEach, Prototype) \
-VALUE(Array, some, Prototype) \
-VALUE(Array, sort, Prototype) \
-VALUE(Array, every, Prototype) \
-VALUE(Array, includes, Prototype) \
-VALUE(Array, reduce, Prototype) \
-VALUE(Object, fromEntries, Constructor) \
-VALUE(Math, max, Object) \
-VALUE(Math, min, Object)
-
-enum class FunctionKind
-{
-#define VALUE(ClassName, methodName, propertyType) ClassName##_##methodName,
-    FUNCTIONKIND_VALUES(VALUE) 
-#undef VALUE
-    Max
-};
-
-enum class IsPropertyTypeStatic : bool
+enum class IsTypeStatic : bool
 {
-    Prototype = false,
-    Constructor = true,
-    Object = true
+    prototype = false,
+    constructor = true,
+    object = true
 };
 
 namespace Js
 {
 
     JsBuiltInEngineInterfaceExtensionObject::JsBuiltInEngineInterfaceExtensionObject(ScriptContext * scriptContext) :
-        EngineExtensionObjectBase(EngineInterfaceExtensionKind_JsBuiltIn, scriptContext),
-        jsBuiltInByteCode(nullptr),
-        wasInitialized(false)
+        EngineExtensionObjectBase(EngineInterfaceExtensionKind_JsBuiltIn, scriptContext)
     {
     }
 
@@ -123,24 +76,39 @@ namespace Js
         library->arrayIteratorPrototypeBuiltinNextFunction = VarTo<JavascriptFunction>(JavascriptOperators::GetProperty(library->arrayIteratorPrototype, PropertyIds::next, scriptContext));
     }
 
-    void JsBuiltInEngineInterfaceExtensionObject::InjectJsBuiltInLibraryCode(ScriptContext * scriptContext)
+    void JsBuiltInEngineInterfaceExtensionObject::InjectJsBuiltInLibraryCode(ScriptContext * scriptContext, JsBuiltInFile file)
     {
         JavascriptExceptionObject *pExceptionObject = nullptr;
-        if (jsBuiltInByteCode != nullptr)
+        FunctionBody* jsBuiltInByteCode = nullptr;
+
+        switch (file)
         {
-            return;
+            #define jsBuiltInByteCodeCase(class, type, obj) \
+            case (JsBuiltInFile::class##_##type): \
+            { \
+                if (jsBuiltIn##class##_##type##Bytecode != nullptr) \
+                    return; \
+                EnsureSourceInfo(); \
+                uint32 flags = fscrJsBuiltIn | (CONFIG_FLAG(CreateFunctionProxy) && !scriptContext->IsProfiling() ? fscrAllowFunctionProxy : 0); \
+                SRCINFO* hsi = sourceInfo; \
+                Js::ByteCodeSerializer::DeserializeFromBuffer(scriptContext, flags, (LPCUTF8)nullptr, hsi, (byte*)js::Library_Bytecode_##class##_##type, nullptr, &jsBuiltIn##class##_##type##Bytecode); \
+                jsBuiltInByteCode = jsBuiltIn##class##_##type##Bytecode; \
+                break; \
+            }
+            JsBuiltIns(jsBuiltInByteCodeCase)
+            #undef jsBuiltInByteCodeCase
         }
+        this->SetHasBytecode();
 
         try {
-            EnsureJsBuiltInByteCode(scriptContext);
-            Assert(jsBuiltInByteCode != nullptr);
+            AssertOrFailFast(jsBuiltInByteCode != nullptr);
 
             Js::ScriptFunction *functionGlobal = scriptContext->GetLibrary()->CreateScriptFunction(jsBuiltInByteCode);
 
             // If we are in the debugger and doing a GetProperty of arguments, then Js Builtins code will be injected on-demand
             // Since it is a cross site call, we marshall not only functionGlobal but also its entire prototype chain
             // The prototype of functionGlobal will be shared by a normal Js function,
-            // so marshalling will inadvertantly transition the entrypoint of the prototype to a crosssite entrypoint
+            // so marshalling will inadvertently transition the entrypoint of the prototype to a crosssite entrypoint
             // So we set the prototype to null here
             functionGlobal->SetPrototype(scriptContext->GetLibrary()->nullValue);
 
@@ -177,6 +145,7 @@ namespace Js
             Js::ScriptFunction *functionBuiltins = scriptContext->GetLibrary()->CreateScriptFunction(jsBuiltInByteCode->GetNestedFunctionForExecution(0));
             functionBuiltins->SetPrototype(scriptContext->GetLibrary()->nullValue);
 
+            current = file;
             // Clear disable implicit call bit as initialization code doesn't have any side effect
             {
                 ThreadContext::AutoRestoreImplicitFlags autoRestoreImplicitFlags(scriptContext->GetThreadContext(), scriptContext->GetThreadContext()->GetImplicitCallFlags(), scriptContext->GetThreadContext()->GetDisableImplicitFlags());
@@ -184,7 +153,10 @@ namespace Js
                 JavascriptFunction::CallRootFunctionInScript(functionBuiltins, Js::Arguments(callInfo, args));
             }
 
-            InitializePrototypes(scriptContext);
+            if (file == JsBuiltInFile::Array_prototype)
+            {
+                InitializePrototypes(scriptContext);
+            }
 #if DBG_DUMP
             if (PHASE_DUMP(Js::ByteCodePhase, functionGlobal->GetFunctionProxy()) && Js::Configuration::Global.flags.Verbose)
             {
@@ -199,6 +171,15 @@ namespace Js
 
         if (pExceptionObject)
         {
+            switch (file)
+            {
+                #define clearJsBuiltInByteCodeCase(class, type, obj) \
+            case (JsBuiltInFile::class##_##type): \
+                jsBuiltIn##class##_##type##Bytecode = nullptr;
+                    break;
+            JsBuiltIns(clearJsBuiltInByteCodeCase)
+            #undef clearJsBuiltInByteCodeCase
+            }
             jsBuiltInByteCode = nullptr;
             if (pExceptionObject == ThreadContext::GetContextForCurrentThread()->GetPendingSOErrorObject())
             {
@@ -210,20 +191,13 @@ namespace Js
 
     bool JsBuiltInEngineInterfaceExtensionObject::InitializeJsBuiltInNativeInterfaces(DynamicObject * builtInNativeInterfaces, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode)
     {
-        int initSlotCapacity = 6; // for register{ChakraLibrary}Function, FunctionKind, POSITIVE_INFINITY, NEGATIVE_INFINITY, and GetIteratorPrototype
+        int initSlotCapacity = 5; // for register{ChakraLibrary}Function, POSITIVE_INFINITY, NEGATIVE_INFINITY, and GetIteratorPrototype
 
         typeHandler->Convert(builtInNativeInterfaces, mode, initSlotCapacity);
 
         ScriptContext* scriptContext = builtInNativeInterfaces->GetScriptContext();
         JavascriptLibrary* library = scriptContext->GetLibrary();
 
-        DynamicObject * functionKindObj = library->CreateObject();
-
-#define VALUE(ClassName, methodName, propertyType) library->AddMember(functionKindObj, PropertyIds::ClassName##_##methodName, JavascriptNumber::ToVar((int)FunctionKind::ClassName##_##methodName, scriptContext));
-        FUNCTIONKIND_VALUES(VALUE)
-#undef VALUE
-
-        library->AddMember(builtInNativeInterfaces, PropertyIds::FunctionKind, functionKindObj);
         library->AddMember(builtInNativeInterfaces, PropertyIds::POSITIVE_INFINITY, library->GetPositiveInfinite());
         library->AddMember(builtInNativeInterfaces, PropertyIds::NEGATIVE_INFINITY, library->GetNegativeInfinite());
 
@@ -236,17 +210,37 @@ namespace Js
     }
 
 #if DBG
+    void JsBuiltInEngineInterfaceExtensionObject::DumpByteCode(JsBuiltInFile file)
+    {
+        Output::Print(_u("Dumping JS Built Ins Byte Code:\n"));
+        switch (file)
+        {
+            #define fileCase(class, type, obj) \
+            case class##_##type: \
+                Assert(this->jsBuiltIn##class##_##type##Bytecode != nullptr); \
+                Js::ByteCodeDumper::DumpRecursively(this->jsBuiltIn##class##_##type##Bytecode); \
+                break;
+            JsBuiltIns(fileCase)
+            #undef fileCase
+        }
+    }
+
     void JsBuiltInEngineInterfaceExtensionObject::DumpByteCode()
     {
         Output::Print(_u("Dumping JS Built Ins Byte Code:\n"));
-        Assert(this->jsBuiltInByteCode);
-        Js::ByteCodeDumper::DumpRecursively(jsBuiltInByteCode);
+        #define dumpOne(class, type, obj) \
+        if (this->jsBuiltIn##class##_##type##Bytecode != nullptr) \
+        { \
+            DumpByteCode(JsBuiltInFile::class##_##type); \
+        }
+        JsBuiltIns(dumpOne)
+        #undef dumpOne
     }
 #endif // DBG
 
-    void JsBuiltInEngineInterfaceExtensionObject::EnsureJsBuiltInByteCode(ScriptContext * scriptContext)
+    void JsBuiltInEngineInterfaceExtensionObject::EnsureSourceInfo()
     {
-        if (jsBuiltInByteCode == nullptr)
+        if (sourceInfo == nullptr)
         {
             SourceContextInfo* sourceContextInfo = RecyclerNewStructZ(scriptContext->GetRecycler(), SourceContextInfo);
             sourceContextInfo->dwHostSourceContext = Js::Constants::JsBuiltInSourceContext;
@@ -258,13 +252,7 @@ namespace Js
             SRCINFO si;
             memset(&si, 0, sizeof(si));
             si.sourceContextInfo = sourceContextInfo;
-            SRCINFO *hsi = scriptContext->AddHostSrcInfo(&si);
-            uint32 flags = fscrJsBuiltIn | (CONFIG_FLAG(CreateFunctionProxy) && !scriptContext->IsProfiling() ? fscrAllowFunctionProxy : 0);
-
-            HRESULT hr = Js::ByteCodeSerializer::DeserializeFromBuffer(scriptContext, flags, (LPCUTF8)nullptr, hsi, (byte*)Library_Bytecode_JsBuiltIn, nullptr, &jsBuiltInByteCode);
-
-            IfFailAssertMsgAndThrowHr(hr, "Failed to deserialize JsBuiltIn.js bytecode - very probably the bytecode needs to be rebuilt.");
-            this->SetHasBytecode();
+            sourceInfo = scriptContext->AddHostSrcInfo(&si);
         }
     }
 
@@ -299,46 +287,46 @@ namespace Js
     {
         EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
 
-        AssertOrFailFast(args.Info.Count == 3 && TaggedInt::Is(args.Values[1]) && VarIs<ScriptFunction>(args.Values[2]));
+        AssertOrFailFast(args.Info.Count == 3 && VarIs<ScriptFunction>(args.Values[2]));
 
         JavascriptLibrary * library = scriptContext->GetLibrary();
 
-        FunctionKind funcKind = static_cast<FunctionKind>(TaggedInt::ToInt32(args.Values[1]));
-        AssertOrFailFast(funcKind >= (FunctionKind)0 && funcKind < FunctionKind::Max);
+        // process function name and get property ID
+        JavascriptString* methodString = VarTo<JavascriptString>(args.Values[1]);
+        PropertyRecord* methodPropertyRecord = nullptr;
+        methodString->GetPropertyRecord((PropertyRecord const **) &methodPropertyRecord, false);
+        PropertyId methodPropID = methodPropertyRecord->GetPropertyId();
 
         DynamicObject *installTarget = nullptr;
         bool isStatic = false;
-        PropertyId methodPropID = PropertyIds::_none;
-        PropertyString *methodPropString = nullptr;
         PropertyString *classPropString = nullptr;
         JavascriptString *fullName = nullptr;
         JavascriptString *dot = library->GetDotString();
-        switch (funcKind)
+        JsBuiltInFile current = (static_cast<JsBuiltInEngineInterfaceExtensionObject*>(scriptContext->GetLibrary()
+            ->GetEngineInterfaceObject()->GetEngineExtension(EngineInterfaceExtensionKind_JsBuiltIn)))->current;
+
+        // determine what object this function is being added too
+        switch (current)
         {
-#define VALUE(ClassName, methodName, propertyType) \
-        case FunctionKind::ClassName##_##methodName: \
-            isStatic = static_cast<bool>(IsPropertyTypeStatic::##propertyType); \
-            installTarget = library->Get##ClassName##propertyType##(); \
-            methodPropID = PropertyIds::methodName; \
-            methodPropString = scriptContext->GetPropertyString(methodPropID); \
-            classPropString = scriptContext->GetPropertyString(PropertyIds::ClassName); \
-            break;
-FUNCTIONKIND_VALUES(VALUE)
-#undef VALUE
-        default:
-            AssertOrFailFastMsg(false, "funcKind should never be outside the range of projected values");
+            #define file(class, type, obj) \
+            case class##_##type: \
+                isStatic = static_cast<bool>(IsTypeStatic::##type); \
+                installTarget = library->Get##obj##(); \
+                classPropString = scriptContext->GetPropertyString(PropertyIds::class); \
+                break;
+            JsBuiltIns(file)
         }
 
-        Assert(methodPropString && classPropString && installTarget && methodPropID != PropertyIds::_none);
+        Assert(methodString && classPropString && installTarget && methodPropID != PropertyIds::_none);
 
         if (isStatic)
         {
-            fullName = JavascriptString::Concat3(classPropString, dot, methodPropString);
+            fullName = JavascriptString::Concat3(classPropString, dot, methodString);
         }
         else
         {
             JavascriptString *dotPrototypeDot = JavascriptString::Concat3(dot, scriptContext->GetPropertyString(PropertyIds::prototype), dot);
-            fullName = JavascriptString::Concat3(classPropString, dotPrototypeDot, methodPropString);
+            fullName = JavascriptString::Concat3(classPropString, dotPrototypeDot, methodString);
         }
 
         ScriptFunction *func = EngineInterfaceObject::CreateLibraryCodeScriptFunction(
@@ -351,59 +339,50 @@ FUNCTIONKIND_VALUES(VALUE)
 
         library->AddMember(installTarget, methodPropID, func);
 
-        // do extra logic here which didnt easily fit into the macro table
-        switch (funcKind)
+        // Make function available to other internal facilities that need it
+        // applicable for specific functions only - this may need review upon moving other functions into JsBuiltins
+        if (current == JsBuiltInFile::Array_prototype)
         {
-        case FunctionKind::Array_entries:
-            library->arrayPrototypeEntriesFunction = func;
-            break;
-        case FunctionKind::Array_values:
-            library->arrayPrototypeValuesFunction = func;
-            library->AddMember(installTarget, PropertyIds::_symbolIterator, func);
-            break;
-        case FunctionKind::Array_keys:
-            library->arrayPrototypeKeysFunction = func;
-            break;
-        case FunctionKind::Array_forEach:
-            library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryForEach, func);
-            break;
-        case FunctionKind::Array_filter:
-            library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryFilter, func);
-            break;
-        case FunctionKind::Array_indexOf:
-            library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryIndexOf, func);
-            break;
-        case FunctionKind::Array_some:
-            library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntrySome, func);
-            break;
-        case FunctionKind::Array_every:
-            library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryEvery, func);
-            break;
-        case FunctionKind::Array_includes:
-            library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryIncludes, func);
-            break;
-        case FunctionKind::Array_reduce:
-            library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryReduce, func);
-            break;
-        case FunctionKind::Math_max:
-            library->mathMax = func;
-            library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMathMax, func);
-            break;
-        case FunctionKind::Math_min:
-            library->mathMin = func;
-            library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMathMin, func);
-            break;
-        // FunctionKinds with no entry functions
-        case FunctionKind::Array_sort:
-        case FunctionKind::Array_flat:
-        case FunctionKind::Array_flatMap:
-        case FunctionKind::Object_fromEntries:
-            break;
-        default:
-            AssertOrFailFastMsg(false, "funcKind should never be outside the range of projected values");
-            break;
+            switch (methodPropID)
+            {
+                case PropertyIds::entries:
+                    library->arrayPrototypeEntriesFunction = func;
+                    break;
+                case PropertyIds::values:
+                    library->arrayPrototypeValuesFunction = func;
+                    library->AddMember(installTarget, PropertyIds::_symbolIterator, func);
+                    break;
+                case PropertyIds::keys:
+                    library->arrayPrototypeKeysFunction = func;
+                    break;
+                case PropertyIds::forEach:
+                    library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInArray_prototype_forEach, func);
+                    break;
+                case PropertyIds::filter:
+                    library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInArray_prototype_filter, func);
+                    break;
+                case PropertyIds::indexOf:
+                    library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInArray_prototype_indexOf, func);
+                    break;
+                case PropertyIds::reduce:
+                    library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInArray_prototype_reduce, func);
+                    break;
+            }
+        }
+        else if (current == JsBuiltInFile::Math_object)
+        {
+            switch (methodPropID)
+            {
+                case PropertyIds::max:
+                    library->mathMax = func;
+                    library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMath_object_max, func);
+                    break;
+                case PropertyIds::min:
+                    library->mathMin = func;
+                    library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMath_object_min, func);
+                    break;
+            }
         }
-
         //Don't need to return anything
         return library->GetUndefined();
     }

+ 18 - 4
lib/Runtime/Library/JsBuiltInEngineInterfaceExtensionObject.h

@@ -1,18 +1,26 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
 #ifdef ENABLE_JS_BUILTINS
 namespace Js
 {
+
+    #define enum_file(class, type, obj) class##_##type,
+    typedef enum {
+        JsBuiltIns(enum_file)
+    } JsBuiltInFile;
+    #undef enum_file
+
     class JsBuiltInEngineInterfaceExtensionObject : public EngineExtensionObjectBase
     {
     public:
         JsBuiltInEngineInterfaceExtensionObject(ScriptContext* scriptContext);
         void Initialize();
         void InitializePrototypes(ScriptContext * scriptContext);
-        void InjectJsBuiltInLibraryCode(ScriptContext * scriptContext);
+        void InjectJsBuiltInLibraryCode(ScriptContext * scriptContext, JsBuiltInFile file);
 
         static bool __cdecl InitializeJsBuiltInNativeInterfaces(DynamicObject* intlNativeInterfaces, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode);
 
@@ -36,11 +44,17 @@ namespace Js
 
     private:
         Field(DynamicObject*) builtInNativeInterfaces;
-        Field(FunctionBody*) jsBuiltInByteCode;
 
-        Field(bool) wasInitialized;
+        #define BuiltInFunctionBody(class, type, obj) Field(FunctionBody*) jsBuiltIn##class##_##type##Bytecode = nullptr;
+        JsBuiltIns(BuiltInFunctionBody)
+        #undef BuiltInFunctionBody
+
+        Field(JsBuiltInFile) current;
+        Field(bool) wasInitialized = false;
+        Field(SRCINFO*) sourceInfo = nullptr;
 
-        void EnsureJsBuiltInByteCode(ScriptContext * scriptContext);
+        void EnsureSourceInfo();
+        void JsBuiltInEngineInterfaceExtensionObject::DumpByteCode(JsBuiltInFile file);
 
         static Var EntryJsBuiltIn_RegisterChakraLibraryFunction(RecyclableObject* function, CallInfo callInfo, ...);
         static Var EntryJsBuiltIn_RegisterFunction(RecyclableObject* function, CallInfo callInfo, ...);