Skip to content

Commit 5af7feb

Browse files
author
Thomas Moore (CHAKRA)
committed
Enable Deferred Parsing for Background Parse
This change turns on Deferred Parsing in BGParseManager, which will reduce the amount of time needed to parse in the background. Appropriate flags are added in calls inside BGParseManager and BGParseWorkItem. Also, in order to serialize defer parsed bytecode, ScriptContext::CompileUTF8Core refactors the Parser object outside of the call because the serializer needs state from the parser to complete.
1 parent 0730b1f commit 5af7feb

File tree

11 files changed

+165
-37
lines changed

11 files changed

+165
-37
lines changed

bin/ch/HostConfigFlagsList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ FLAG(bool, TraceHostCallback, "Output traces for host callbacks",
1919
FLAG(bool, Test262, "load Test262 harness", false)
2020
FLAG(bool, TrackRejectedPromises, "Enable tracking of unhandled promise rejections", false)
2121
FLAG(BSTR, CustomConfigFile, "Custom config file to be used to pass in additional flags to Chakra", NULL)
22+
FLAG(bool, ExecuteWithBgParse, "[No-op] Load script with bgparse (note: requires bgparse to be on as well)", false)
2223
#undef FLAG
2324
#endif

lib/Common/ConfigFlagsList.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ FLAGR (NumberSet, BailOutByteCode , "Byte code location to insert BailOut. U
971971
#endif
972972
FLAGNR(Boolean, Benchmark , "Disable security code which introduce variability in benchmarks", false)
973973
FLAGR (Boolean, BgJit , "Background JIT. Disable to force heuristic-based foreground JITting. (default: true)", true)
974-
FLAGR (Boolean, BgParse , "Background Parse. Disable to force all parsing to occur on UI thread. (default: false)", false)
974+
FLAGR (Boolean, BgParse , "Background Parse. Disable to force all parsing to occur on UI thread. (default: true)", true)
975975
FLAGNR(Number, BgJitDelay , "Delay to wait for speculative jitting before starting script execution", DEFAULT_CONFIG_BgJitDelay)
976976
FLAGNR(Number, BgJitDelayFgBuffer , "When speculatively jitting in the foreground thread, do so for (BgJitDelay - BgJitDelayBuffer) milliseconds", DEFAULT_CONFIG_BgJitDelayFgBuffer)
977977
FLAGNR(Number, BgJitPendingFuncCap , "Disable delay if pending function count larger then cap", DEFAULT_CONFIG_BgJitPendingFuncCap)

lib/Parser/BGParseManager.cpp

Lines changed: 110 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
#include "Base/ScriptContext.h"
1515
#include "ByteCodeSerializer.h"
1616

17+
#define BGPARSE_FLAGS (fscrGlobalCode | fscrWillDeferFncParse | fscrCanDeferFncParse | fscrCreateParserState)
18+
1719
// Global, process singleton
1820
BGParseManager* BGParseManager::s_BGParseManager = nullptr;
1921
DWORD BGParseManager::s_lastCookie = 0;
22+
DWORD BGParseManager::s_completed = 0;
23+
DWORD BGParseManager::s_failed = 0;
2024
CriticalSection BGParseManager::s_staticMemberLock;
2125

2226
// Static member management
@@ -49,6 +53,17 @@ DWORD BGParseManager::GetNextCookie()
4953
return ++s_lastCookie;
5054
}
5155

56+
DWORD BGParseManager::IncCompleted()
57+
{
58+
AutoCriticalSection lock(&s_staticMemberLock);
59+
return ++s_completed;
60+
}
61+
DWORD BGParseManager::IncFailed()
62+
{
63+
AutoCriticalSection lock(&s_staticMemberLock);
64+
return ++s_failed;
65+
}
66+
5267

5368
// Note: runs on any thread
5469
BGParseManager::BGParseManager()
@@ -217,7 +232,16 @@ HRESULT BGParseManager::GetInputFromCookie(DWORD cookie, LPCUTF8* ppszSrc, size_
217232

218233
// Deserializes the background parse results into this thread
219234
// Note: *must* run on a UI/Execution thread with an available ScriptContext
220-
HRESULT BGParseManager::GetParseResults(Js::ScriptContext* scriptContextUI, DWORD cookie, LPCUTF8 pszSrc, SRCINFO const * pSrcInfo, Js::ParseableFunctionInfo** ppFunc, CompileScriptException* pse, size_t& srcLength)
235+
HRESULT BGParseManager::GetParseResults(
236+
Js::ScriptContext* scriptContextUI,
237+
DWORD cookie,
238+
LPCUTF8 pszSrc,
239+
SRCINFO const * pSrcInfo,
240+
Js::ParseableFunctionInfo** ppFunc,
241+
CompileScriptException* pse,
242+
size_t& srcLength,
243+
Js::Utf8SourceInfo* utf8SourceInfo,
244+
uint& sourceIndex)
221245
{
222246
// TODO: Is there a way to cache the environment from which serialization begins to
223247
// determine whether or not deserialization will succeed? Specifically, being able
@@ -232,25 +256,20 @@ HRESULT BGParseManager::GetParseResults(Js::ScriptContext* scriptContextUI, DWOR
232256
{
233257
// Synchronously wait for the job to complete
234258
workitem->WaitForCompletion();
259+
260+
Js::FunctionBody* functionBody = nullptr;
261+
hr = workitem->DeserializeParseResults(scriptContextUI, pszSrc, pSrcInfo, utf8SourceInfo, &functionBody, srcLength, sourceIndex);
262+
(*ppFunc) = functionBody;
263+
workitem->TransferCSE(pse);
235264

236-
Field(Js::FunctionBody*) functionBody = nullptr;
237-
hr = workitem->GetParseHR();
238265
if (hr == S_OK)
239266
{
240-
srcLength = workitem->GetParseSourceLength();
241-
hr = Js::ByteCodeSerializer::DeserializeFromBuffer(
242-
scriptContextUI,
243-
0, // flags
244-
(const byte *)pszSrc,
245-
pSrcInfo,
246-
workitem->GetReturnBuffer(),
247-
nullptr, // nativeModule
248-
&functionBody
249-
);
267+
BGParseManager::IncCompleted();
268+
}
269+
else
270+
{
271+
BGParseManager::IncFailed();
250272
}
251-
252-
*ppFunc = functionBody;
253-
workitem->TransferCSE(pse);
254273
}
255274

256275
if (PHASE_TRACE1(Js::BgParsePhase))
@@ -475,27 +494,42 @@ void BGParseWorkItem::ParseUTF8Core(Js::ScriptContext* scriptContext)
475494
}
476495

477496
SRCINFO si = {
478-
/* sourceContextInfo */ sourceContextInfo,
479-
/* dlnHost */ 0,
480-
/* ulColumnHost */ 0,
481-
/* lnMinHost */ 0,
482-
/* ichMinHost */ 0,
483-
/* ichLimHost */ (ULONG)0,
484-
/* ulCharOffset */ 0,
485-
/* mod */ 0,
486-
/* grfsi */ 0
497+
sourceContextInfo,
498+
0, // dlnHost
499+
0, // ulColumnHost
500+
0, // lnMinHost
501+
0, // ichMinHost
502+
static_cast<ULONG>(cb / sizeof(utf8char_t)), // ichLimHost
503+
0, // ulCharOffset
504+
kmodGlobal, // mod
505+
0 // grfsi
487506
};
488507

489-
// Currently always called from a try-catch
490508
ENTER_PINNED_SCOPE(Js::Utf8SourceInfo, sourceInfo);
491-
sourceInfo = Js::Utf8SourceInfo::NewWithNoCopy(scriptContext, (LPUTF8)this->script, (int32)this->cb, static_cast<int32>(this->cb), &si, false);
492-
LEAVE_PINNED_SCOPE();
509+
sourceInfo = Js::Utf8SourceInfo::NewWithNoCopy(scriptContext, (LPUTF8)this->script, (int32)this->cb, static_cast<int32>(this->cb), &si, false);
493510

494-
// what's a better name for "fIsOriginalUtf8Source?" what if i want to say "isutf8source" but not "isoriginal"?
495511
charcount_t cchLength = 0;
496512
uint sourceIndex = 0;
497513
Js::ParseableFunctionInfo * func = nullptr;
498-
this->parseHR = scriptContext->CompileUTF8Core(sourceInfo, &si, true, this->script, this->cb, fscrGlobalCode, &this->cse, cchLength, this->parseSourceLength, sourceIndex, &func, nullptr);
514+
515+
Parser ps(scriptContext);
516+
this->parseHR = scriptContext->CompileUTF8Core(
517+
ps,
518+
sourceInfo,
519+
&si,
520+
true, // fOriginalUtf8Code
521+
this->script,
522+
this->cb,
523+
BGPARSE_FLAGS,
524+
&this->cse,
525+
cchLength,
526+
this->parseSourceLength,
527+
sourceIndex,
528+
&func,
529+
nullptr // pDataCache
530+
);
531+
532+
499533
if (this->parseHR == S_OK)
500534
{
501535
BEGIN_TEMP_ALLOCATOR(tempAllocator, scriptContext, _u("BGParseWorkItem"));
@@ -510,7 +544,7 @@ void BGParseWorkItem::ParseUTF8Core(Js::ScriptContext* scriptContext)
510544
true, // allocateBuffer
511545
&this->bufferReturn,
512546
&this->bufferReturnBytes,
513-
0
547+
GENERATE_BYTE_CODE_PARSER_STATE
514548
);
515549
END_TEMP_ALLOCATOR(tempAllocator, scriptContext);
516550
Assert(this->parseHR == S_OK);
@@ -520,6 +554,51 @@ void BGParseWorkItem::ParseUTF8Core(Js::ScriptContext* scriptContext)
520554
Assert(this->cse.ei.bstrSource != nullptr);
521555
Assert(func == nullptr);
522556
}
557+
558+
LEAVE_PINNED_SCOPE();
559+
}
560+
561+
// Deserializes the background parse results into this thread
562+
// Note: *must* run on a UI/Execution thread with an available ScriptContext
563+
HRESULT BGParseWorkItem::DeserializeParseResults(
564+
Js::ScriptContext* scriptContextUI,
565+
LPCUTF8 pszSrc,
566+
SRCINFO const * pSrcInfo,
567+
Js::Utf8SourceInfo* utf8SourceInfo,
568+
Js::FunctionBody** functionBodyReturn,
569+
size_t& srcLength,
570+
uint& sourceIndex
571+
)
572+
{
573+
HRESULT hr = this->parseHR;
574+
if (hr == S_OK)
575+
{
576+
srcLength = this->parseSourceLength;
577+
sourceIndex = scriptContextUI->SaveSourceNoCopy(utf8SourceInfo, (int)srcLength, false /*isCesu8*/);
578+
Assert(sourceIndex != Js::Constants::InvalidSourceIndex);
579+
580+
Field(Js::FunctionBody*) functionBody = nullptr;
581+
hr = Js::ByteCodeSerializer::DeserializeFromBuffer(
582+
scriptContextUI,
583+
BGPARSE_FLAGS,
584+
(const byte *)pszSrc,
585+
pSrcInfo,
586+
this->bufferReturn,
587+
nullptr, // nativeModule
588+
&functionBody,
589+
sourceIndex
590+
);
591+
592+
if (hr == S_OK)
593+
{
594+
// The buffer is now owned by the output of DeserializeFromBuffer
595+
(*functionBodyReturn) = functionBody;
596+
this->bufferReturn = nullptr;
597+
this->bufferReturnBytes = 0;
598+
}
599+
}
600+
601+
return hr;
523602
}
524603

525604
void BGParseWorkItem::CreateCompletionEvent()

lib/Parser/BGParseManager.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class BGParseManager sealed : public JsUtil::WaitableJobManager
4848
static BGParseManager* GetBGParseManager();
4949
static void DeleteBGParseManager();
5050
static DWORD GetNextCookie();
51+
static DWORD IncCompleted();
52+
static DWORD IncFailed();
5153

5254
HRESULT QueueBackgroundParse(LPCUTF8 pszSrc, size_t cbLength, char16 *fullPath, DWORD* dwBgParseCookie);
5355
HRESULT GetInputFromCookie(DWORD cookie, LPCUTF8* ppszSrc, size_t* pcbLength);
@@ -58,7 +60,9 @@ class BGParseManager sealed : public JsUtil::WaitableJobManager
5860
SRCINFO const * pSrcInfo,
5961
Js::ParseableFunctionInfo** ppFunc,
6062
CompileScriptException* pse,
61-
size_t& srcLength
63+
size_t& srcLength,
64+
Js::Utf8SourceInfo* utf8SourceInfo,
65+
uint& sourceIndex
6266
);
6367
bool DiscardParseResults(DWORD cookie, void* buffer);
6468

@@ -81,6 +85,8 @@ class BGParseManager sealed : public JsUtil::WaitableJobManager
8185
JsUtil::DoublyLinkedList<BGParseWorkItem> workitemsProcessed;
8286

8387
static DWORD s_lastCookie;
88+
static DWORD s_completed;
89+
static DWORD s_failed;
8490
static BGParseManager* s_BGParseManager;
8591
static CriticalSection s_staticMemberLock;
8692
};
@@ -100,6 +106,15 @@ class BGParseWorkItem sealed : public JsUtil::Job
100106
~BGParseWorkItem();
101107

102108
void ParseUTF8Core(Js::ScriptContext* scriptContext);
109+
HRESULT DeserializeParseResults(
110+
Js::ScriptContext* scriptContextUI,
111+
LPCUTF8 pszSrc,
112+
SRCINFO const * pSrcInfo,
113+
Js::Utf8SourceInfo* utf8SourceInfo,
114+
Js::FunctionBody** functionBodyReturn,
115+
size_t& srcLength,
116+
uint& sourceIndex
117+
);
103118
void TransferCSE(CompileScriptException* pse);
104119

105120
void CreateCompletionEvent();
@@ -112,9 +127,6 @@ class BGParseWorkItem sealed : public JsUtil::Job
112127
DWORD GetCookie() const { return cookie; }
113128
const byte* GetScriptSrc() const { return script; }
114129
size_t GetScriptLength() const { return cb; }
115-
byte * GetReturnBuffer() const{ return bufferReturn; }
116-
HRESULT GetParseHR() const { return parseHR; }
117-
size_t GetParseSourceLength() const { return parseSourceLength; }
118130

119131
private:
120132
// This cookie is the public identifier for this parser work

lib/Runtime/Base/ScriptContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2260,6 +2260,7 @@ namespace Js
22602260
}
22612261

22622262
HRESULT ScriptContext::CompileUTF8Core(
2263+
__in Parser& ps,
22632264
__in Js::Utf8SourceInfo* utf8SourceInfo,
22642265
__in SRCINFO *srcInfo,
22652266
__in BOOL fOriginalUTF8Code,
@@ -2275,7 +2276,6 @@ namespace Js
22752276
)
22762277
{
22772278
HRESULT hr = E_FAIL;
2278-
Parser ps(this);
22792279
(*func) = nullptr;
22802280
srcLength = cchLength;
22812281

lib/Runtime/Base/ScriptContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,7 @@ namespace Js
13081308
_In_ Js::SimpleDataCacheWrapper* pDataCache);
13091309

13101310
HRESULT CompileUTF8Core(
1311+
__in Parser& ps,
13111312
__in Js::Utf8SourceInfo* utf8SourceInfo,
13121313
__in SRCINFO *srcInfo,
13131314
__in BOOL fOriginalUTF8Code,

test/Math/rlexe.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@
102102
<baseline>sin.baseline</baseline>
103103
</default>
104104
</test>
105+
<test>
106+
<default>
107+
<files>sin.js</files>
108+
<baseline>sin.baseline</baseline>
109+
<compile-flags>-ExecuteWithBgParse</compile-flags>
110+
</default>
111+
</test>
105112
<test>
106113
<default>
107114
<files>sqrt.js</files>

test/Object/rlexe.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@
4242
<baseline>Object.baseline</baseline>
4343
</default>
4444
</test>
45+
<test>
46+
<default>
47+
<files>Object.js</files>
48+
<baseline>Object.baseline</baseline>
49+
<compile-flags>-ExecuteWithBgParse</compile-flags>
50+
</default>
51+
</test>
4552
<test>
4653
<default>
4754
<files>null.js</files>

test/Optimizer/rlexe.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,12 @@
915915
<files>test127.js</files>
916916
</default>
917917
</test>
918+
<test>
919+
<default>
920+
<files>test127.js</files>
921+
<compile-flags>-ExecuteWithBgParse</compile-flags>
922+
</default>
923+
</test>
918924
<test>
919925
<default>
920926
<files>test128.js</files>

test/Strings/rlexe.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,13 @@
212212
<baseline>long_concatstr.baseline</baseline>
213213
</default>
214214
</test>
215+
<test>
216+
<default>
217+
<files>long_concatstr.js</files>
218+
<baseline>long_concatstr.baseline</baseline>
219+
<compile-flags>-ExecuteWithBgParse</compile-flags>
220+
</default>
221+
</test>
215222
<test>
216223
<default>
217224
<files>StringTagFunctions.js</files>

0 commit comments

Comments
 (0)