Skip to content

Commit c7c6c6e

Browse files
committed
[MERGE #5170 @boingoing] Reuse the deserialized buffer when serializing parser state cache
Merge pull request #5170 from boingoing:ReuseDeserializedParserStateCacheBuffer We serialize the parser state cache after either deserializing from the cache stream or generating bytecode and serializing that. If we succeeded to deserialize the parser state cache from a buffer retrieved from the cache stream, we can avoid serializing the bytecode into a buffer again.
2 parents 939ab74 + c404af8 commit c7c6c6e

File tree

2 files changed

+49
-18
lines changed

2 files changed

+49
-18
lines changed

lib/Runtime/Base/ScriptContext.cpp

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,14 +2126,20 @@ namespace Js
21262126
_In_ bool isCesu8,
21272127
_In_opt_ NativeModule* nativeModule,
21282128
_Out_ Js::ParseableFunctionInfo ** func,
2129+
_Out_ byte** parserStateCacheBuffer,
2130+
_Out_ DWORD* parserStateCacheByteCount,
21292131
_In_ Js::SimpleDataCacheWrapper* pDataCache)
21302132
{
21312133
HRESULT hr = E_FAIL;
21322134

21332135
Assert(pDataCache != nullptr);
21342136
Assert(func != nullptr);
2137+
Assert(parserStateCacheBuffer != nullptr);
2138+
Assert(parserStateCacheByteCount != nullptr);
21352139

21362140
*func = nullptr;
2141+
*parserStateCacheBuffer = nullptr;
2142+
*parserStateCacheByteCount = 0;
21372143

21382144
#ifdef ENABLE_WININET_PROFILE_DATA_CACHE
21392145
// Find the parser state block in the read stream and get the size of the block in bytes.
@@ -2190,13 +2196,17 @@ namespace Js
21902196

21912197
if (FAILED(hr))
21922198
{
2199+
AdeleteArray(alloc, byteCount, buffer);
2200+
21932201
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Failed to deserialize parser state cache (hr = 0x%08lx) for '%s'\n"), hr, url);
21942202
return hr;
21952203
}
21962204

21972205
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Successfully deserialized parser state cache for '%s'\n"), url);
21982206

21992207
*func = functionBody->GetParseableFunctionInfo();
2208+
*parserStateCacheBuffer = buffer;
2209+
*parserStateCacheByteCount = byteCount;
22002210
#endif
22012211

22022212
return hr;
@@ -2207,6 +2217,8 @@ namespace Js
22072217
_In_ size_t cbLength,
22082218
_In_ SRCINFO *srcInfo,
22092219
_In_ Js::ParseableFunctionInfo* func,
2220+
_In_ byte* parserStateCacheBuffer,
2221+
_In_ DWORD parserStateCacheByteCount,
22102222
_In_ Js::SimpleDataCacheWrapper* pDataCache)
22112223
{
22122224
HRESULT hr = E_FAIL;
@@ -2215,38 +2227,51 @@ namespace Js
22152227
Assert(pDataCache != nullptr);
22162228

22172229
#ifdef ENABLE_WININET_PROFILE_DATA_CACHE
2218-
byte* parserStateCacheBuffer = nullptr;
2219-
DWORD parserStateCacheSize = 0;
2230+
byte* serializeParserStateCacheBuffer = parserStateCacheBuffer;
2231+
DWORD serializeParserStateCacheSize = parserStateCacheByteCount;
22202232
DWORD dwFlags = GENERATE_BYTE_CODE_PARSER_STATE;
22212233
DebugOnly(auto url = !srcInfo->sourceContextInfo->isHostDynamicDocument ? srcInfo->sourceContextInfo->url : this->GetUrl());
22222234

2223-
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Trying to serialize parser state cache for '%s'\n"), url);
2235+
// If we already have a parser state cache serialized into a buffer, we should skip creating it again
2236+
if (parserStateCacheBuffer == nullptr)
2237+
{
2238+
Assert(serializeParserStateCacheSize == 0);
22242239

2225-
BEGIN_TEMP_ALLOCATOR(tempAllocator, this, _u("ByteCodeSerializer"));
2226-
hr = Js::ByteCodeSerializer::SerializeToBuffer(this,
2227-
tempAllocator, (DWORD)cbLength, pszSrc, func->GetFunctionBody(),
2228-
func->GetHostSrcInfo(), true, &parserStateCacheBuffer,
2229-
&parserStateCacheSize, dwFlags);
2230-
END_TEMP_ALLOCATOR(tempAllocator, this);
2240+
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Trying to serialize parser state cache for '%s'\n"), url);
22312241

2232-
if (FAILED(hr))
2242+
BEGIN_TEMP_ALLOCATOR(tempAllocator, this, _u("ByteCodeSerializer"));
2243+
hr = Js::ByteCodeSerializer::SerializeToBuffer(this,
2244+
tempAllocator, (DWORD)cbLength, pszSrc, func->GetFunctionBody(),
2245+
func->GetHostSrcInfo(), true, &serializeParserStateCacheBuffer,
2246+
&serializeParserStateCacheSize, dwFlags);
2247+
END_TEMP_ALLOCATOR(tempAllocator, this);
2248+
2249+
if (FAILED(hr))
2250+
{
2251+
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Failed to serialize parser state cache (hr = 0x%08lx) for '%s'\n"), hr, url);
2252+
return hr;
2253+
}
2254+
2255+
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Successfully serialized parser state cache for '%s'\n"), url);
2256+
}
2257+
else
22332258
{
2234-
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Failed to serialize parser state cache (hr = 0x%08lx) for '%s'\n"), hr, url);
2235-
return hr;
2259+
Assert(serializeParserStateCacheSize != 0);
2260+
2261+
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Skip serializing parser state cache since deserialized cache is available for '%s'\n"), url);
22362262
}
22372263

2238-
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Successfully serialized parser state cache for '%s'\n"), url);
2239-
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Trying to write parser state cache (%lu bytes) to stream for '%s'\n"), parserStateCacheSize, url);
2264+
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Trying to write parser state cache (%lu bytes) to stream for '%s'\n"), serializeParserStateCacheSize, url);
22402265

2241-
hr = pDataCache->StartBlock(Js::SimpleDataCacheWrapper::BlockType_ParserState, parserStateCacheSize);
2266+
hr = pDataCache->StartBlock(Js::SimpleDataCacheWrapper::BlockType_ParserState, serializeParserStateCacheSize);
22422267

22432268
if (FAILED(hr))
22442269
{
22452270
OUTPUT_TRACE_DEBUGONLY(Js::DataCachePhase, _u(" Failed to write a block to the parser state cache data stream (hr = 0x%08lx) for '%s'\n"), hr, url);
22462271
return hr;
22472272
}
22482273

2249-
hr = pDataCache->WriteArray(parserStateCacheBuffer, parserStateCacheSize);
2274+
hr = pDataCache->WriteArray(serializeParserStateCacheBuffer, serializeParserStateCacheSize);
22502275

22512276
if (FAILED(hr))
22522277
{
@@ -2287,10 +2312,12 @@ namespace Js
22872312
&& CONFIG_FLAG(ParserStateCache)
22882313
&& pDataCache != nullptr
22892314
&& !this->IsScriptContextInDebugMode();
2315+
byte* parserStateCacheBuffer = nullptr;
2316+
DWORD parserStateCacheByteCount = 0;
22902317

22912318
if (fUseParserStateCache)
22922319
{
2293-
hr = TryDeserializeParserState(grfscr, cchLength, srcInfo, utf8SourceInfo, sourceIndex, isCesu8, nullptr, func, pDataCache);
2320+
hr = TryDeserializeParserState(grfscr, cchLength, srcInfo, utf8SourceInfo, sourceIndex, isCesu8, nullptr, func, &parserStateCacheBuffer, &parserStateCacheByteCount, pDataCache);
22942321
#ifdef ENABLE_WININET_PROFILE_DATA_CACHE
22952322
// ERROR_WRITE_PROTECT indicates we cannot cache this script for whatever reason.
22962323
// Disable generating and serializing the parser state cache.
@@ -2339,7 +2366,7 @@ namespace Js
23392366
if (fUseParserStateCache)
23402367
{
23412368
Assert(*func != nullptr);
2342-
TrySerializeParserState(pszSrc, cbLength, srcInfo, *func, pDataCache);
2369+
TrySerializeParserState(pszSrc, cbLength, srcInfo, *func, parserStateCacheBuffer, parserStateCacheByteCount, pDataCache);
23432370
}
23442371
}
23452372
#ifdef ENABLE_SCRIPT_DEBUGGING

lib/Runtime/Base/ScriptContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,13 +1298,17 @@ namespace Js
12981298
_In_ bool isCesu8,
12991299
_In_opt_ NativeModule* nativeModule,
13001300
_Out_ Js::ParseableFunctionInfo ** func,
1301+
_Out_ byte** parserStateCacheBuffer,
1302+
_Out_ DWORD* parserStateCacheByteCount,
13011303
_In_ Js::SimpleDataCacheWrapper* pDataCache);
13021304

13031305
HRESULT TrySerializeParserState(
13041306
_In_ LPCUTF8 pszSrc,
13051307
_In_ size_t cbLength,
13061308
_In_ SRCINFO *srcInfo,
13071309
_In_ Js::ParseableFunctionInfo* func,
1310+
_In_ byte* parserStateCacheBuffer,
1311+
_In_ DWORD parserStateCacheByteCount,
13081312
_In_ Js::SimpleDataCacheWrapper* pDataCache);
13091313

13101314
HRESULT CompileUTF8Core(

0 commit comments

Comments
 (0)