diff --git a/bin/ChakraCore/ChakraCore.def b/bin/ChakraCore/ChakraCore.def index 8883c53695e..903eca2a38b 100644 --- a/bin/ChakraCore/ChakraCore.def +++ b/bin/ChakraCore/ChakraCore.def @@ -46,6 +46,7 @@ JsTTDMoveToTopLevelEvent JsTTDReplayExecution JsTTDDiagWriteLog +JsTTDDiagSetAutoTraceStatus JsInitializeModuleRecord JsParseModuleSource diff --git a/lib/Jsrt/ChakraDebug.h b/lib/Jsrt/ChakraDebug.h index 3ee2c2bbbd9..e7239766d5c 100644 --- a/lib/Jsrt/ChakraDebug.h +++ b/lib/Jsrt/ChakraDebug.h @@ -1014,6 +1014,17 @@ typedef unsigned __int32 uint32_t; _Inout_ JsTTDMoveMode* moveMode, _Out_ int64_t* rootEventTime); + /// + /// TTD API -- may change in future versions: + /// Enable or disable autotrace ability from JsRT. + /// + /// True to enable autotracing false to disable it. + /// The code JsNoError if the operation succeeded, a failure code otherwise. + CHAKRA_API + JsTTDDiagSetAutoTraceStatus( + _In_ bool status + ); + /// /// TTD API -- may change in future versions: /// A way for the debugger to programatically write a trace when it is at a breakpoint. diff --git a/lib/Jsrt/Jsrt.cpp b/lib/Jsrt/Jsrt.cpp index 22c01b59221..2530dd8e335 100644 --- a/lib/Jsrt/Jsrt.cpp +++ b/lib/Jsrt/Jsrt.cpp @@ -4695,6 +4695,27 @@ CHAKRA_API JsTTDReplayExecution(_Inout_ JsTTDMoveMode* moveMode, _Out_ int64_t* #endif } +CHAKRA_API JsTTDDiagSetAutoTraceStatus(_In_ bool status) +{ +#if !ENABLE_TTD + return JsErrorCategoryUsage; +#else + JsrtContext *currentContext = JsrtContext::GetCurrent(); + JsErrorCode cCheck = CheckContext(currentContext, JSRT_MAYBE_TRUE); + TTDAssert(cCheck == JsNoError, "Must have valid context when setting auto trace status."); + + Js::ScriptContext* scriptContext = currentContext->GetScriptContext(); + ThreadContext* threadContext = scriptContext->GetThreadContext(); + + if (threadContext->IsRuntimeInTTDMode()) + { + threadContext->TTDLog->SetAutoTraceEnabled(status); + } + + return JsNoError; +#endif +} + #ifdef _CHAKRACOREBUILD template diff --git a/lib/Runtime/Debug/TTEventLog.cpp b/lib/Runtime/Debug/TTEventLog.cpp index b9bdc1232da..369be47decc 100644 --- a/lib/Runtime/Debug/TTEventLog.cpp +++ b/lib/Runtime/Debug/TTEventLog.cpp @@ -508,6 +508,7 @@ namespace TTD TTD_CREATE_EVENTLIST_VTABLE_ENTRY(ExternalCallTag, None, ExternalCallEventLogEntry, nullptr, NSLogEvents::ExternalCallEventLogEntry_UnloadEventMemory, NSLogEvents::ExternalCallEventLogEntry_Emit, NSLogEvents::ExternalCallEventLogEntry_Parse); TTD_CREATE_EVENTLIST_VTABLE_ENTRY(ExplicitLogWriteTag, None, ExplicitLogWriteEventLogEntry, nullptr, nullptr, NSLogEvents::ExplicitLogWriteEntry_Emit, NSLogEvents::ExplicitLogWriteEntry_Parse); TTD_CREATE_EVENTLIST_VTABLE_ENTRY(TTDInnerLoopLogWriteTag, None, TTDInnerLoopLogWriteEventLogEntry, nullptr, nullptr, NSLogEvents::TTDInnerLoopLogWriteEventLogEntry_Emit, NSLogEvents::TTDInnerLoopLogWriteEventLogEntry_Parse); + TTD_CREATE_EVENTLIST_VTABLE_ENTRY(TTDFetchAutoTraceStatusTag, None, TTDFetchAutoTraceStatusEventLogEntry, nullptr, nullptr, NSLogEvents::TTDFetchAutoTraceStatusEventLogEntry_Emit, NSLogEvents::TTDFetchAutoTraceStatusEventLogEntry_Parse); TTD_CREATE_EVENTLIST_VTABLE_ENTRY(CreateScriptContextActionTag, GlobalAPIWrapper, JsRTCreateScriptContextAction, NSLogEvents::CreateScriptContext_Execute, NSLogEvents::CreateScriptContext_UnloadEventMemory, NSLogEvents::CreateScriptContext_Emit, NSLogEvents::CreateScriptContext_Parse); TTD_CREATE_EVENTLIST_VTABLE_ENTRY_COMMON(SetActiveScriptContextActionTag, GlobalAPIWrapper, JsRTSingleVarArgumentAction, SetActiveScriptContext_Execute); @@ -586,7 +587,7 @@ namespace TTD : m_threadContext(threadContext), m_eventSlabAllocator(TTD_SLAB_BLOCK_ALLOCATION_SIZE_MID), m_miscSlabAllocator(TTD_SLAB_BLOCK_ALLOCATION_SIZE_SMALL), m_eventTimeCtr(0), m_timer(), m_topLevelCallbackEventTime(-1), m_eventListVTable(nullptr), m_eventList(&this->m_eventSlabAllocator), m_currentReplayEventIterator(), - m_modeStack(), m_currentMode(TTDMode::Invalid), + m_modeStack(), m_currentMode(TTDMode::Invalid), m_autoTracesEnabled(true), m_snapExtractor(), m_elapsedExecutionTimeSinceSnapshot(0.0), m_lastInflateSnapshotTime(-1), m_lastInflateMap(nullptr), m_propertyRecordList(&this->m_miscSlabAllocator), m_sourceInfoCount(0), m_loadedTopLevelScripts(&this->m_miscSlabAllocator), m_newFunctionTopLevelScripts(&this->m_miscSlabAllocator), m_evalTopLevelScripts(&this->m_miscSlabAllocator) @@ -879,6 +880,18 @@ namespace TTD } } + void EventLog::RecordTTDFetchAutoTraceStatusEvent(bool status) + { + NSLogEvents::TTDFetchAutoTraceStatusEventLogEntry* atfEvent = this->RecordGetInitializedEvent_DataOnly(); + atfEvent->IsEnabled = status; + } + + bool EventLog::ReplayTTDFetchAutoTraceStatusLogEvent() + { + const NSLogEvents::TTDFetchAutoTraceStatusEventLogEntry* atfEvent = this->ReplayGetReplayEvent_Helper(); + return atfEvent->IsEnabled; + } + void EventLog::RecordDateTimeEvent(double time) { NSLogEvents::DoubleEventLogEntry* dEvent = this->RecordGetInitializedEvent_DataOnly(); @@ -2558,9 +2571,14 @@ namespace TTD return isInnerLoop & isEnabled; } - bool EventLog::SuppressDiagnosticTracesDuringInnerLoop() const + void EventLog::SetAutoTraceEnabled(bool enabled) + { + this->m_autoTracesEnabled = enabled; + } + + bool EventLog::GetAutoTraceEnabled() const { - return (this->m_currentMode & (TTDMode::DebuggerAttachedMode)) == TTDMode::DebuggerAttachedMode; + return this->m_autoTracesEnabled; } void EventLog::EmitLog(const char* emitUri, size_t emitUriLength, NSLogEvents::EventLogEntry* optInnerLoopEvent) diff --git a/lib/Runtime/Debug/TTEventLog.h b/lib/Runtime/Debug/TTEventLog.h index 90dd493f11c..9a320724349 100644 --- a/lib/Runtime/Debug/TTEventLog.h +++ b/lib/Runtime/Debug/TTEventLog.h @@ -226,6 +226,7 @@ namespace TTD //The current mode the system is running in (and a stack of mode push/pops that we use to generate it) TTModeStack m_modeStack; TTDMode m_currentMode; + bool m_autoTracesEnabled; //The snapshot extractor that this log uses SnapshotExtractor m_snapExtractor; @@ -393,6 +394,12 @@ namespace TTD //Replay a event that writes the log to a given uri void ReplayEmitLogEvent(); + //Record that we are accessing the TTDFetchAutoTraceStatus and what the value is + void RecordTTDFetchAutoTraceStatusEvent(bool status); + + //Replay that we are accessing the TTDFetchAutoTraceStatus + bool ReplayTTDFetchAutoTraceStatusLogEvent(); + //Log a time that is fetched during date operations void RecordDateTimeEvent(double time); @@ -605,7 +612,8 @@ namespace TTD void InnerLoopEmitLog(const TTDebuggerSourceLocation& writeLocation, const char* emitUri, size_t emitUriLength); bool CanWriteInnerLoopTrace() const; - bool SuppressDiagnosticTracesDuringInnerLoop() const; + void SetAutoTraceEnabled(bool enabled); + bool GetAutoTraceEnabled() const; void EmitLog(const char* emitUri, size_t emitUriLength, NSLogEvents::EventLogEntry* optInnerLoopEvent = nullptr); void ParseLogInto(TTDataIOInfo& iofp, const char* parseUri, size_t parseUriLength); diff --git a/lib/Runtime/Debug/TTEvents.cpp b/lib/Runtime/Debug/TTEvents.cpp index a43af831d24..068ebe28755 100644 --- a/lib/Runtime/Debug/TTEvents.cpp +++ b/lib/Runtime/Debug/TTEvents.cpp @@ -597,6 +597,20 @@ namespace TTD ilevt->Line = reader->ReadUInt32(NSTokens::Key::line, true); ilevt->Column = reader->ReadUInt32(NSTokens::Key::column, true); } + + void TTDFetchAutoTraceStatusEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext) + { + const TTDFetchAutoTraceStatusEventLogEntry* atfevt = GetInlineEventDataAs(evt); + + writer->WriteLogTag(NSTokens::Key::boolVal, atfevt->IsEnabled, NSTokens::Separator::CommaSeparator); + } + + void TTDFetchAutoTraceStatusEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc) + { + TTDFetchAutoTraceStatusEventLogEntry* atfevt = GetInlineEventDataAs(evt); + + atfevt->IsEnabled = reader->ReadLogTag(NSTokens::Key::boolVal, true); + } } } diff --git a/lib/Runtime/Debug/TTEvents.h b/lib/Runtime/Debug/TTEvents.h index dfed9e8c34b..8621221c27d 100644 --- a/lib/Runtime/Debug/TTEvents.h +++ b/lib/Runtime/Debug/TTEvents.h @@ -98,6 +98,7 @@ namespace TTD ExternalCallTag, ExplicitLogWriteTag, TTDInnerLoopLogWriteTag, + TTDFetchAutoTraceStatusTag, //JsRTActionTag is a marker for where the JsRT actions begin JsRTActionTag, @@ -498,6 +499,15 @@ namespace TTD void TTDInnerLoopLogWriteEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext); void TTDInnerLoopLogWriteEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc); + + //A struct for recording the result of a read of the AutoTraceStatus + struct TTDFetchAutoTraceStatusEventLogEntry + { + bool IsEnabled; + }; + + void TTDFetchAutoTraceStatusEventLogEntry_Emit(const EventLogEntry* evt, FileWriter* writer, ThreadContext* threadContext); + void TTDFetchAutoTraceStatusEventLogEntry_Parse(EventLogEntry* evt, ThreadContext* threadContext, FileReader* reader, UnlinkableSlabAllocator& alloc); } } diff --git a/lib/Runtime/Library/GlobalObject.cpp b/lib/Runtime/Library/GlobalObject.cpp index 8e8a4947104..310067adf4c 100644 --- a/lib/Runtime/Library/GlobalObject.cpp +++ b/lib/Runtime/Library/GlobalObject.cpp @@ -1675,9 +1675,20 @@ namespace Js PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault); ARGUMENTS(args, callInfo); - if(function->GetScriptContext()->ShouldPerformRecordOrReplayAction() && !function->GetScriptContext()->GetThreadContext()->TTDLog->SuppressDiagnosticTracesDuringInnerLoop()) + if (function->GetScriptContext()->ShouldPerformReplayAction()) { - return function->GetScriptContext()->GetLibrary()->GetTrue(); + TTD::EventLog* ttlog = function->GetScriptContext()->GetThreadContext()->TTDLog; + bool isEnabled = ttlog->ReplayTTDFetchAutoTraceStatusLogEvent(); + + return function->GetScriptContext()->GetLibrary()->CreateBoolean(isEnabled); + } + else if (function->GetScriptContext()->ShouldPerformRecordAction()) + { + TTD::EventLog* ttlog = function->GetScriptContext()->GetThreadContext()->TTDLog; + bool isEnabled = ttlog->GetAutoTraceEnabled(); + ttlog->RecordTTDFetchAutoTraceStatusEvent(isEnabled); + + return function->GetScriptContext()->GetLibrary()->CreateBoolean(isEnabled); } else {