Skip to content

Commit 3162205

Browse files
committed
[MERGE #5208 @boingoing] OS#16855035 - Properly support redeferral for serialized defer-parsed functions
Merge pull request #5208 from boingoing:redefer_for_serialized_defer_parse When we redeferred and subsequently reparsed a function which was defer-parsed and deserialized from bytecode, we took the null captured names set off of the new ParseNode and used it to generate a set of empty deferred stubs for the function. When we skipped scanning nested functions we didn't push references to their captured names. This caused us to try and load from invalid slots at runtime. We also lost the set of deferred stubs stored in ParseableFunctionInfo AuxPtrs during one of the duplication hops when we duplicate a FunctionProxy. Fixes: https://microsoft.visualstudio.com/OS/_workitems/edit/16855035
2 parents db37d77 + 1d0f7c4 commit 3162205

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

lib/Runtime/Base/FunctionBody.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,6 @@ namespace Js
728728
SetCountField(CounterFields::ConstantCount, 1);
729729

730730
proxy->UpdateFunctionBodyImpl(this);
731-
this->SetDeferredStubs(proxy->GetDeferredStubs());
732731

733732
this->m_defaultEntryPointInfo = RecyclerNewFinalized(scriptContext->GetRecycler(),
734733
FunctionEntryPointInfo, this, scriptContext->CurrentThunk, scriptContext->GetThreadContext());
@@ -1456,6 +1455,7 @@ namespace Js
14561455
CopyDeferParseField(m_inParamCount);
14571456
CopyDeferParseField(m_grfscr);
14581457
other->SetScopeInfo(this->GetScopeInfo());
1458+
other->SetDeferredStubs(this->GetDeferredStubs());
14591459
CopyDeferParseField(m_utf8SourceHasBeenSet);
14601460
#if DBG
14611461
CopyDeferParseField(deferredParseNextFunctionId);
@@ -4993,7 +4993,6 @@ namespace Js
49934993
this->SetStatementMaps(nullptr);
49944994
this->SetCodeGenGetSetRuntimeData(nullptr);
49954995
this->SetPropertyIdOnRegSlotsContainer(nullptr);
4996-
this->SetDeferredStubs(nullptr);
49974996
this->profiledLdLenCount = 0;
49984997
this->profiledLdElemCount = 0;
49994998
this->profiledStElemCount = 0;

lib/Runtime/ByteCode/ByteCodeEmitter.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2770,7 +2770,7 @@ void ByteCodeGenerator::EmitOneFunction(ParseNodeFnc *pnodeFnc)
27702770

27712771
if (funcInfo->root->pnodeBody == nullptr)
27722772
{
2773-
if (!PHASE_OFF1(Js::SkipNestedDeferredPhase) && (this->GetFlags() & fscrCreateParserState) == fscrCreateParserState)
2773+
if (!PHASE_OFF1(Js::SkipNestedDeferredPhase) && (this->GetFlags() & fscrCreateParserState) == fscrCreateParserState && deferParseFunction->GetCompileCount() == 0)
27742774
{
27752775
deferParseFunction->BuildDeferredStubs(funcInfo->root);
27762776
}
@@ -2779,10 +2779,6 @@ void ByteCodeGenerator::EmitOneFunction(ParseNodeFnc *pnodeFnc)
27792779
}
27802780

27812781
Js::FunctionBody* byteCodeFunction = funcInfo->GetParsedFunctionBody();
2782-
// We've now done a full parse of this function, so we no longer need to remember the extents
2783-
// and attributes of the top-level nested functions. (The above code has run for all of those,
2784-
// so they have pointers to the stub sub-trees they need.)
2785-
byteCodeFunction->SetDeferredStubs(nullptr);
27862782

27872783
try
27882784
{

lib/Runtime/Language/AsmJsModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ namespace Js
554554

555555
if (fncNode->pnodeBody == NULL)
556556
{
557-
if (!PHASE_OFF1(Js::SkipNestedDeferredPhase) && (grfscr & fscrCreateParserState) == fscrCreateParserState)
557+
if (!PHASE_OFF1(Js::SkipNestedDeferredPhase) && (grfscr & fscrCreateParserState) == fscrCreateParserState && deferParseFunction->GetCompileCount() == 0)
558558
{
559559
deferParseFunction->BuildDeferredStubs(fncNode);
560560
}

test/Basics/bug_os16855035.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
// With -useparserstatecache -force:deferparse -force:redeferral -CollectGarbage we should not hit an AV
7+
8+
var glo;
9+
function test()
10+
{
11+
function nested1(param2)
12+
{
13+
function nested2()
14+
{
15+
return param2;
16+
}
17+
18+
escape();
19+
return 'pass';
20+
}
21+
WScript.Echo(nested1());
22+
23+
function blah() { return 'pass' }
24+
function escape() { glo = blah; }
25+
}
26+
27+
28+
test("test3" )
29+
WScript.Echo(glo());
30+
31+
CollectGarbage();
32+
33+
test("test1");

test/Basics/rlexe.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,4 +421,11 @@
421421
<tags>exclude_test,exclude_jshost</tags>
422422
</default>
423423
</test>
424+
<test>
425+
<default>
426+
<files>bug_os16855035.js</files>
427+
<compile-flags>-UseParserStateCache -ParserStateCache -Force:DeferParse -Force:Redeferral -CollectGarbage</compile-flags>
428+
<tags>exclude_test,exclude_jshost</tags>
429+
</default>
430+
</test>
424431
</regress-exe>

0 commit comments

Comments
 (0)