|
|
@@ -3071,6 +3071,34 @@ namespace Js
|
|
|
}
|
|
|
|
|
|
HRESULT hr = S_OK;
|
|
|
+
|
|
|
+#ifndef _WIN32
|
|
|
+ BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
|
|
|
+ {
|
|
|
+ // xplat eh_frame handling is a bit different than Windows
|
|
|
+ // RecreateNativeCodeGenerator call below will be cleaning up
|
|
|
+ // XDataAllocation and we won't be able to __DEREGISTER_FRAME
|
|
|
+
|
|
|
+ // xplat-todo: make eh_frame handling better
|
|
|
+ this->sourceList->Map([=](uint i, RecyclerWeakReference<Js::Utf8SourceInfo>* sourceInfoWeakRef) {
|
|
|
+ Js::Utf8SourceInfo* sourceInfo = sourceInfoWeakRef->Get();
|
|
|
+
|
|
|
+ if (sourceInfo != nullptr)
|
|
|
+ {
|
|
|
+ sourceInfo->MapFunction([](Js::FunctionBody* functionBody) {
|
|
|
+ functionBody->ResetEntryPoint();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ END_TRANSLATE_OOM_TO_HRESULT(hr);
|
|
|
+
|
|
|
+ if (FAILED(hr))
|
|
|
+ {
|
|
|
+ return hr;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
if (!CONFIG_FLAG(ForceDiagnosticsMode))
|
|
|
{
|
|
|
#if ENABLE_NATIVE_CODEGEN
|
|
|
@@ -3113,12 +3141,14 @@ namespace Js
|
|
|
functionBody->SetEntryToDeferParseForDebugger();
|
|
|
});
|
|
|
}
|
|
|
+#ifdef _WIN32
|
|
|
else
|
|
|
{
|
|
|
sourceInfo->MapFunction([](Js::FunctionBody* functionBody) {
|
|
|
functionBody->ResetEntryPoint();
|
|
|
});
|
|
|
}
|
|
|
+#endif
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
@@ -3134,7 +3164,6 @@ namespace Js
|
|
|
this->RegisterDebugThunk();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
#if ENABLE_PROFILE_INFO
|
|
|
#if DBG_DUMP || defined(DYNAMIC_PROFILE_STORAGE) || defined(RUNTIME_DATA_COLLECTION)
|
|
|
// Reset the dynamic profile list
|
|
|
@@ -3147,12 +3176,12 @@ namespace Js
|
|
|
return hr;
|
|
|
}
|
|
|
|
|
|
+#if defined(ENABLE_SCRIPT_DEBUGGING) || defined(ENABLE_SCRIPT_PROFILING)
|
|
|
// We use ProfileThunk under debugger.
|
|
|
void ScriptContext::RegisterDebugThunk(bool calledDuringAttach /*= true*/)
|
|
|
{
|
|
|
if (this->IsExceptionWrapperForBuiltInsEnabled())
|
|
|
{
|
|
|
-#ifdef ENABLE_SCRIPT_PROFILING
|
|
|
this->CurrentThunk = ProfileEntryThunk;
|
|
|
this->CurrentCrossSiteThunk = CrossSite::ProfileThunk;
|
|
|
#if ENABLE_NATIVE_CODEGEN
|
|
|
@@ -3163,16 +3192,14 @@ namespace Js
|
|
|
// are created with entry point set to the ProfileThunk.
|
|
|
this->javascriptLibrary->SetProfileMode(true);
|
|
|
this->javascriptLibrary->SetDispatchProfile(true, DispatchProfileInvoke);
|
|
|
+
|
|
|
+#ifdef ENABLE_SCRIPT_PROFILING
|
|
|
if (!calledDuringAttach)
|
|
|
{
|
|
|
-#ifdef ENABLE_SCRIPT_PROFILING
|
|
|
m_fTraceDomCall = TRUE; // This flag is always needed in DebugMode to wrap external functions with DebugProfileThunk
|
|
|
-#endif
|
|
|
// Update the function objects currently present in there.
|
|
|
this->SetFunctionInRecyclerToProfileMode(true/*enumerateNonUserFunctionsOnly*/);
|
|
|
}
|
|
|
-#else
|
|
|
- AssertMsg(false, "Profiling needs to be enabled to call RegisterDebugThunk");
|
|
|
#endif
|
|
|
}
|
|
|
}
|
|
|
@@ -3194,6 +3221,7 @@ namespace Js
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+#endif // defined(ENABLE_SCRIPT_DEBUGGING) || defined(ENABLE_SCRIPT_PROFILING)
|
|
|
|
|
|
#ifdef ENABLE_SCRIPT_PROFILING
|
|
|
HRESULT ScriptContext::RegisterBuiltinFunctions(RegisterExternalLibraryType RegisterExternalLibrary)
|
|
|
@@ -3389,7 +3417,7 @@ namespace Js
|
|
|
scriptFunction->ChangeEntryPoint(pBody->GetDefaultFunctionEntryPointInfo(), newEntryPoint);
|
|
|
}
|
|
|
|
|
|
-#ifdef ENABLE_SCRIPT_PROFILING
|
|
|
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
|
|
|
void ScriptContext::RecyclerEnumClassEnumeratorCallback(void *address, size_t size)
|
|
|
{
|
|
|
// TODO: we are assuming its function because for now we are enumerating only on functions
|
|
|
@@ -3430,6 +3458,7 @@ namespace Js
|
|
|
char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
|
|
|
#endif
|
|
|
|
|
|
+#if defined(ENABLE_SCRIPT_PROFILING)
|
|
|
OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("ScriptContext::RecyclerEnumClassEnumeratorCallback\n"));
|
|
|
OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("\tFunctionProxy : 0x%08X, FunctionNumber : %s, DeferredParseAttributes : %d, EntryPoint : 0x%08X"),
|
|
|
(DWORD_PTR)proxy, proxy->GetDebugNumberSet(debugStringBuffer), proxy->GetAttributes(), (DWORD_PTR)entryPoint);
|
|
|
@@ -3438,6 +3467,7 @@ namespace Js
|
|
|
IsTrueOrFalse(IsIntermediateCodeGenThunk(entryPoint)), IsTrueOrFalse(scriptContext->IsNativeAddress(entryPoint)));
|
|
|
#endif
|
|
|
OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("\n"));
|
|
|
+#endif
|
|
|
|
|
|
#if ENABLE_NATIVE_CODEGEN
|
|
|
if (!IsIntermediateCodeGenThunk(entryPoint) && entryPoint != DynamicProfileInfo::EnsureDynamicProfileInfoThunk)
|
|
|
@@ -3448,7 +3478,7 @@ namespace Js
|
|
|
ScriptFunction * scriptFunction = ScriptFunction::FromVar(pFunction);
|
|
|
scriptFunction->ChangeEntryPoint(proxy->GetDefaultEntryPointInfo(), Js::ScriptContext::GetProfileModeThunk(entryPoint));
|
|
|
|
|
|
-#if ENABLE_NATIVE_CODEGEN
|
|
|
+#if ENABLE_NATIVE_CODEGEN && defined(ENABLE_SCRIPT_PROFILING)
|
|
|
OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("\tUpdated entrypoint : 0x%08X (isNative : %s)\n"), (DWORD_PTR)pFunction->GetEntryPoint(), IsTrueOrFalse(scriptContext->IsNativeAddress(entryPoint)));
|
|
|
#endif
|
|
|
}
|
|
|
@@ -3489,9 +3519,9 @@ namespace Js
|
|
|
|
|
|
JavascriptMethod ScriptContext::GetProfileModeThunk(JavascriptMethod entryPoint)
|
|
|
{
|
|
|
-#if ENABLE_NATIVE_CODEGEN
|
|
|
+ #if ENABLE_NATIVE_CODEGEN
|
|
|
Assert(!IsIntermediateCodeGenThunk(entryPoint));
|
|
|
-#endif
|
|
|
+ #endif
|
|
|
if (entryPoint == DefaultDeferredParsingThunk || entryPoint == ProfileDeferredParsingThunk)
|
|
|
{
|
|
|
return ProfileDeferredParsingThunk;
|
|
|
@@ -3508,7 +3538,7 @@ namespace Js
|
|
|
}
|
|
|
return ProfileEntryThunk;
|
|
|
}
|
|
|
-#endif // ENABLE_SCRIPT_PROFILING
|
|
|
+#endif // defined(ENABLE_SCRIPT_PROFILING) || defiend(ENABLE_SCRIPT_DEBUGGING)
|
|
|
|
|
|
#if _M_IX86
|
|
|
__declspec(naked)
|
|
|
@@ -3717,12 +3747,7 @@ namespace Js
|
|
|
Assert(!AsmJsScriptFunction::IsWasmScriptFunction(callable));
|
|
|
JavascriptFunction* function = JavascriptFunction::FromVar(callable);
|
|
|
ScriptContext* scriptContext = function->GetScriptContext();
|
|
|
- PROFILER_TOKEN scriptId = -1;
|
|
|
- PROFILER_TOKEN functionId = -1;
|
|
|
bool functionEnterEventSent = false;
|
|
|
-
|
|
|
- const bool isProfilingUserCode = scriptContext->GetThreadContext()->IsProfilingUserCode();
|
|
|
- const bool isUserCode = !function->IsLibraryCode();
|
|
|
char16 *pwszExtractedFunctionName = NULL;
|
|
|
const char16 *pwszFunctionName = NULL;
|
|
|
HRESULT hrOfEnterEvent = S_OK;
|
|
|
@@ -3730,6 +3755,12 @@ namespace Js
|
|
|
// We can come here when profiling is not on
|
|
|
// e.g. User starts profiling, we update all thinks and then stop profiling - we don't update thunk
|
|
|
// So we still get this call
|
|
|
+#if defined(ENABLE_SCRIPT_PROFILING)
|
|
|
+ PROFILER_TOKEN scriptId = -1;
|
|
|
+ PROFILER_TOKEN functionId = -1;
|
|
|
+ const bool isProfilingUserCode = scriptContext->GetThreadContext()->IsProfilingUserCode();
|
|
|
+ const bool isUserCode = !function->IsLibraryCode();
|
|
|
+
|
|
|
const bool fProfile = (isUserCode || isProfilingUserCode) // Only report user code or entry library code
|
|
|
&& scriptContext->GetProfileInfo(function, scriptId, functionId);
|
|
|
|
|
|
@@ -3754,7 +3785,7 @@ namespace Js
|
|
|
}
|
|
|
AssertMsg(pBody == NULL || pBody->GetProfileSession() == pBody->GetScriptContext()->GetProfileSession(), "Function info wasn't reported for this profile session");
|
|
|
}
|
|
|
-#endif
|
|
|
+#endif // DEBUG
|
|
|
|
|
|
if (functionId == -1)
|
|
|
{
|
|
|
@@ -3803,11 +3834,12 @@ namespace Js
|
|
|
|
|
|
scriptContext->GetThreadContext()->SetIsProfilingUserCode(isUserCode); // Update IsProfilingUserCode state
|
|
|
}
|
|
|
+#endif // ENABLE_SCRIPT_PROFILING
|
|
|
|
|
|
Var aReturn = NULL;
|
|
|
JavascriptMethod origEntryPoint = function->GetFunctionInfo()->GetOriginalEntryPoint();
|
|
|
|
|
|
- __try
|
|
|
+ __TRY_FINALLY_BEGIN // SEH is not guaranteed, see the implementation
|
|
|
{
|
|
|
Assert(!function->IsScriptFunction() || function->GetFunctionProxy());
|
|
|
|
|
|
@@ -3848,14 +3880,15 @@ namespace Js
|
|
|
{
|
|
|
threadContext->GetDebugManager()->GetDebuggingFlags()->SetIsBuiltInWrapperPresent(false);
|
|
|
}
|
|
|
- __try
|
|
|
+ __TRY_FINALLY_BEGIN // SEH is not guaranteed, see the implementation
|
|
|
{
|
|
|
aReturn = JavascriptFunction::CallFunction<true>(function, origEntryPoint, args);
|
|
|
}
|
|
|
- __finally
|
|
|
+ __FINALLY
|
|
|
{
|
|
|
threadContext->GetDebugManager()->GetDebuggingFlags()->SetIsBuiltInWrapperPresent(isOrigWrapperPresent);
|
|
|
}
|
|
|
+ __TRY_FINALLY_END
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -3866,8 +3899,9 @@ namespace Js
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- __finally
|
|
|
+ __FINALLY
|
|
|
{
|
|
|
+#if defined(ENABLE_SCRIPT_PROFILING)
|
|
|
if (fProfile)
|
|
|
{
|
|
|
if (hrOfEnterEvent != ACTIVPROF_E_PROFILER_ABSENT)
|
|
|
@@ -3892,12 +3926,14 @@ namespace Js
|
|
|
|
|
|
scriptContext->GetThreadContext()->SetIsProfilingUserCode(isProfilingUserCode); // Restore IsProfilingUserCode state
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
if (scriptContext->IsScriptContextInDebugMode())
|
|
|
{
|
|
|
scriptContext->GetDebugContext()->GetProbeContainer()->EndRecordingCall(aReturn, function);
|
|
|
}
|
|
|
}
|
|
|
+ __TRY_FINALLY_END
|
|
|
|
|
|
return aReturn;
|
|
|
#else
|
|
|
@@ -3905,7 +3941,7 @@ namespace Js
|
|
|
#endif // defined(ENABLE_SCRIPT_DEBUGGING) || defined(ENABLE_SCRIPT_PROFILING)
|
|
|
}
|
|
|
|
|
|
-#ifdef ENABLE_SCRIPT_PROFILING
|
|
|
+#if defined(ENABLE_SCRIPT_DEBUGGING) || defined(ENABLE_SCRIPT_PROFILING)
|
|
|
// Part of ProfileModeThunk which is called in debug mode (debug or debug & profile).
|
|
|
Var ScriptContext::ProfileModeThunk_DebugModeWrapper(JavascriptFunction* function, ScriptContext* scriptContext, JavascriptMethod entryPoint, Arguments& args)
|
|
|
{
|
|
|
@@ -3917,7 +3953,9 @@ namespace Js
|
|
|
|
|
|
return aReturn;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
+#ifdef ENABLE_SCRIPT_PROFILING
|
|
|
HRESULT ScriptContext::OnScriptCompiled(PROFILER_TOKEN scriptId, PROFILER_SCRIPT_TYPE type, IUnknown *pIDebugDocumentContext)
|
|
|
{
|
|
|
// TODO : can we do a delay send of these events or can we send an event before doing all this stuff that could calculate overhead?
|
|
|
@@ -4025,7 +4063,7 @@ namespace Js
|
|
|
|
|
|
HRESULT ScriptContext::RegisterLibraryFunction(const char16 *pwszObjectName, const char16 *pwszFunctionName, Js::PropertyId functionPropertyId, JavascriptMethod entryPoint)
|
|
|
{
|
|
|
-#ifdef ENABLE_SCRIPT_PROFILING
|
|
|
+#if defined(ENABLE_SCRIPT_PROFILING)
|
|
|
#if DEBUG
|
|
|
const char16 *pwszObjectNameFromProperty = const_cast<char16 *>(GetPropertyName(functionPropertyId)->GetBuffer());
|
|
|
if (GetPropertyName(functionPropertyId)->IsSymbol())
|