Skip to content

Commit fb1c04f

Browse files
author
Thomas Moore (CHAKRA)
committed
[MERGE #5830 @thomasmo] Expose BGParse through new JSRT APIs
Merge pull request #5830 from thomasmo:bgparse_core This change introduces new experimental JSRT APIs to expose the functionality of BGParseManager: - JsQueueBackgroundParse_Experimental - JsDiscardBackgroundParse_Experimental - JsExecuteBackgroundParse_Experimental This gives ChakraCore a programmatic means to move script parsing off of the UI thread. Changes are also made in ch.exe to exercise these APIs for testing. Additional changes are made elsewhere for proper cleanup during shutdown. This feature is still off by default. To test in ch.exe, the following flags are required: "-bgparse -executewithbgparse -parserstatecache"
2 parents 1633d80 + 5c787ed commit fb1c04f

13 files changed

+393
-81
lines changed

bin/ChakraCore/ChakraCore.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,7 @@ JsSerializeParserState
7070
JsRunScriptWithParserState
7171
JsGetPromiseState
7272
JsGetPromiseResult
73+
74+
JsQueueBackgroundParse_Experimental
75+
JsDiscardBackgroundParse_Experimental
76+
JsExecuteBackgroundParse_Experimental

bin/ChakraCore/ChakraCoreDllFunc.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ EXTERN_C BOOL WINAPI DllMain(HINSTANCE hmod, DWORD dwReason, PVOID pvReserved)
153153
#if defined(CHECK_MEMORY_LEAK) || defined(LEAK_REPORT)
154154
else
155155
{
156+
ThreadBoundThreadContextManager::DestroyAllContexts();
157+
DetachProcess();
156158
ThreadContext::ReportAndCheckLeaksOnProcessDetach();
157159
}
158160
#endif

bin/ch/ChakraRtInterface.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ bool ChakraRTInterface::LoadChakraDll(ArgInfo* argInfo, HINSTANCE *outLibrary)
160160
m_jsApiHooks.pfJsrtSerializeParserState = (JsAPIHooks::JsrtSerializeParserState)GetChakraCoreSymbol(library, "JsSerializeParserState");
161161
m_jsApiHooks.pfJsrtRunScriptWithParserState = (JsAPIHooks::JsrtRunScriptWithParserState)GetChakraCoreSymbol(library, "JsRunScriptWithParserState");
162162

163+
m_jsApiHooks.pfJsrtQueueBackgroundParse_Experimental = (JsAPIHooks::JsrtQueueBackgroundParse_Experimental)GetChakraCoreSymbol(library, "JsQueueBackgroundParse_Experimental");
164+
m_jsApiHooks.pfJsrtDiscardBackgroundParse_Experimental = (JsAPIHooks::JsrtDiscardBackgroundParse_Experimental)GetChakraCoreSymbol(library, "JsDiscardBackgroundParse_Experimental");
165+
m_jsApiHooks.pfJsrtExecuteBackgroundParse_Experimental = (JsAPIHooks::JsrtExecuteBackgroundParse_Experimental)GetChakraCoreSymbol(library, "JsExecuteBackgroundParse_Experimental");
166+
163167
m_jsApiHooks.pfJsrtTTDCreateRecordRuntime = (JsAPIHooks::JsrtTTDCreateRecordRuntimePtr)GetChakraCoreSymbol(library, "JsTTDCreateRecordRuntime");
164168
m_jsApiHooks.pfJsrtTTDCreateReplayRuntime = (JsAPIHooks::JsrtTTDCreateReplayRuntimePtr)GetChakraCoreSymbol(library, "JsTTDCreateReplayRuntime");
165169
m_jsApiHooks.pfJsrtTTDCreateContext = (JsAPIHooks::JsrtTTDCreateContextPtr)GetChakraCoreSymbol(library, "JsTTDCreateContext");

bin/ch/ChakraRtInterface.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ struct JsAPIHooks
9292

9393
typedef JsErrorCode(WINAPI *JsrtSerializeParserState)(JsValueRef script, JsValueRef *buffer, JsParseScriptAttributes parseAttributes);
9494
typedef JsErrorCode(WINAPI *JsrtRunScriptWithParserState)(JsValueRef script, JsSourceContext sourceContext, JsValueRef sourceUrl, JsParseScriptAttributes parseAttributes, JsValueRef parserState, JsValueRef *result);
95+
96+
typedef JsErrorCode(WINAPI *JsrtQueueBackgroundParse_Experimental)(JsScriptContents* contents, DWORD* dwBgParseCookie);
97+
typedef JsErrorCode(WINAPI *JsrtDiscardBackgroundParse_Experimental)(DWORD dwBgParseCookie, void* buffer, bool* callerOwnsBuffer);
98+
typedef JsErrorCode(WINAPI *JsrtExecuteBackgroundParse_Experimental)(DWORD dwBgParseCookie, JsValueRef script, JsSourceContext sourceContext, WCHAR *url, JsParseScriptAttributes parseAttributes, JsValueRef parserState, JsValueRef *result);
9599

96100
typedef JsErrorCode(WINAPI *JsrtTTDCreateRecordRuntimePtr)(JsRuntimeAttributes attributes, bool enableDebugging, size_t snapInterval, size_t snapHistoryLength, TTDOpenResourceStreamCallback openResourceStream, JsTTDWriteBytesToStreamCallback writeBytesToStream, JsTTDFlushAndCloseStreamCallback flushAndCloseStream, JsThreadServiceCallback threadService, JsRuntimeHandle *runtime);
97101
typedef JsErrorCode(WINAPI *JsrtTTDCreateReplayRuntimePtr)(JsRuntimeAttributes attributes, const char* infoUri, size_t infoUriCount, bool enableDebugging, TTDOpenResourceStreamCallback openResourceStream, JsTTDReadBytesFromStreamCallback readBytesFromStream, JsTTDFlushAndCloseStreamCallback flushAndCloseStream, JsThreadServiceCallback threadService, JsRuntimeHandle *runtime);
@@ -195,6 +199,10 @@ struct JsAPIHooks
195199
JsrtSerializeParserState pfJsrtSerializeParserState;
196200
JsrtRunScriptWithParserState pfJsrtRunScriptWithParserState;
197201

202+
JsrtQueueBackgroundParse_Experimental pfJsrtQueueBackgroundParse_Experimental;
203+
JsrtDiscardBackgroundParse_Experimental pfJsrtDiscardBackgroundParse_Experimental;
204+
JsrtExecuteBackgroundParse_Experimental pfJsrtExecuteBackgroundParse_Experimental;
205+
198206
JsrtTTDCreateRecordRuntimePtr pfJsrtTTDCreateRecordRuntime;
199207
JsrtTTDCreateReplayRuntimePtr pfJsrtTTDCreateReplayRuntime;
200208
JsrtTTDCreateContextPtr pfJsrtTTDCreateContext;
@@ -430,6 +438,10 @@ class ChakraRTInterface
430438

431439
static JsErrorCode WINAPI JsSerializeParserState(JsValueRef script, JsValueRef *buffer, JsParseScriptAttributes parseAttributes) { return HOOK_JS_API(SerializeParserState(script, buffer, parseAttributes)); }
432440
static JsErrorCode WINAPI JsRunScriptWithParserState(JsValueRef script, JsSourceContext sourceContext, JsValueRef sourceUrl, JsParseScriptAttributes parseAttributes, JsValueRef parserState, JsValueRef * result) { return HOOK_JS_API(RunScriptWithParserState(script, sourceContext, sourceUrl, parseAttributes, parserState, result)); }
441+
442+
static JsErrorCode WINAPI JsQueueBackgroundParse_Experimental(JsScriptContents* contents, DWORD* dwBgParseCookie) { return HOOK_JS_API(QueueBackgroundParse_Experimental)(contents, dwBgParseCookie); }
443+
static JsErrorCode WINAPI JsDiscardBackgroundParse_Experimental(DWORD dwBgParseCookie, void* buffer, bool* callerOwnsBuffer) { return HOOK_JS_API(DiscardBackgroundParse_Experimental(dwBgParseCookie, buffer, callerOwnsBuffer)); }
444+
static JsErrorCode WINAPI JsExecuteBackgroundParse_Experimental(DWORD dwBgParseCookie, JsValueRef script, JsSourceContext sourceContext, WCHAR *url, JsParseScriptAttributes parseAttributes, JsValueRef parserState, JsValueRef *result) { return HOOK_JS_API(ExecuteBackgroundParse_Experimental(dwBgParseCookie, script, sourceContext, url, parseAttributes, parserState, result)); }
433445
};
434446

435447
class AutoRestoreContext

bin/ch/HostConfigFlagsList.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ FLAG(bool, Test262, "load Test262 harness", false)
2020
FLAG(bool, Module, "load the script as a module", false)
2121
FLAG(bool, TrackRejectedPromises, "Enable tracking of unhandled promise rejections", false)
2222
FLAG(BSTR, CustomConfigFile, "Custom config file to be used to pass in additional flags to Chakra", NULL)
23-
FLAG(bool, ExecuteWithBgParse, "[No-op] Load script with bgparse (note: requires bgparse to be on as well)", false)
23+
FLAG(bool, ExecuteWithBgParse, "Load script with bgparse (note: requires bgparse and parserstatecache be on as well)", false)
2424
#undef FLAG
2525
#endif

bin/ch/WScriptJsrt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ class WScriptJsrt
8989
return _u("FatalError");
9090
case (JsErrorCode::JsErrorInExceptionState) :
9191
return _u("ErrorInExceptionState");
92+
case (JsErrorCode::JsErrorBadSerializedScript):
93+
return _u("ErrorBadSerializedScript ");
9294
default:
9395
AssertMsg(false, "Unexpected JsErrorCode");
9496
return nullptr;

bin/ch/ch.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ UINT32 snapHistoryLength = MAXUINT32;
3939
LPCWSTR connectionUuidString = NULL;
4040
UINT32 startEventCount = 1;
4141

42+
HRESULT RunBgParseSync(LPCSTR fileContents, UINT lengthBytes, const char* fileName);
43+
4244
extern "C"
4345
HRESULT __stdcall OnChakraCoreLoadedEntry(TestHooks& testHooks)
4446
{
@@ -456,14 +458,20 @@ HRESULT RunScript(const char* fileName, LPCSTR fileContents, size_t fileLength,
456458
{
457459
runScript = WScriptJsrt::ModuleEntryPoint(fileName, fileContents, fullPath);
458460
}
461+
else if (HostConfigFlags::flags.ExecuteWithBgParse && !HostConfigFlags::flags.DebugLaunch)
462+
{
463+
unsigned int lengthBytes = (unsigned int) fileLength;
464+
runScript = (JsErrorCode)RunBgParseSync(fileContents, lengthBytes, fileName);
465+
}
459466
else // bufferValue == nullptr && parserStateCache == nullptr
460467
{
461468
JsValueRef scriptSource;
462469
IfJsErrorFailLog(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContents,
463470
(unsigned int)fileLength,
464471
fileContentsFinalizeCallback, (void*)fileContents, &scriptSource));
472+
465473
#if ENABLE_TTD
466-
if(doTTRecord)
474+
if (doTTRecord)
467475
{
468476
JsPropertyIdRef ttProperty = nullptr;
469477
JsValueRef ttString = nullptr;
@@ -755,6 +763,47 @@ HRESULT CreateAndRunSerializedScript(const char* fileName, LPCSTR fileContents,
755763
return hr;
756764
}
757765

766+
// Use the asynchronous BGParse JSRT APIs in a synchronous call
767+
HRESULT RunBgParseSync(LPCSTR fileContents, UINT lengthBytes, const char* fileName)
768+
{
769+
JsValueRef scriptSource;
770+
JsErrorCode e = (ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContents,
771+
(unsigned int)lengthBytes,
772+
nullptr, (void*)fileContents, &scriptSource));
773+
774+
// What's the preferred way of doing this?
775+
WCHAR fileNameWide[MAX_PATH] = { 0 };
776+
size_t fileNameLength = strlen(fileName);
777+
for (size_t i = 0; i < fileNameLength; i++)
778+
{
779+
fileNameWide[i] = fileName[i];
780+
}
781+
782+
JsScriptContents scriptContents = { 0 };
783+
scriptContents.container = (LPVOID)fileContents;
784+
scriptContents.containerType = JsScriptContainerType::HeapAllocatedBuffer;
785+
scriptContents.encodingType = JsScriptEncodingType::Utf8;
786+
scriptContents.contentLengthInBytes = lengthBytes;
787+
scriptContents.fullPath = fileNameWide;
788+
789+
DWORD cookie = 0;
790+
e = ChakraRTInterface::JsQueueBackgroundParse_Experimental(&scriptContents, &cookie);
791+
Assert(e == JsErrorCode::JsNoError);
792+
793+
JsValueRef bgResult = nullptr;
794+
e = ChakraRTInterface::JsExecuteBackgroundParse_Experimental(
795+
cookie,
796+
scriptSource,
797+
WScriptJsrt::GetNextSourceContext(),
798+
(WCHAR*)scriptContents.fullPath,
799+
JsParseScriptAttributes::JsParseScriptAttributeNone,
800+
nullptr,//_In_ JsValueRef parserState,
801+
&bgResult
802+
);
803+
804+
return e;
805+
}
806+
758807
HRESULT ExecuteTest(const char* fileName)
759808
{
760809
HRESULT hr = S_OK;

lib/Jsrt/ChakraCommon.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,27 @@ typedef unsigned short uint16_t;
625625
JsDataView = 12,
626626
} JsValueType;
627627

628+
typedef enum _JsScriptEncodingType
629+
{
630+
Utf8,
631+
Utf16
632+
} JsScriptEncodingType;
633+
634+
typedef enum _JsScriptContainerType
635+
{
636+
HeapAllocatedBuffer
637+
} JsScriptContainerType;
638+
639+
typedef struct _JsScriptContents
640+
{
641+
void * container;
642+
JsScriptEncodingType encodingType;
643+
JsScriptContainerType containerType;
644+
JsSourceContext sourceContext;
645+
size_t contentLengthInBytes;
646+
WCHAR * fullPath;
647+
} JsScriptContents;
648+
628649
/// <summary>
629650
/// User implemented callback routine for memory allocation events
630651
/// </summary>
@@ -2413,6 +2434,60 @@ typedef unsigned short uint16_t;
24132434
_In_opt_ JsPromiseContinuationCallback promiseContinuationCallback,
24142435
_In_opt_ void *callbackState);
24152436

2437+
/// <summary>
2438+
/// Note: Experimental API
2439+
/// Starts a request for background script parsing on another thread
2440+
/// </summary>
2441+
/// <param name="contents">ScriptContents struct with data needed to start parsing</param>
2442+
/// <param name="dwBgParseCookie">Identifier for subsequent BGParse operations</param>
2443+
/// <returns>
2444+
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
2445+
/// </returns>
2446+
CHAKRA_API
2447+
JsQueueBackgroundParse_Experimental(
2448+
_In_ JsScriptContents* contents,
2449+
_Out_ DWORD* dwBgParseCookie);
2450+
2451+
/// <summary>
2452+
/// Note: Experimental API
2453+
/// Appropriately frees resources associated with a previously queued background parse
2454+
/// </summary>
2455+
/// <param name="dwBgParseCookie">Identifier for BGParse operation</param>
2456+
/// <param name="buffer">Pointer to script source buffer, used for validation</param>
2457+
/// <param name="callerOwnsBuffer">When <c>true</c>, caller is responsible for freeing buffer</param>
2458+
/// <returns>
2459+
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
2460+
/// </returns>
2461+
CHAKRA_API
2462+
JsDiscardBackgroundParse_Experimental(
2463+
_In_ DWORD dwBgParseCookie,
2464+
_In_ void* buffer,
2465+
_Out_ bool* callerOwnsBuffer);
2466+
2467+
/// <summary>
2468+
/// Note: Experimental API
2469+
/// Executes the background parsed script
2470+
/// </summary>
2471+
/// <param name="dwBgParseCookie">Identifier for subsequent BGParse operations</param>
2472+
/// <param name="script">Pointer to script source</param>
2473+
/// <param name="sourceContext">JsSourceContext identifier</param>
2474+
/// <param name="url">Path to the parsed script</param>
2475+
/// <param name="parseAttributes"></param>
2476+
/// <param name="parserState">[May not be needed]</param>
2477+
/// <param name="result">Result of script execution</param>
2478+
/// <returns>
2479+
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
2480+
/// </returns>
2481+
CHAKRA_API
2482+
JsExecuteBackgroundParse_Experimental(
2483+
_In_ DWORD dwBgParseCookie,
2484+
_In_ JsValueRef script,
2485+
_In_ JsSourceContext sourceContext,
2486+
_In_ WCHAR *url,
2487+
_In_ JsParseScriptAttributes parseAttributes,
2488+
_In_ JsValueRef parserState,
2489+
_Out_ JsValueRef *result);
2490+
24162491
#ifdef _WIN32
24172492
#include "ChakraCommonWindows.h"
24182493
#endif // _WIN32

0 commit comments

Comments
 (0)