Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
deps: update ChakraCore to chakra-core/ChakraCore@3a7377de77
Browse files Browse the repository at this point in the history
[MERGE #5581 @pleath] OS#15992595: On debug reparse, update entry points associated with all parsed functions, not just the ones associated with function objects

Merge pull request #5581 from pleath:15992595

Object may evolve after reparse and use types that are not referenced at reparse time.

Reviewed-By: chakrabot <[email protected]>
  • Loading branch information
pleath authored and kfarnung committed Aug 16, 2018
1 parent dc75228 commit a2ca496
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 66 deletions.
36 changes: 21 additions & 15 deletions deps/chakrashim/core/lib/Runtime/Base/FunctionBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2406,17 +2406,10 @@ namespace Js

if (isDebugOrAsmJsReparse)
{
grfscr &= ~fscrWillDeferFncParse; // Disable deferred parsing if not DeferNested, or doing a debug/asm.js re-parse
}

if (isDebugOrAsmJsReparse)
{
grfscr |= fscrNoAsmJs; // Disable asm.js when debugging or if linking failed
}

if (isDebugOrAsmJsReparse)
{
grfscr &= ~fscrCreateParserState; // Disable parser state cache if we're debugging or reparsing asm.js
// Disable deferred parsing if not DeferNested, or doing a debug/asm.js re-parse
// Disable asm.js when debugging or if linking failed
// Disable parser state cache if we're debugging or reparsing asm.js
grfscr = fscrNoAsmJs | (grfscr & ~(fscrWillDeferFncParse | fscrCreateParserState));
}

BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT
Expand Down Expand Up @@ -3520,6 +3513,23 @@ namespace Js
#endif
}

void FunctionBody::UpdateEntryPointsOnDebugReparse()
{
// Update all function types associated with this function body. Note that we can't rely on updating
// types pointed to by function objects, because the type may evolve to one that is not currently referenced.

ProxyEntryPointInfo * entryPointInfo = this->GetDefaultFunctionEntryPointInfo();
JavascriptMethod newEntryPoint = this->GetDirectEntryPoint(entryPointInfo);
bool isAsmJS = this->GetIsAsmjsMode();

auto updateOneType = [&](ScriptFunctionType* functionType) {
// Note that the ScriptFunctionType method will handle cross-site thunks correctly.
functionType->ChangeEntryPoint(entryPointInfo, newEntryPoint, isAsmJS);
};

this->MapFunctionObjectTypes(updateOneType);
}

void FunctionProxy::Finalize(bool isShutdown)
{
this->CleanupFunctionProxyCounters();
Expand Down Expand Up @@ -5188,10 +5198,6 @@ namespace Js
}

this->SetOriginalEntryPoint(DefaultDeferredParsingThunk);

// Abandon the shared type so a new function will get a new one
this->deferredPrototypeType = nullptr;
this->undeferredFunctionType = nullptr;
this->SetAttributes((FunctionInfo::Attributes) (this->GetAttributes() | FunctionInfo::Attributes::DeferredParse));
}

Expand Down
2 changes: 2 additions & 0 deletions deps/chakrashim/core/lib/Runtime/Base/FunctionBody.h
Original file line number Diff line number Diff line change
Expand Up @@ -3213,6 +3213,8 @@ namespace Js
void ClearEntryPoints();
void ResetEntryPoint();
void CleanupToReparseHelper();
void UpdateEntryPointsOnDebugReparse();

void AddDeferParseAttribute();
void RemoveDeferParseAttribute();
#if DBG
Expand Down
20 changes: 3 additions & 17 deletions deps/chakrashim/core/lib/Runtime/Base/ScriptContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4021,7 +4021,6 @@ namespace Js
// Wrapped function are not allocated with the EnumClass bit
Assert(pFunction->GetFunctionInfo() != &JavascriptExternalFunction::EntryInfo::WrappedFunctionThunk);

JavascriptMethod entryPoint = pFunction->GetEntryPoint();
FunctionInfo * info = pFunction->GetFunctionInfo();
FunctionProxy * proxy = info->GetFunctionProxy();

Expand Down Expand Up @@ -4093,26 +4092,13 @@ namespace Js
}
#endif

ScriptFunction * scriptFunction = ScriptFunction::FromVar(pFunction);

#ifdef ASMJS_PLAT
ScriptFunction * scriptFunction = ScriptFunction::FromVar(pFunction);
scriptContext->TransitionEnvironmentForDebugger(scriptFunction);
#endif

JavascriptMethod newEntryPoint;
if (CrossSite::IsThunk(entryPoint))
{
// Can't change from cross-site to non-cross-site, but still need to update the e.p.info on ScriptFunctionType.
newEntryPoint = entryPoint;
}
else
{
newEntryPoint = pBody->GetDirectEntryPoint(pBody->GetDefaultFunctionEntryPointInfo());
}

scriptFunction->ChangeEntryPoint(pBody->GetDefaultFunctionEntryPointInfo(), newEntryPoint);
}
#endif

#endif // ENABLE_SCRIPT_DEBUGGING

#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
void ScriptContext::RecyclerEnumClassEnumeratorCallback(void *address, size_t size)
Expand Down
3 changes: 3 additions & 0 deletions deps/chakrashim/core/lib/Runtime/Debug/DebugContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,10 @@ namespace Js
{
pFuncBody->ReinitializeExecutionModeAndLimits();
}
pFuncBody->UpdateEntryPointsOnDebugReparse();
});
}

return false;
}

Expand Down Expand Up @@ -330,6 +332,7 @@ namespace Js
{
pFuncBody->ReinitializeExecutionModeAndLimits();
}
pFuncBody->UpdateEntryPointsOnDebugReparse();
});
}

Expand Down
35 changes: 1 addition & 34 deletions deps/chakrashim/core/lib/Runtime/Library/ScriptFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,48 +210,15 @@ using namespace Js;

void ScriptFunction::ChangeEntryPoint(ProxyEntryPointInfo* entryPointInfo, JavascriptMethod entryPoint)
{
Assert(entryPoint != nullptr);
Assert(this->GetTypeId() == TypeIds_Function);
#if ENABLE_NATIVE_CODEGEN
Assert(!IsCrossSiteObject() || entryPoint != (Js::JavascriptMethod)checkCodeGenThunk);
#endif

Assert((entryPointInfo != nullptr && this->GetFunctionProxy() != nullptr));
if (this->GetEntryPoint() == entryPoint && this->GetScriptFunctionType()->GetEntryPointInfo() == entryPointInfo)
{
return;
}

bool isAsmJS = HasFunctionBody() && this->GetFunctionBody()->GetIsAsmjsMode();

// ASMJS:- for asmjs we don't need to update the entry point here as it updates the types entry point
if (!isAsmJS)
{
// We can't go from cross-site to non-cross-site. Update only in the non-cross site case
if (!CrossSite::IsThunk(this->GetEntryPoint()))
{
this->SetEntryPoint(entryPoint);
}
}
// instead update the address in the function entrypoint info
else
{
entryPointInfo->jsMethod = entryPoint;
}

ProxyEntryPointInfo* oldEntryPointInfo = this->GetScriptFunctionType()->GetEntryPointInfo();
if (oldEntryPointInfo
&& oldEntryPointInfo != entryPointInfo
&& oldEntryPointInfo->SupportsExpiration())
{
// The old entry point could be executing so we need root it to make sure
// it isn't prematurely collected. The rooting is done by queuing it up on the threadContext
ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread();

threadContext->QueueFreeOldEntryPointInfoIfInScript((FunctionEntryPointInfo*)oldEntryPointInfo);
}

this->GetScriptFunctionType()->SetEntryPointInfo(entryPointInfo);
this->GetScriptFunctionType()->ChangeEntryPoint(entryPointInfo, entryPoint, isAsmJS);
}

FunctionProxy * ScriptFunction::GetFunctionProxy() const
Expand Down
39 changes: 39 additions & 0 deletions deps/chakrashim/core/lib/Runtime/Types/ScriptFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,43 @@ namespace Js
library->ScriptFunctionTypeHandler(!proxy->IsConstructor(), proxy->GetIsAnonymousFunction()),
isShared, isShared);
}

void ScriptFunctionType::ChangeEntryPoint(ProxyEntryPointInfo * entryPointInfo, JavascriptMethod entryPoint, bool isAsmJS)
{
Assert(entryPoint != nullptr);
Assert(entryPointInfo != nullptr);
if (this->GetEntryPoint() == entryPoint && this->GetEntryPointInfo() == entryPointInfo)
{
return;
}

// ASMJS:- for asmjs we don't need to update the entry point here as it updates the types entry point
if (!isAsmJS)
{
// We can't go from cross-site to non-cross-site. Update only in the non-cross site case
if (!CrossSite::IsThunk(this->GetEntryPoint()))
{
this->SetEntryPoint(entryPoint);
}
}
// instead update the address in the function entrypoint info
else
{
entryPointInfo->jsMethod = entryPoint;
}

ProxyEntryPointInfo* oldEntryPointInfo = this->GetEntryPointInfo();
if (oldEntryPointInfo
&& oldEntryPointInfo != entryPointInfo
&& oldEntryPointInfo->SupportsExpiration())
{
// The old entry point could be executing so we need root it to make sure
// it isn't prematurely collected. The rooting is done by queuing it up on the threadContext
ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread();

threadContext->QueueFreeOldEntryPointInfoIfInScript((FunctionEntryPointInfo*)oldEntryPointInfo);
}

this->SetEntryPointInfo(entryPointInfo);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Js
static DWORD GetEntryPointInfoOffset() { return offsetof(ScriptFunctionType, entryPointInfo); }
ProxyEntryPointInfo * GetEntryPointInfo() const { return entryPointInfo; }
void SetEntryPointInfo(ProxyEntryPointInfo * entryPointInfo) { this->entryPointInfo = entryPointInfo; }
void ChangeEntryPoint(ProxyEntryPointInfo * entryPointInfo, JavascriptMethod entryPoint, bool isAsmJS);
private:
ScriptFunctionType(ScriptFunctionType * type);
ScriptFunctionType(ScriptContext* scriptContext, RecyclableObject* prototype,
Expand Down

0 comments on commit a2ca496

Please sign in to comment.