Diff
Modified: trunk/Source/_javascript_Core/API/JSProfilerPrivate.cpp (174318 => 174319)
--- trunk/Source/_javascript_Core/API/JSProfilerPrivate.cpp 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/_javascript_Core/API/JSProfilerPrivate.cpp 2014-10-04 19:18:38 UTC (rev 174319)
@@ -34,7 +34,7 @@
void JSStartProfiling(JSContextRef ctx, JSStringRef title)
{
- LegacyProfiler::profiler()->startProfiling(toJS(ctx), title->string());
+ LegacyProfiler::profiler()->startProfiling(toJS(ctx), title->string(), Stopwatch::create());
}
void JSEndProfiling(JSContextRef ctx, JSStringRef title)
Modified: trunk/Source/_javascript_Core/ChangeLog (174318 => 174319)
--- trunk/Source/_javascript_Core/ChangeLog 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-10-04 19:18:38 UTC (rev 174319)
@@ -1,3 +1,36 @@
+2014-10-04 Brian J. Burg <[email protected]>
+
+ Web Inspector: timelines should not count time elapsed while paused in the debugger
+ https://bugs.webkit.org/show_bug.cgi?id=136351
+
+ Reviewed by Timothy Hatcher.
+
+ Now that we have a stopwatch to provide pause-aware timing data, we can remove the
+ profiler's handling of debugger pause/continue callbacks. The timeline agent accounts
+ for debugger pauses by pausing and resuming the stopwatch.
+
+ * API/JSProfilerPrivate.cpp:
+ (JSStartProfiling): Use a fresh stopwatch when profiling from the JSC API.
+ * inspector/ScriptDebugServer.cpp:
+ (Inspector::ScriptDebugServer::handlePause):
+ * profiler/LegacyProfiler.cpp:
+ (JSC::LegacyProfiler::profiler): Use nullptr.
+ (JSC::LegacyProfiler::startProfiling): Hand off a stopwatch to the profile generator.
+ (JSC::LegacyProfiler::stopProfiling): Use nullptr.
+ (JSC::LegacyProfiler::didPause): Deleted.
+ (JSC::LegacyProfiler::didContinue): Deleted.
+ * profiler/LegacyProfiler.h:
+ * profiler/ProfileGenerator.cpp: Remove debugger pause/continue callbacks and the
+ timestamp member that was used to track time elapsed by the debugger. Just use the
+ stopwatch's elapsed times to generate start/elapsed times for function calls.
+ (JSC::ProfileGenerator::create):
+ (JSC::ProfileGenerator::ProfileGenerator):
+ (JSC::ProfileGenerator::beginCallEntry):
+ (JSC::ProfileGenerator::endCallEntry):
+ (JSC::ProfileGenerator::didPause): Deleted.
+ (JSC::ProfileGenerator::didContinue): Deleted.
+ * profiler/ProfileGenerator.h:
+
2014-10-04 Filip Pizlo <[email protected]>
FTL should sink PutLocals
Modified: trunk/Source/_javascript_Core/inspector/ScriptDebugServer.cpp (174318 => 174319)
--- trunk/Source/_javascript_Core/inspector/ScriptDebugServer.cpp 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/_javascript_Core/inspector/ScriptDebugServer.cpp 2014-10-04 19:18:38 UTC (rev 174319)
@@ -38,7 +38,6 @@
#include "JSJavaScriptCallFrame.h"
#include "JSLock.h"
#include "_javascript_CallFrame.h"
-#include "LegacyProfiler.h"
#include "ScriptValue.h"
#include "SourceProvider.h"
#include <wtf/NeverDestroyed.h>
@@ -307,14 +306,12 @@
void ScriptDebugServer::handlePause(Debugger::ReasonForPause, JSGlobalObject* vmEntryGlobalObject)
{
dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidPause);
- LegacyProfiler::profiler()->didPause(currentDebuggerCallFrame());
didPause(vmEntryGlobalObject);
m_doneProcessingDebuggerEvents = false;
runEventLoopWhilePaused();
didContinue(vmEntryGlobalObject);
- LegacyProfiler::profiler()->didContinue(currentDebuggerCallFrame());
dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidContinue);
}
Modified: trunk/Source/_javascript_Core/profiler/LegacyProfiler.cpp (174318 => 174319)
--- trunk/Source/_javascript_Core/profiler/LegacyProfiler.cpp 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/_javascript_Core/profiler/LegacyProfiler.cpp 2014-10-04 19:18:38 UTC (rev 174319)
@@ -32,7 +32,6 @@
#include "CallFrame.h"
#include "CodeBlock.h"
#include "CommonIdentifiers.h"
-#include "DebuggerCallFrame.h"
#include "InternalFunction.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
@@ -50,16 +49,16 @@
static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber);
-LegacyProfiler* LegacyProfiler::s_sharedLegacyProfiler = 0;
+LegacyProfiler* LegacyProfiler::s_sharedLegacyProfiler = nullptr;
LegacyProfiler* LegacyProfiler::profiler()
{
if (!s_sharedLegacyProfiler)
s_sharedLegacyProfiler = new LegacyProfiler();
return s_sharedLegacyProfiler;
-}
+}
-void LegacyProfiler::startProfiling(ExecState* exec, const String& title)
+void LegacyProfiler::startProfiling(ExecState* exec, const String& title, PassRefPtr<Stopwatch> stopwatch)
{
if (!exec)
return;
@@ -75,14 +74,14 @@
}
exec->vm().setEnabledProfiler(this);
- RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID);
+ RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID, stopwatch);
m_currentProfiles.append(profileGenerator);
}
PassRefPtr<Profile> LegacyProfiler::stopProfiling(ExecState* exec, const String& title)
{
if (!exec)
- return 0;
+ return nullptr;
JSGlobalObject* origin = exec->lexicalGlobalObject();
for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
@@ -94,12 +93,12 @@
m_currentProfiles.remove(i);
if (!m_currentProfiles.size())
exec->vm().setEnabledProfiler(nullptr);
-
+
return returnProfile;
}
}
- return 0;
+ return nullptr;
}
void LegacyProfiler::stopProfiling(JSGlobalObject* origin)
@@ -184,28 +183,6 @@
callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::exceptionUnwind, std::placeholders::_1, handlerCallFrame, callIdentifier), m_currentProfiles, handlerCallFrame->lexicalGlobalObject()->profileGroup());
}
-void LegacyProfiler::didPause(PassRefPtr<DebuggerCallFrame> prpCallFrame)
-{
- if (m_currentProfiles.isEmpty())
- return;
-
- RefPtr<DebuggerCallFrame> callFrame = prpCallFrame;
- CallIdentifier callIdentifier = createCallIdentifier(callFrame->exec(), JSValue(), StringImpl::empty(), 0, 0);
-
- callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::didPause, std::placeholders::_1, callFrame, callIdentifier), m_currentProfiles, callFrame->vmEntryGlobalObject()->profileGroup());
-}
-
-void LegacyProfiler::didContinue(PassRefPtr<DebuggerCallFrame> prpCallFrame)
-{
- if (m_currentProfiles.isEmpty())
- return;
-
- RefPtr<DebuggerCallFrame> callFrame = prpCallFrame;
- CallIdentifier callIdentifier = createCallIdentifier(callFrame->exec(), JSValue(), StringImpl::empty(), 0, 0);
-
- callFunctionForProfilesWithGroup(std::bind(&ProfileGenerator::didContinue, std::placeholders::_1, callFrame, callIdentifier), m_currentProfiles, callFrame->vmEntryGlobalObject()->profileGroup());
-}
-
CallIdentifier LegacyProfiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const String& defaultSourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber)
{
if (!functionValue)
Modified: trunk/Source/_javascript_Core/profiler/LegacyProfiler.h (174318 => 174319)
--- trunk/Source/_javascript_Core/profiler/LegacyProfiler.h 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/_javascript_Core/profiler/LegacyProfiler.h 2014-10-04 19:18:38 UTC (rev 174319)
@@ -32,13 +32,12 @@
#include "Profile.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
+#include <wtf/Stopwatch.h>
#include <wtf/Vector.h>
namespace JSC {
-class DebuggerCallFrame;
class ExecState;
-class VM;
class JSGlobalObject;
class JSObject;
class JSValue;
@@ -48,10 +47,10 @@
class LegacyProfiler {
WTF_MAKE_FAST_ALLOCATED;
public:
- JS_EXPORT_PRIVATE static LegacyProfiler* profiler();
+ JS_EXPORT_PRIVATE static LegacyProfiler* profiler();
static CallIdentifier createCallIdentifier(ExecState*, JSValue, const WTF::String& sourceURL, unsigned defaultLineNumber, unsigned defaultColumnNumber);
- JS_EXPORT_PRIVATE void startProfiling(ExecState*, const WTF::String& title);
+ JS_EXPORT_PRIVATE void startProfiling(ExecState*, const WTF::String& title, PassRefPtr<Stopwatch>);
JS_EXPORT_PRIVATE PassRefPtr<Profile> stopProfiling(ExecState*, const WTF::String& title);
void stopProfiling(JSGlobalObject*);
@@ -66,9 +65,6 @@
void exceptionUnwind(ExecState* handlerCallFrame);
- void didPause(PassRefPtr<DebuggerCallFrame>);
- void didContinue(PassRefPtr<DebuggerCallFrame>);
-
const Vector<RefPtr<ProfileGenerator>>& currentProfiles() { return m_currentProfiles; };
private:
Modified: trunk/Source/_javascript_Core/profiler/ProfileGenerator.cpp (174318 => 174319)
--- trunk/Source/_javascript_Core/profiler/ProfileGenerator.cpp 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/_javascript_Core/profiler/ProfileGenerator.cpp 2014-10-04 19:18:38 UTC (rev 174319)
@@ -28,7 +28,6 @@
#include "CallFrame.h"
#include "CodeBlock.h"
-#include "Debugger.h"
#include "JSGlobalObject.h"
#include "JSStringRef.h"
#include "JSFunction.h"
@@ -40,21 +39,18 @@
namespace JSC {
-PassRefPtr<ProfileGenerator> ProfileGenerator::create(ExecState* exec, const String& title, unsigned uid)
+PassRefPtr<ProfileGenerator> ProfileGenerator::create(ExecState* exec, const String& title, unsigned uid, PassRefPtr<Stopwatch> stopwatch)
{
- return adoptRef(new ProfileGenerator(exec, title, uid));
+ return adoptRef(new ProfileGenerator(exec, title, uid, stopwatch));
}
-ProfileGenerator::ProfileGenerator(ExecState* exec, const String& title, unsigned uid)
+ProfileGenerator::ProfileGenerator(ExecState* exec, const String& title, unsigned uid, PassRefPtr<Stopwatch> stopwatch)
: m_origin(exec ? exec->lexicalGlobalObject() : nullptr)
, m_profileGroup(exec ? exec->lexicalGlobalObject()->profileGroup() : 0)
- , m_debuggerPausedTimestamp(NAN)
+ , m_stopwatch(stopwatch)
, m_foundConsoleStartParent(false)
, m_suspended(false)
{
- if (Debugger* debugger = exec->lexicalGlobalObject()->debugger())
- m_debuggerPausedTimestamp = debugger->isPaused() ? currentTime() : NAN;
-
m_profile = Profile::create(title, uid);
m_currentNode = m_rootNode = m_profile->rootNode();
if (exec)
@@ -118,13 +114,8 @@
ASSERT_ARG(node, node);
if (isnan(startTime))
- startTime = currentTime();
+ startTime = m_stopwatch->elapsedTime();
- // If the debugger is paused when beginning, then don't set the start time. It
- // will be fixed up when the debugger unpauses or the call entry ends.
- if (!isnan(m_debuggerPausedTimestamp))
- startTime = NAN;
-
node->appendCall(ProfileNode::Call(startTime));
}
@@ -133,22 +124,8 @@
ASSERT_ARG(node, node);
ProfileNode::Call& last = node->lastCall();
-
- // If the debugger is paused, ignore the interval that ends now.
- if (!isnan(m_debuggerPausedTimestamp) && !isnan(last.elapsedTime()))
- return;
-
- // If paused and no time was accrued then the debugger was never unpaused. The call will
- // have no time accrued and appear to have started when the debugger was paused.
- if (!isnan(m_debuggerPausedTimestamp)) {
- last.setStartTime(m_debuggerPausedTimestamp);
- last.setElapsedTime(0.0);
- return;
- }
-
- // Otherwise, add the interval ending now to elapsed time.
double previousElapsedTime = isnan(last.elapsedTime()) ? 0.0 : last.elapsedTime();
- double newlyElapsedTime = currentTime() - last.startTime();
+ double newlyElapsedTime = m_stopwatch->elapsedTime() - last.startTime();
last.setElapsedTime(previousElapsedTime + newlyElapsedTime);
}
@@ -223,33 +200,6 @@
}
}
-void ProfileGenerator::didPause(PassRefPtr<DebuggerCallFrame>, const CallIdentifier&)
-{
- ASSERT(isnan(m_debuggerPausedTimestamp));
-
- m_debuggerPausedTimestamp = currentTime();
-
- for (ProfileNode* node = m_currentNode.get(); node != m_profile->rootNode(); node = node->parent()) {
- ProfileNode::Call& last = node->lastCall();
- ASSERT(!isnan(last.startTime()));
-
- double previousElapsedTime = isnan(last.elapsedTime()) ? 0.0 : last.elapsedTime();
- double additionalElapsedTime = m_debuggerPausedTimestamp - last.startTime();
- last.setStartTime(NAN);
- last.setElapsedTime(previousElapsedTime + additionalElapsedTime);
- }
-}
-
-void ProfileGenerator::didContinue(PassRefPtr<DebuggerCallFrame>, const CallIdentifier&)
-{
- ASSERT(!isnan(m_debuggerPausedTimestamp));
-
- for (ProfileNode* node = m_currentNode.get(); node != m_profile->rootNode(); node = node->parent())
- node->lastCall().setStartTime(m_debuggerPausedTimestamp);
-
- m_debuggerPausedTimestamp = NAN;
-}
-
void ProfileGenerator::stopProfiling()
{
for (ProfileNode* node = m_currentNode.get(); node != m_profile->rootNode(); node = node->parent())
Modified: trunk/Source/_javascript_Core/profiler/ProfileGenerator.h (174318 => 174319)
--- trunk/Source/_javascript_Core/profiler/ProfileGenerator.h 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/_javascript_Core/profiler/ProfileGenerator.h 2014-10-04 19:18:38 UTC (rev 174319)
@@ -29,6 +29,7 @@
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
+#include <wtf/Stopwatch.h>
#include <wtf/text/WTFString.h>
namespace JSC {
@@ -42,7 +43,7 @@
class ProfileGenerator : public RefCounted<ProfileGenerator> {
public:
- static PassRefPtr<ProfileGenerator> create(ExecState*, const WTF::String& title, unsigned uid);
+ static PassRefPtr<ProfileGenerator> create(ExecState*, const WTF::String& title, unsigned uid, PassRefPtr<Stopwatch>);
// Members
const WTF::String& title() const;
@@ -54,15 +55,12 @@
void didExecute(ExecState* callerCallFrame, const CallIdentifier&);
void exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&);
- void didPause(PassRefPtr<DebuggerCallFrame>, const CallIdentifier&);
- void didContinue(PassRefPtr<DebuggerCallFrame>, const CallIdentifier&);
-
void setIsSuspended(bool suspended) { ASSERT(m_suspended != suspended); m_suspended = suspended; }
void stopProfiling();
private:
- ProfileGenerator(ExecState*, const WTF::String& title, unsigned uid);
+ ProfileGenerator(ExecState*, const WTF::String& title, unsigned uid, PassRefPtr<Stopwatch>);
void addParentForConsoleStart(ExecState*);
void removeProfileStart();
@@ -74,8 +72,7 @@
RefPtr<Profile> m_profile;
JSGlobalObject* m_origin;
unsigned m_profileGroup;
- // Timestamp is set to NAN when the debugger is not currently paused.
- double m_debuggerPausedTimestamp;
+ RefPtr<Stopwatch> m_stopwatch;
RefPtr<ProfileNode> m_rootNode;
RefPtr<ProfileNode> m_currentNode;
bool m_foundConsoleStartParent;
Modified: trunk/Source/WTF/ChangeLog (174318 => 174319)
--- trunk/Source/WTF/ChangeLog 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WTF/ChangeLog 2014-10-04 19:18:38 UTC (rev 174319)
@@ -1,3 +1,19 @@
+2014-10-04 Brian J. Burg <[email protected]>
+
+ Web Inspector: timelines should not count time elapsed while paused in the debugger
+ https://bugs.webkit.org/show_bug.cgi?id=136351
+
+ Reviewed by Timothy Hatcher.
+
+ * WTF.vcxproj/WTF.vcxproj:
+ * WTF.vcxproj/WTF.vcxproj.filters:
+ * WTF.xcodeproj/project.pbxproj:
+ * wtf/CMakeLists.txt:
+ * wtf/Stopwatch.h: Added. This implements a refcounted monotonic stopwatch.
+ (WTF::Stopwatch::reset):
+ (WTF::Stopwatch::start):
+ (WTF::Stopwatch::stop):
+
2014-10-04 Filip Pizlo <[email protected]>
FTL should sink PutLocals
Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj (174318 => 174319)
--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj 2014-10-04 19:18:38 UTC (rev 174319)
@@ -269,6 +269,7 @@
<ClInclude Include="..\wtf\StackBounds.h" />
<ClInclude Include="..\wtf\StaticConstructors.h" />
<ClInclude Include="..\wtf\StdLibExtras.h" />
+ <ClInclude Include="..\wtf\Stopwatch.h" />
<ClInclude Include="..\wtf\StringExtras.h" />
<ClInclude Include="..\wtf\StringHasher.h" />
<ClInclude Include="..\wtf\StringPrintStream.h" />
Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters (174318 => 174319)
--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters 2014-10-04 19:18:38 UTC (rev 174319)
@@ -609,6 +609,9 @@
<ClInclude Include="..\wtf\StdLibExtras.h">
<Filter>wtf</Filter>
</ClInclude>
+ <ClInclude Include="..\wtf\Stopwatch.h">
+ <Filter>wtf</Filter>
+ </ClInclude>
<ClInclude Include="..\wtf\StringExtras.h">
<Filter>wtf</Filter>
</ClInclude>
Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (174318 => 174319)
--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2014-10-04 19:18:38 UTC (rev 174319)
@@ -272,6 +272,7 @@
A8A47487151A825B004123FF /* WTFThreadData.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4737B151A825B004123FF /* WTFThreadData.h */; };
A8A4748C151A8264004123FF /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = A8A4748B151A8264004123FF /* config.h */; };
B38FD7BD168953E80065C969 /* FeatureDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = B38FD7BC168953E80065C969 /* FeatureDefines.h */; };
+ C4F8A93719C65EB400B2B15D /* Stopwatch.h in Headers */ = {isa = PBXBuildFile; fileRef = C4F8A93619C65EB400B2B15D /* Stopwatch.h */; };
CD5497AC15857D0300B5BC30 /* MediaTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD5497AA15857D0300B5BC30 /* MediaTime.cpp */; };
CD5497AD15857D0300B5BC30 /* MediaTime.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5497AB15857D0300B5BC30 /* MediaTime.h */; };
CE46516E19DB1FB4003ECA05 /* NSMapTableSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CE46516D19DB1FB4003ECA05 /* NSMapTableSPI.h */; };
@@ -564,6 +565,7 @@
A8A4737B151A825B004123FF /* WTFThreadData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WTFThreadData.h; sourceTree = "<group>"; };
A8A4748B151A8264004123FF /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
B38FD7BC168953E80065C969 /* FeatureDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FeatureDefines.h; sourceTree = "<group>"; };
+ C4F8A93619C65EB400B2B15D /* Stopwatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Stopwatch.h; sourceTree = "<group>"; };
CD5497AA15857D0300B5BC30 /* MediaTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaTime.cpp; sourceTree = "<group>"; };
CD5497AB15857D0300B5BC30 /* MediaTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaTime.h; sourceTree = "<group>"; };
CE46516D19DB1FB4003ECA05 /* NSMapTableSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSMapTableSPI.h; sourceTree = "<group>"; };
@@ -856,6 +858,7 @@
FEDACD3C1630F83F00C69634 /* StackStats.h */,
A8A47310151A825B004123FF /* StaticConstructors.h */,
A8A47311151A825B004123FF /* StdLibExtras.h */,
+ C4F8A93619C65EB400B2B15D /* Stopwatch.h */,
1A6BB768162F300500DD16DB /* StreamBuffer.h */,
A8A47313151A825B004123FF /* StringExtras.h */,
A748745117A0BDAE00FA04CB /* StringHashDumpContext.h */,
@@ -1075,6 +1078,7 @@
A8A473A3151A825B004123FF /* DecimalNumber.h in Headers */,
0F2B66A617B6B4FB00A7AE3F /* DeferrableRefCounted.h in Headers */,
A8A473A5151A825B004123FF /* Deque.h in Headers */,
+ C4F8A93719C65EB400B2B15D /* Stopwatch.h in Headers */,
A8A473A6151A825B004123FF /* DisallowCType.h in Headers */,
A8A473AF151A825B004123FF /* diy-fp.h in Headers */,
A8A473B1151A825B004123FF /* double-conversion.h in Headers */,
Modified: trunk/Source/WTF/wtf/CMakeLists.txt (174318 => 174319)
--- trunk/Source/WTF/wtf/CMakeLists.txt 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WTF/wtf/CMakeLists.txt 2014-10-04 19:18:38 UTC (rev 174319)
@@ -92,6 +92,7 @@
StackStats.h
StaticConstructors.h
StdLibExtras.h
+ Stopwatch.h
StringExtras.h
StringHasher.h
StringPrintStream.h
Added: trunk/Source/WTF/wtf/Stopwatch.h (0 => 174319)
--- trunk/Source/WTF/wtf/Stopwatch.h (rev 0)
+++ trunk/Source/WTF/wtf/Stopwatch.h 2014-10-04 19:18:38 UTC (rev 174319)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 University of Washington. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Stopwatch_h
+#define Stopwatch_h
+
+#include <cmath>
+#include <wtf/CurrentTime.h>
+#include <wtf/RefCounted.h>
+
+namespace WTF {
+
+class Stopwatch : public RefCounted<Stopwatch> {
+public:
+ static PassRefPtr<Stopwatch> create()
+ {
+ return adoptRef(new Stopwatch());
+ }
+
+ void reset();
+ void start();
+ void stop();
+
+ double elapsedTime();
+
+private:
+ Stopwatch()
+ : m_elapsedTime(NAN)
+ , m_lastStartTime(NAN)
+ {
+ }
+
+ double m_elapsedTime;
+ double m_lastStartTime;
+};
+
+inline void Stopwatch::reset()
+{
+ m_elapsedTime = 0.0;
+ m_lastStartTime = NAN;
+}
+
+inline void Stopwatch::start()
+{
+ ASSERT(!isnan(m_elapsedTime) && isnan(m_lastStartTime));
+
+ m_lastStartTime = monotonicallyIncreasingTime();
+}
+
+inline void Stopwatch::stop()
+{
+ ASSERT(!isnan(m_elapsedTime) && !isnan(m_lastStartTime));
+
+ m_elapsedTime += monotonicallyIncreasingTime() - m_lastStartTime;
+ m_lastStartTime = NAN;
+}
+
+inline double Stopwatch::elapsedTime()
+{
+ bool shouldSuspend = !isnan(m_lastStartTime);
+ if (shouldSuspend)
+ stop();
+
+ ASSERT(!isnan(m_elapsedTime) && isnan(m_lastStartTime));
+ double elapsedTime = m_elapsedTime;
+
+ if (shouldSuspend)
+ start();
+ return elapsedTime;
+}
+
+} // namespace WTF
+
+using WTF::Stopwatch;
+
+#endif // Stopwatch_h
Modified: trunk/Source/WebCore/ChangeLog (174318 => 174319)
--- trunk/Source/WebCore/ChangeLog 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebCore/ChangeLog 2014-10-04 19:18:38 UTC (rev 174319)
@@ -1,3 +1,66 @@
+2014-10-04 Brian J. Burg <[email protected]>
+
+ Web Inspector: timelines should not count time elapsed while paused in the debugger
+ https://bugs.webkit.org/show_bug.cgi?id=136351
+
+ Reviewed by Timothy Hatcher.
+
+ To avoid counting time elapsed while the debugger is paused, timeline records should
+ keep track of time elapsed since the start of timeline capturing, rather than wall clock
+ timestamps. We can easily compute elapsed time by sharing Stopwatch instance among
+ all timeline record-generating code. The stopwatch is paused while the debugger is paused,
+ so subsequent time measurements will not include time elapsed while the debugger is paused.
+
+ Agents use the shared stopwatch to generate timestamps if the timeline agent is active
+ (i.e., a timeline recording is being captured). If not, use a zero timestamp since the timing data is only revealed through the Timeline interface.
+
+ This refactoring is safe because start and end times are only used to graph records; the
+ timestamp's actual value is irrelevant and is not displayed in the user interface. Date
+ timestamps are still included with network-related records as part of their header data.
+
+ No new tests, because we cannot reliably test timing changes induced by debugger pauses.
+ It is possible for records to accrue time before the debugger pauses or after it resumes.
+
+ * inspector/InspectorCSSAgent.cpp: Remove unused include.
+ * inspector/InspectorPageAgent.cpp: Use timestamps from the shared stopwatch.
+ (WebCore::InspectorPageAgent::timestamp):
+ (WebCore::InspectorPageAgent::domContentEventFired):
+ (WebCore::InspectorPageAgent::loadEventFired):
+ * inspector/InspectorPageAgent.h:
+ * inspector/InspectorResourceAgent.cpp: Use timestamps from the shared stopwatch.
+ (WebCore::InspectorResourceAgent::timestamp):
+ (WebCore::InspectorResourceAgent::willSendRequest):
+ (WebCore::InspectorResourceAgent::didReceiveResponse):
+ (WebCore::InspectorResourceAgent::didReceiveData):
+ (WebCore::InspectorResourceAgent::didFinishLoading):
+ (WebCore::InspectorResourceAgent::didFailLoading):
+ (WebCore::InspectorResourceAgent::didLoadResourceFromMemoryCache):
+ (WebCore::InspectorResourceAgent::willSendWebSocketHandshakeRequest):
+ (WebCore::InspectorResourceAgent::didReceiveWebSocketHandshakeResponse):
+ (WebCore::InspectorResourceAgent::didCloseWebSocket):
+ (WebCore::InspectorResourceAgent::didReceiveWebSocketFrame):
+ (WebCore::InspectorResourceAgent::didSendWebSocketFrame):
+ (WebCore::InspectorResourceAgent::didReceiveWebSocketFrameError):
+ * inspector/InspectorResourceAgent.h:
+ * inspector/InspectorTimelineAgent.cpp: Add calls to reset, start, and stop the stopwatch.
+ (WebCore::InspectorTimelineAgent::didCreateFrontendAndBackend):
+ (WebCore::InspectorTimelineAgent::internalStart):
+ (WebCore::InspectorTimelineAgent::internalStop):
+ (WebCore::startProfiling):
+ (WebCore::InspectorTimelineAgent::startFromConsole):
+ (WebCore::InspectorTimelineAgent::willCallFunction):
+ (WebCore::InspectorTimelineAgent::willEvaluateScript):
+ (WebCore::InspectorTimelineAgent::didPause):
+ (WebCore::InspectorTimelineAgent::didContinue):
+ (WebCore::InspectorTimelineAgent::InspectorTimelineAgent):
+ (WebCore::InspectorTimelineAgent::timestamp):
+ (WebCore::TimelineTimeConverter::reset): Deleted.
+ * inspector/InspectorTimelineAgent.h: Make timestamp() public, and remove old timepieces.
+ (WebCore::TimelineTimeConverter::TimelineTimeConverter): Deleted.
+ (WebCore::TimelineTimeConverter::fromMonotonicallyIncreasingTime): Deleted.
+ (WebCore::InspectorTimelineAgent::timeConverter): Deleted.
+ * inspector/TimelineRecordFactory.cpp:
+
2014-10-04 Tim Horton <[email protected]>
Make it possible to test page overlays
Modified: trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp (174318 => 174319)
--- trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp 2014-10-04 19:18:38 UTC (rev 174319)
@@ -57,7 +57,6 @@
#include "StyleSheetList.h"
#include "WebKitNamedFlow.h"
#include <inspector/InspectorValues.h>
-#include <wtf/CurrentTime.h>
#include <wtf/HashSet.h>
#include <wtf/Ref.h>
#include <wtf/Vector.h>
Modified: trunk/Source/WebCore/inspector/InspectorPageAgent.cpp (174318 => 174319)
--- trunk/Source/WebCore/inspector/InspectorPageAgent.cpp 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebCore/inspector/InspectorPageAgent.cpp 2014-10-04 19:18:38 UTC (rev 174319)
@@ -57,6 +57,7 @@
#include "InspectorDOMAgent.h"
#include "InspectorInstrumentation.h"
#include "InspectorOverlay.h"
+#include "InspectorTimelineAgent.h"
#include "InspectorWebFrontendDispatchers.h"
#include "InstrumentingAgents.h"
#include "MainFrame.h"
@@ -73,7 +74,6 @@
#include <inspector/ContentSearchUtilities.h>
#include <inspector/IdentifiersFactory.h>
#include <inspector/InspectorValues.h>
-#include <wtf/CurrentTime.h>
#include <wtf/ListHashSet.h>
#include <wtf/Vector.h>
#include <wtf/text/Base64.h>
@@ -361,6 +361,16 @@
#endif
}
+double InspectorPageAgent::timestamp()
+{
+ // If the timeline agent is recording now, use its stopwatch. Otherwise, just report 0.0
+ // since the timestamps are only used to accurately graph records on the timeline.
+ if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+ return timelineAgent->timestamp();
+
+ return 0.0;
+}
+
void InspectorPageAgent::enable(ErrorString&)
{
m_enabled = true;
@@ -752,12 +762,12 @@
void InspectorPageAgent::domContentEventFired()
{
m_isFirstLayoutAfterOnLoad = true;
- m_frontendDispatcher->domContentEventFired(currentTime());
+ m_frontendDispatcher->domContentEventFired(timestamp());
}
void InspectorPageAgent::loadEventFired()
{
- m_frontendDispatcher->loadEventFired(currentTime());
+ m_frontendDispatcher->loadEventFired(timestamp());
}
void InspectorPageAgent::frameNavigated(DocumentLoader* loader)
Modified: trunk/Source/WebCore/inspector/InspectorPageAgent.h (174318 => 174319)
--- trunk/Source/WebCore/inspector/InspectorPageAgent.h 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebCore/inspector/InspectorPageAgent.h 2014-10-04 19:18:38 UTC (rev 174319)
@@ -167,6 +167,8 @@
void updateTouchEventEmulationInPage(bool);
#endif
+ double timestamp();
+
static bool mainResourceContent(Frame*, bool withBase64Encode, String* result);
static bool dataContent(const char* data, unsigned size, const String& textEncodingName, bool withBase64Encode, String* result);
Modified: trunk/Source/WebCore/inspector/InspectorResourceAgent.cpp (174318 => 174319)
--- trunk/Source/WebCore/inspector/InspectorResourceAgent.cpp 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebCore/inspector/InspectorResourceAgent.cpp 2014-10-04 19:18:38 UTC (rev 174319)
@@ -47,6 +47,7 @@
#include "IconController.h"
#include "InspectorClient.h"
#include "InspectorPageAgent.h"
+#include "InspectorTimelineAgent.h"
#include "InspectorWebFrontendDispatchers.h"
#include "InstrumentingAgents.h"
#include "JSMainThreadExecState.h"
@@ -69,7 +70,6 @@
#include <inspector/InspectorValues.h>
#include <inspector/ScriptCallStack.h>
#include <inspector/ScriptCallStackFactory.h>
-#include <wtf/CurrentTime.h>
#include <wtf/RefPtr.h>
#include <wtf/text/StringBuilder.h>
@@ -276,6 +276,16 @@
ASSERT(!m_instrumentingAgents->inspectorResourceAgent());
}
+double InspectorResourceAgent::timestamp()
+{
+ // If the timeline agent is recording now, use its stopwatch. Otherwise, just report 0.0
+ // since the timestamps are only used to accurately graph records on the timeline.
+ if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
+ return timelineAgent->timestamp();
+
+ return 0.0;
+}
+
void InspectorResourceAgent::willSendRequest(unsigned long identifier, DocumentLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
if (request.hiddenFromInspector()) {
@@ -320,7 +330,7 @@
Inspector::Protocol::Page::ResourceType resourceType = InspectorPageAgent::resourceTypeJson(type);
RefPtr<Inspector::Protocol::Network::Initiator> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : nullptr);
- m_frontendDispatcher->requestWillBeSent(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), loader->url().string(), buildObjectForResourceRequest(request), currentTime(), initiatorObject, buildObjectForResourceResponse(redirectResponse, loader), type != InspectorPageAgent::OtherResource ? &resourceType : nullptr);
+ m_frontendDispatcher->requestWillBeSent(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), loader->url().string(), buildObjectForResourceRequest(request), timestamp(), initiatorObject, buildObjectForResourceResponse(redirectResponse, loader), type != InspectorPageAgent::OtherResource ? &resourceType : nullptr);
}
void InspectorResourceAgent::markResourceAsCached(unsigned long identifier)
@@ -365,7 +375,7 @@
m_resourcesData->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), response);
m_resourcesData->setResourceType(requestId, type);
- m_frontendDispatcher->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), currentTime(), InspectorPageAgent::resourceTypeJson(type), resourceResponse);
+ m_frontendDispatcher->responseReceived(requestId, m_pageAgent->frameId(loader->frame()), m_pageAgent->loaderId(loader), timestamp(), InspectorPageAgent::resourceTypeJson(type), resourceResponse);
// If we revalidated the resource and got Not modified, send content length following didReceiveResponse
// as there will be no calls to didReceiveData from the network stack.
@@ -391,7 +401,7 @@
m_resourcesData->maybeAddResourceData(requestId, data, dataLength);
}
- m_frontendDispatcher->dataReceived(requestId, currentTime(), dataLength, encodedDataLength);
+ m_frontendDispatcher->dataReceived(requestId, timestamp(), dataLength, encodedDataLength);
}
void InspectorResourceAgent::didFinishLoading(unsigned long identifier, DocumentLoader* loader, double finishTime)
@@ -411,7 +421,7 @@
// However, all other times passed to the Inspector are generated from the web process. Mixing
// times from different processes can cause the finish time to be earlier than the response
// received time due to inter-process communication lag.
- finishTime = currentTime();
+ finishTime = timestamp();
String sourceMappingURL;
NetworkResourcesData::ResourceData const* resourceData = m_resourcesData->data(requestId);
@@ -437,7 +447,7 @@
}
bool canceled = error.isCancellation();
- m_frontendDispatcher->loadingFailed(requestId, currentTime(), error.localizedDescription(), canceled ? &canceled : nullptr);
+ m_frontendDispatcher->loadingFailed(requestId, timestamp(), error.localizedDescription(), canceled ? &canceled : nullptr);
}
void InspectorResourceAgent::didLoadResourceFromMemoryCache(DocumentLoader* loader, CachedResource* resource)
@@ -456,7 +466,7 @@
RefPtr<Inspector::Protocol::Network::Initiator> initiatorObject = buildInitiatorObject(loader->frame() ? loader->frame()->document() : nullptr);
- m_frontendDispatcher->requestServedFromMemoryCache(requestId, frameId, loaderId, loader->url().string(), currentTime(), initiatorObject, buildObjectForCachedResource(resource, loader));
+ m_frontendDispatcher->requestServedFromMemoryCache(requestId, frameId, loaderId, loader->url().string(), timestamp(), initiatorObject, buildObjectForCachedResource(resource, loader));
}
void InspectorResourceAgent::setInitialScriptContent(unsigned long identifier, const String& sourceString)
@@ -588,7 +598,7 @@
{
RefPtr<Inspector::Protocol::Network::WebSocketRequest> requestObject = Inspector::Protocol::Network::WebSocketRequest::create()
.setHeaders(buildObjectForHeaders(request.httpHeaderFields()));
- m_frontendDispatcher->webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), currentTime(), requestObject);
+ m_frontendDispatcher->webSocketWillSendHandshakeRequest(IdentifiersFactory::requestId(identifier), timestamp(), requestObject);
}
void InspectorResourceAgent::didReceiveWebSocketHandshakeResponse(unsigned long identifier, const ResourceResponse& response)
@@ -597,12 +607,12 @@
.setStatus(response.httpStatusCode())
.setStatusText(response.httpStatusText())
.setHeaders(buildObjectForHeaders(response.httpHeaderFields()));
- m_frontendDispatcher->webSocketHandshakeResponseReceived(IdentifiersFactory::requestId(identifier), currentTime(), responseObject);
+ m_frontendDispatcher->webSocketHandshakeResponseReceived(IdentifiersFactory::requestId(identifier), timestamp(), responseObject);
}
void InspectorResourceAgent::didCloseWebSocket(unsigned long identifier)
{
- m_frontendDispatcher->webSocketClosed(IdentifiersFactory::requestId(identifier), currentTime());
+ m_frontendDispatcher->webSocketClosed(IdentifiersFactory::requestId(identifier), timestamp());
}
void InspectorResourceAgent::didReceiveWebSocketFrame(unsigned long identifier, const WebSocketFrame& frame)
@@ -611,7 +621,7 @@
.setOpcode(frame.opCode)
.setMask(frame.masked)
.setPayloadData(String(frame.payload, frame.payloadLength));
- m_frontendDispatcher->webSocketFrameReceived(IdentifiersFactory::requestId(identifier), currentTime(), frameObject);
+ m_frontendDispatcher->webSocketFrameReceived(IdentifiersFactory::requestId(identifier), timestamp(), frameObject);
}
void InspectorResourceAgent::didSendWebSocketFrame(unsigned long identifier, const WebSocketFrame& frame)
@@ -620,12 +630,12 @@
.setOpcode(frame.opCode)
.setMask(frame.masked)
.setPayloadData(String(frame.payload, frame.payloadLength));
- m_frontendDispatcher->webSocketFrameSent(IdentifiersFactory::requestId(identifier), currentTime(), frameObject);
+ m_frontendDispatcher->webSocketFrameSent(IdentifiersFactory::requestId(identifier), timestamp(), frameObject);
}
void InspectorResourceAgent::didReceiveWebSocketFrameError(unsigned long identifier, const String& errorMessage)
{
- m_frontendDispatcher->webSocketFrameError(IdentifiersFactory::requestId(identifier), currentTime(), errorMessage);
+ m_frontendDispatcher->webSocketFrameError(IdentifiersFactory::requestId(identifier), timestamp(), errorMessage);
}
#endif // ENABLE(WEB_SOCKETS)
Modified: trunk/Source/WebCore/inspector/InspectorResourceAgent.h (174318 => 174319)
--- trunk/Source/WebCore/inspector/InspectorResourceAgent.h 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebCore/inspector/InspectorResourceAgent.h 2014-10-04 19:18:38 UTC (rev 174319)
@@ -138,6 +138,8 @@
private:
void enable();
+ double timestamp();
+
InspectorPageAgent* m_pageAgent;
InspectorClient* m_client;
std::unique_ptr<Inspector::InspectorNetworkFrontendDispatcher> m_frontendDispatcher;
Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp (174318 => 174319)
--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp 2014-10-04 19:18:38 UTC (rev 174319)
@@ -61,11 +61,6 @@
namespace WebCore {
-void TimelineTimeConverter::reset()
-{
- m_startOffset = monotonicallyIncreasingTime() - currentTime();
-}
-
InspectorTimelineAgent::~InspectorTimelineAgent()
{
}
@@ -76,6 +71,7 @@
m_backendDispatcher = InspectorTimelineBackendDispatcher::create(backendDispatcher, this);
m_instrumentingAgents->setPersistentInspectorTimelineAgent(this);
+ m_stopwatch->reset();
if (m_scriptDebugServer)
m_scriptDebugServer->recompileAllJSFunctions();
@@ -118,7 +114,7 @@
else
m_maxCallStackDepth = 5;
- m_timeConverter.reset();
+ m_stopwatch->start();
m_instrumentingAgents->setInspectorTimelineAgent(this);
@@ -136,6 +132,8 @@
if (!m_enabled)
return;
+ m_stopwatch->stop();
+
m_instrumentingAgents->setInspectorTimelineAgent(nullptr);
if (m_scriptDebugServer)
@@ -157,9 +155,9 @@
m_scriptDebugServer = scriptDebugServer;
}
-static inline void startProfiling(JSC::ExecState* exec, const String& title)
+static inline void startProfiling(JSC::ExecState* exec, const String& title, PassRefPtr<Stopwatch> stopwatch)
{
- JSC::LegacyProfiler::profiler()->startProfiling(exec, title);
+ JSC::LegacyProfiler::profiler()->startProfiling(exec, title, stopwatch);
}
static inline PassRefPtr<JSC::Profile> stopProfiling(JSC::ExecState* exec, const String& title)
@@ -167,9 +165,9 @@
return JSC::LegacyProfiler::profiler()->stopProfiling(exec, title);
}
-static inline void startProfiling(Frame* frame, const String& title)
+static inline void startProfiling(Frame* frame, const String& title, PassRefPtr<Stopwatch> stopwatch)
{
- startProfiling(toJSDOMWindow(frame, debuggerWorld())->globalExec(), title);
+ startProfiling(toJSDOMWindow(frame, debuggerWorld())->globalExec(), title, stopwatch);
}
static inline PassRefPtr<JSC::Profile> stopProfiling(Frame* frame, const String& title)
@@ -193,7 +191,7 @@
if (!m_enabled && m_pendingConsoleProfileRecords.isEmpty())
internalStart();
- startProfiling(exec, title);
+ startProfiling(exec, title, m_stopwatch);
m_pendingConsoleProfileRecords.append(createRecordEntry(TimelineRecordFactory::createConsoleProfileData(title), TimelineRecordType::ConsoleProfile, true, frameFromExecState(exec)));
}
@@ -232,7 +230,7 @@
pushCurrentRecord(TimelineRecordFactory::createFunctionCallData(scriptName, scriptLine), TimelineRecordType::FunctionCall, true, frame);
if (frame && !m_callStackDepth)
- startProfiling(frame, ASCIILiteral("Timeline FunctionCall"));
+ startProfiling(frame, ASCIILiteral("Timeline FunctionCall"), m_stopwatch);
++m_callStackDepth;
}
@@ -407,7 +405,7 @@
if (frame && !m_callStackDepth) {
++m_callStackDepth;
- startProfiling(frame, ASCIILiteral("Timeline EvaluateScript"));
+ startProfiling(frame, ASCIILiteral("Timeline EvaluateScript"), m_stopwatch);
}
}
@@ -554,6 +552,16 @@
appendRecord(TimelineRecordFactory::createProbeSampleData(action, hitCount), TimelineRecordType::ProbeSample, false, frameFromExecState(exec));
}
+void InspectorTimelineAgent::didPause(JSC::ExecState*, const Deprecated::ScriptValue&, const Deprecated::ScriptValue&)
+{
+ m_stopwatch->stop();
+}
+
+void InspectorTimelineAgent::didContinue()
+{
+ m_stopwatch->start();
+}
+
static Inspector::Protocol::Timeline::EventType toProtocol(TimelineRecordType type)
{
switch (type) {
@@ -690,6 +698,7 @@
: InspectorAgentBase(ASCIILiteral("Timeline"), instrumentingAgents)
, m_pageAgent(pageAgent)
, m_scriptDebugServer(nullptr)
+ , m_stopwatch(Stopwatch::create())
, m_id(1)
, m_callStackDepth(0)
, m_maxCallStackDepth(5)
@@ -748,7 +757,7 @@
double InspectorTimelineAgent::timestamp()
{
- return m_timeConverter.fromMonotonicallyIncreasingTime(monotonicallyIncreasingTime());
+ return m_stopwatch->elapsedTime();
}
Page* InspectorTimelineAgent::page()
Modified: trunk/Source/WebCore/inspector/InspectorTimelineAgent.h (174318 => 174319)
--- trunk/Source/WebCore/inspector/InspectorTimelineAgent.h 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebCore/inspector/InspectorTimelineAgent.h 2014-10-04 19:18:38 UTC (rev 174319)
@@ -40,6 +40,7 @@
#include "LayoutRect.h"
#include <inspector/InspectorValues.h>
#include <inspector/ScriptDebugListener.h>
+#include <wtf/Stopwatch.h>
#include <wtf/Vector.h>
#include <wtf/WeakPtr.h>
@@ -113,19 +114,6 @@
WebSocketDestroy
};
-class TimelineTimeConverter {
-public:
- TimelineTimeConverter()
- : m_startOffset(0)
- {
- }
- double fromMonotonicallyIncreasingTime(double time) const { return (time - m_startOffset) * 1000.0; }
- void reset();
-
-private:
- double m_startOffset;
-};
-
class InspectorTimelineAgent
: public InspectorAgentBase
, public Inspector::InspectorTimelineBackendDispatcherHandler
@@ -210,6 +198,10 @@
void willFireAnimationFrame(int callbackId, Frame*);
void didFireAnimationFrame();
+ // Returns the elapsed time from a monotonic stopwatch that starts with timeline recording and
+ // pauses when the debugger pauses or execution is otherwise suspended.
+ double timestamp();
+
#if ENABLE(WEB_SOCKETS)
void didCreateWebSocket(unsigned long identifier, const URL&, const String& protocol, Frame*);
void willSendWebSocketHandshakeRequest(unsigned long identifier, Frame*);
@@ -218,11 +210,11 @@
#endif
protected:
- // ScriptDebugListener. This is only used to create records for probe samples.
+ // ScriptDebugListener
virtual void didParseSource(JSC::SourceID, const Script&) override { }
virtual void failedToParseSource(const String&, const String&, int, int, const String&) override { }
- virtual void didPause(JSC::ExecState*, const Deprecated::ScriptValue&, const Deprecated::ScriptValue&) override { }
- virtual void didContinue() override { }
+ virtual void didPause(JSC::ExecState*, const Deprecated::ScriptValue&, const Deprecated::ScriptValue&) override;
+ virtual void didContinue() override;
virtual void breakpointActionLog(JSC::ExecState*, const String&) override { }
virtual void breakpointActionSound(int) override { }
@@ -264,17 +256,15 @@
void clearRecordStack();
void localToPageQuad(const RenderObject&, const LayoutRect&, FloatQuad*);
- const TimelineTimeConverter& timeConverter() const { return m_timeConverter; }
- double timestamp();
Page* page();
InspectorPageAgent* m_pageAgent;
PageScriptDebugServer* m_scriptDebugServer;
- TimelineTimeConverter m_timeConverter;
+ RefPtr<Stopwatch> m_stopwatch;
+
std::unique_ptr<Inspector::InspectorTimelineFrontendDispatcher> m_frontendDispatcher;
RefPtr<Inspector::InspectorTimelineBackendDispatcher> m_backendDispatcher;
- double m_timestampOffset;
Vector<TimelineRecordEntry> m_recordStack;
Modified: trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp (174318 => 174319)
--- trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp 2014-10-04 19:18:38 UTC (rev 174319)
@@ -47,7 +47,6 @@
#include <inspector/ScriptCallStack.h>
#include <inspector/ScriptCallStackFactory.h>
#include <profiler/Profile.h>
-#include <wtf/CurrentTime.h>
using namespace Inspector;
Modified: trunk/Source/WebInspectorUI/ChangeLog (174318 => 174319)
--- trunk/Source/WebInspectorUI/ChangeLog 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebInspectorUI/ChangeLog 2014-10-04 19:18:38 UTC (rev 174319)
@@ -1,3 +1,24 @@
+2014-10-04 Brian J. Burg <[email protected]>
+
+ Web Inspector: timelines should not count time elapsed while paused in the debugger
+ https://bugs.webkit.org/show_bug.cgi?id=136351
+
+ Reviewed by Timothy Hatcher.
+
+ Don't update the timeline's current time when the debugger is paused.
+
+ Start and end times for timeline records are now in seconds elapsed since timeline
+ recording started, rather than milliseconds since the epoch. Add a workaround to
+ preserve compatibility with old backends.
+
+ * UserInterface/Controllers/TimelineManager.js:
+ (WebInspector.TimelineManager.prototype.capturingStarted):
+ (WebInspector.TimelineManager.prototype.eventRecorded.processRecord):
+ (WebInspector.TimelineManager.prototype.eventRecorded):
+ * UserInterface/Views/TimelineContentView.js:
+ (WebInspector.TimelineContentView.prototype._debuggerPaused):
+ (WebInspector.TimelineContentView.prototype._debuggerResumed):
+
2014-10-03 Saam Barati <[email protected]>
Web Inspector: Move the computation that results in UI strings from JSC to the Web Inspector
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js (174318 => 174319)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js 2014-10-04 19:18:38 UTC (rev 174319)
@@ -35,6 +35,8 @@
this._activeRecording = null;
this._isCapturing = false;
+ // For legacy backends, we compute the elapsed time of records relative to this timestamp.
+ this._legacyFirstRecordTimestamp = NaN;
this._nextRecordingIdentifier = 1;
this._boundStopCapturing = this.stopCapturing.bind(this);
@@ -55,6 +57,7 @@
CapturingStopped: "timeline-manager-capturing-stopped"
};
+WebInspector.TimelineManager.StartTimeThresholdForLegacyRecordConversion = 28800000; // Date.parse("Jan 1, 1970")
WebInspector.TimelineManager.MaximumAutoRecordDuration = 90000; // 90 seconds
WebInspector.TimelineManager.MaximumAutoRecordDurationAfterLoadEvent = 10000; // 10 seconds
WebInspector.TimelineManager.DeadTimeRequiredToStopAutoRecordingEarly = 2000; // 2 seconds
@@ -163,10 +166,21 @@
function processRecord(recordPayload, parentRecordPayload)
{
- // Convert the timestamps to seconds to match the resource timestamps.
- var startTime = recordPayload.startTime / 1000;
- var endTime = recordPayload.endTime / 1000;
+ var startTime = recordPayload.startTime;
+ var endTime = recordPayload.endTime;
+ // COMPATIBILITY (iOS8): old versions use milliseconds since the epoch, rather
+ // than seconds elapsed since timeline capturing started. We approximate the latter by
+ // subtracting the start timestamp, as old versions did not use monotonic times.
+ if (isNaN(this._legacyFirstRecordTimestamp))
+ this._legacyFirstRecordTimestamp = recordPayload.startTime;
+
+ // If the record's start time sems unreasonably large, treat it as a legacy timestamp.
+ if (startTime > WebInspector.StartTimeThresholdForLegacyRecordConversion) {
+ startTime = (startTime - this._legacyFirstRecordTimestamp) / 1000;
+ endTime = isNaN(endTime) ? NaN : (startTime - this._legacyFirstRecordTimestamp) / 1000;
+ }
+
var callFrames = this._callFramesFromPayload(recordPayload.stackTrace);
var significantCallFrame = null;
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineContentView.js (174318 => 174319)
--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineContentView.js 2014-10-04 17:18:25 UTC (rev 174318)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineContentView.js 2014-10-04 19:18:38 UTC (rev 174319)
@@ -98,6 +98,9 @@
WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingStarted, this._capturingStarted, this);
WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingStopped, this._capturingStopped, this);
+ WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Paused, this._debuggerPaused, this);
+ WebInspector.debuggerManager.addEventListener(WebInspector.DebuggerManager.Event.Resumed, this._debuggerResumed, this);
+
this.showOverviewTimelineView();
};
@@ -407,6 +410,22 @@
this._stopUpdatingCurrentTime();
},
+ _debuggerPaused: function(event)
+ {
+ if (WebInspector.replayManager.sessionState === WebInspector.ReplayManager.SessionState.Replaying)
+ return;
+
+ this._stopUpdatingCurrentTime();
+ },
+
+ _debuggerResumed: function(event)
+ {
+ if (WebInspector.replayManager.sessionState === WebInspector.ReplayManager.SessionState.Replaying)
+ return;
+
+ this._startUpdatingCurrentTime();
+ },
+
_recordingTimesUpdated: function(event)
{
if (!this._waitingToResetCurrentTime)