Source/WebCore: Web Inspector: show raster tasks on Timeline
authorcaseq@chromium.org <caseq@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Feb 2013 13:12:28 +0000 (13:12 +0000)
committercaseq@chromium.org <caseq@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Feb 2013 13:12:28 +0000 (13:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=105851

- add PaintLayer, Paint & RasterTask trace events handling to trace event processor;
- upon begin frame, emit aggregated background event for all raster tasks related to the inspected page.

Reviewed by Pavel Feldman.

* inspector/InspectorInstrumentation.cpp:
(WebCore):
(WebCore::InspectorInstrumentation::willPaintImpl):
(InstrumentationEvents):
(InstrumentationEventArguments):
* inspector/InspectorInstrumentation.h:
(InstrumentationEvents):
(WebCore):
(InstrumentationEventArguments):
* inspector/InspectorTimelineAgent.cpp:
(TimelineRecordType):
(WebCore::InspectorTimelineAgent::stop):
(WebCore::InspectorTimelineAgent::didBeginFrame):
* inspector/InspectorTimelineAgent.h:
(TimelineRecordType):
(WebCore):
* inspector/TimelineRecordFactory.cpp:
(WebCore::TimelineRecordFactory::createRasterData):
(WebCore):
* inspector/TimelineRecordFactory.h:
(TimelineRecordFactory):
* inspector/TimelineTraceEventProcessor.cpp:
(WebCore::TimelineTraceEventProcessor::TimelineTraceEventProcessor):
(WebCore::TimelineTraceEventProcessor::~TimelineTraceEventProcessor):
(WebCore):
(WebCore::TimelineTraceEventProcessor::registerHandler):
(WebCore::TimelineTraceEventProcessor::shutdown):
(WebCore::TimelineTraceEventProcessor::TraceEvent::findParameter):
(WebCore::TimelineTraceEventProcessor::TraceEvent::parameter):
(WebCore::TimelineTraceEventProcessor::processEventOnAnyThread):
(WebCore::TimelineTraceEventProcessor::onBeginFrame):
(WebCore::TimelineTraceEventProcessor::onPaintLayerBegin):
(WebCore::TimelineTraceEventProcessor::onPaintLayerEnd):
(WebCore::TimelineTraceEventProcessor::onRasterTaskBegin):
(WebCore::TimelineTraceEventProcessor::onRasterTaskEnd):
(WebCore::TimelineTraceEventProcessor::onLayerDeleted):
(WebCore::TimelineTraceEventProcessor::onPaint):
(WebCore::TimelineTraceEventProcessor::flushRasterizerStatistics):
(WebCore::TimelineTraceEventProcessor::sendTimelineRecord):
(WebCore::TimelineTraceEventProcessor::processBackgroundEvents):
* inspector/TimelineTraceEventProcessor.h:
(WebCore::TimelineTraceEventProcessor::TraceEvent::TraceEvent):
(WebCore::TimelineTraceEventProcessor::TraceEvent::id):
(WebCore::TimelineTraceEventProcessor::TraceEvent::asBool):
(WebCore::TimelineTraceEventProcessor::TraceEvent::asInt):
(WebCore::TimelineTraceEventProcessor::TraceEvent::asUInt):
(WebCore::TimelineTraceEventProcessor::TraceEvent::asDouble):
(TimelineTraceEventProcessor):
* inspector/front-end/TimelineModel.js:
* inspector/front-end/TimelinePresentationModel.js:
(WebInspector.TimelinePresentationModel._initRecordStyles):

LayoutTests: Web Inspector: show deferred paints on Timeline
https://bugs.webkit.org/show_bug.cgi?id=105851

Reviewed by Pavel Feldman.

* inspector/timeline/timeline-enum-stability-expected.txt: Added "Rasterize" record type.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@144044 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/timeline/timeline-enum-stability-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/InspectorTimelineAgent.cpp
Source/WebCore/inspector/InspectorTimelineAgent.h
Source/WebCore/inspector/TimelineRecordFactory.cpp
Source/WebCore/inspector/TimelineRecordFactory.h
Source/WebCore/inspector/TimelineTraceEventProcessor.cpp
Source/WebCore/inspector/TimelineTraceEventProcessor.h
Source/WebCore/inspector/front-end/TimelineModel.js
Source/WebCore/inspector/front-end/TimelinePresentationModel.js

index 9fb2c49..a8b2a73 100644 (file)
@@ -1,3 +1,12 @@
+2013-02-26  Andrey Kosyakov  <caseq@chromium.org>
+
+        Web Inspector: show deferred paints on Timeline
+        https://bugs.webkit.org/show_bug.cgi?id=105851
+
+        Reviewed by Pavel Feldman.
+
+        * inspector/timeline/timeline-enum-stability-expected.txt: Added "Rasterize" record type.
+
 2013-02-26  Takashi Toyoshima  <toyoshim@chromium.org>
 
         Add User-Agent header in opening handshake headers.
index d57b526..f253de5 100644 (file)
@@ -19,6 +19,7 @@ Applications outside of WebKit depend on the stability of the mapping of these t
     Paint : "Paint"
     ParseHTML : "ParseHTML"
     Program : "Program"
+    Rasterize : "Rasterize"
     RecalculateStyles : "RecalculateStyles"
     RequestAnimationFrame : "RequestAnimationFrame"
     ResizeImage : "ResizeImage"
index b3a277d..cd06d66 100644 (file)
@@ -1,3 +1,65 @@
+2013-02-26  Andrey Kosyakov  <caseq@chromium.org>
+
+        Web Inspector: show raster tasks on Timeline
+        https://bugs.webkit.org/show_bug.cgi?id=105851
+
+        - add PaintLayer, Paint & RasterTask trace events handling to trace event processor;
+        - upon begin frame, emit aggregated background event for all raster tasks related to the inspected page.
+
+        Reviewed by Pavel Feldman.
+
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore):
+        (WebCore::InspectorInstrumentation::willPaintImpl):
+        (InstrumentationEvents):
+        (InstrumentationEventArguments):
+        * inspector/InspectorInstrumentation.h:
+        (InstrumentationEvents):
+        (WebCore):
+        (InstrumentationEventArguments):
+        * inspector/InspectorTimelineAgent.cpp:
+        (TimelineRecordType):
+        (WebCore::InspectorTimelineAgent::stop):
+        (WebCore::InspectorTimelineAgent::didBeginFrame):
+        * inspector/InspectorTimelineAgent.h:
+        (TimelineRecordType):
+        (WebCore):
+        * inspector/TimelineRecordFactory.cpp:
+        (WebCore::TimelineRecordFactory::createRasterData):
+        (WebCore):
+        * inspector/TimelineRecordFactory.h:
+        (TimelineRecordFactory):
+        * inspector/TimelineTraceEventProcessor.cpp:
+        (WebCore::TimelineTraceEventProcessor::TimelineTraceEventProcessor):
+        (WebCore::TimelineTraceEventProcessor::~TimelineTraceEventProcessor):
+        (WebCore):
+        (WebCore::TimelineTraceEventProcessor::registerHandler):
+        (WebCore::TimelineTraceEventProcessor::shutdown):
+        (WebCore::TimelineTraceEventProcessor::TraceEvent::findParameter):
+        (WebCore::TimelineTraceEventProcessor::TraceEvent::parameter):
+        (WebCore::TimelineTraceEventProcessor::processEventOnAnyThread):
+        (WebCore::TimelineTraceEventProcessor::onBeginFrame):
+        (WebCore::TimelineTraceEventProcessor::onPaintLayerBegin):
+        (WebCore::TimelineTraceEventProcessor::onPaintLayerEnd):
+        (WebCore::TimelineTraceEventProcessor::onRasterTaskBegin):
+        (WebCore::TimelineTraceEventProcessor::onRasterTaskEnd):
+        (WebCore::TimelineTraceEventProcessor::onLayerDeleted):
+        (WebCore::TimelineTraceEventProcessor::onPaint):
+        (WebCore::TimelineTraceEventProcessor::flushRasterizerStatistics):
+        (WebCore::TimelineTraceEventProcessor::sendTimelineRecord):
+        (WebCore::TimelineTraceEventProcessor::processBackgroundEvents):
+        * inspector/TimelineTraceEventProcessor.h:
+        (WebCore::TimelineTraceEventProcessor::TraceEvent::TraceEvent):
+        (WebCore::TimelineTraceEventProcessor::TraceEvent::id):
+        (WebCore::TimelineTraceEventProcessor::TraceEvent::asBool):
+        (WebCore::TimelineTraceEventProcessor::TraceEvent::asInt):
+        (WebCore::TimelineTraceEventProcessor::TraceEvent::asUInt):
+        (WebCore::TimelineTraceEventProcessor::TraceEvent::asDouble):
+        (TimelineTraceEventProcessor):
+        * inspector/front-end/TimelineModel.js:
+        * inspector/front-end/TimelinePresentationModel.js:
+        (WebInspector.TimelinePresentationModel._initRecordStyles):
+
 2013-02-26  Jocelyn Turcotte  <jocelyn.turcotte@digia.com>
 
         Work around a MSVC 2012 Update 1 bug causing a crash on x86
index 37a865a..7788d27 100644 (file)
 #include <wtf/StdLibExtras.h>
 #include <wtf/text/CString.h>
 
+#if PLATFORM(CHROMIUM)
+#include "platform/chromium/TraceEvent.h"
+#endif
+
 namespace WebCore {
 
 static const char* const requestAnimationFrameEventName = "requestAnimationFrame";
@@ -523,6 +527,10 @@ void InspectorInstrumentation::didDispatchXHRLoadEventImpl(const InspectorInstru
 
 InspectorInstrumentationCookie InspectorInstrumentation::willPaintImpl(InstrumentingAgents* instrumentingAgents, Frame* frame)
 {
+#if PLATFORM(CHROMIUM)
+    TRACE_EVENT_INSTANT1("instrumentation", InstrumentationEvents::Paint, InstrumentationEventArguments::PageId, frame ? reinterpret_cast<unsigned long long>(frame->page()) : 0);
+#endif
+
     int timelineAgentId = 0;
     if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) {
         timelineAgent->willPaint(frame);
@@ -1361,6 +1369,19 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents* ins
 }
 #endif
 
+namespace InstrumentationEvents {
+const char PaintLayer[] = "PaintLayer";
+const char RasterTask[] = "RasterTask";
+const char Paint[] = "Paint";
+const char Layer[] = "Layer";
+const char BeginFrame[] = "BeginFrame";
+};
+
+namespace InstrumentationEventArguments {
+const char LayerId[] = "layerId";
+const char PageId[] = "pageId";
+};
+
 } // namespace WebCore
 
 #endif // !ENABLE(INSPECTOR)
index 992db0a..86b1582 100644 (file)
@@ -500,6 +500,19 @@ private:
 #endif
 };
 
+namespace InstrumentationEvents {
+extern const char PaintLayer[];
+extern const char RasterTask[];
+extern const char Paint[];
+extern const char Layer[];
+extern const char BeginFrame[];
+};
+
+namespace InstrumentationEventArguments {
+extern const char LayerId[];
+extern const char PageId[];
+};
+
 inline void InspectorInstrumentation::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
 {
 #if ENABLE(INSPECTOR)
index a411137..0a5836a 100644 (file)
@@ -117,6 +117,9 @@ static const char WebSocketCreate[] = "WebSocketCreate";
 static const char WebSocketSendHandshakeRequest[] = "WebSocketSendHandshakeRequest";
 static const char WebSocketReceiveHandshakeResponse[] = "WebSocketReceiveHandshakeResponse";
 static const char WebSocketDestroy[] = "WebSocketDestroy";
+
+// Event names visible to other modules.
+const char Rasterize[] = "Rasterize";
 }
 
 void InspectorTimelineAgent::pushGCEventRecords()
@@ -189,6 +192,7 @@ void InspectorTimelineAgent::stop(ErrorString*)
     if (!m_state->getBoolean(TimelineAgentState::timelineAgentEnabled))
         return;
 
+    m_traceEventProcessor->shutdown();
     m_traceEventProcessor.clear();
     m_weakFactory.revokeAll();
     m_instrumentingAgents->setInspectorTimelineAgent(0);
@@ -222,6 +226,9 @@ void InspectorTimelineAgent::supportsFrameInstrumentation(ErrorString*, bool* re
 
 void InspectorTimelineAgent::didBeginFrame()
 {
+#if PLATFORM(CHROMIUM)
+    TRACE_EVENT_INSTANT0("webkit", InstrumentationEvents::BeginFrame);
+#endif
     m_pendingFrameRecord = TimelineRecordFactory::createGenericRecord(timestamp(), 0);
 }
 
index 876e28c..c499c98 100644 (file)
@@ -63,6 +63,10 @@ class TimelineTraceEventProcessor;
 
 typedef String ErrorString;
 
+namespace TimelineRecordType {
+extern const char Rasterize[];
+};
+
 class InspectorTimelineAgent
     : public InspectorBaseAgent<InspectorTimelineAgent>,
       public ScriptGCEventListener,
index 8dee530..64bad81 100644 (file)
@@ -207,6 +207,14 @@ void TimelineRecordFactory::addRectData(InspectorObject* data, const LayoutRect&
     data->setNumber("height", rect.height());
 }
 
+PassRefPtr<InspectorObject> TimelineRecordFactory::createRasterData(double totalCPUTime, int threadsUsed)
+{
+    RefPtr<InspectorObject> data = InspectorObject::create();
+    data->setNumber("totalCPUTime", totalCPUTime);
+    data->setNumber("threadsUsed", threadsUsed);
+    return data.release();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INSPECTOR)
index ef5dd56..ab54a3a 100644 (file)
@@ -106,6 +106,7 @@ namespace WebCore {
             return data.release();
         }
 #endif
+        static PassRefPtr<InspectorObject> createRasterData(double totalCPUTime, int threadsUsed);
 
     private:
         TimelineRecordFactory() { }
index b06f052..d6928d0 100644 (file)
@@ -75,8 +75,7 @@ public:
             ASSERT_NOT_REACHED();
             return;
         }
-        m_processors[index] = m_processors.last();
-        m_processors.removeLast();
+        m_processors.remove(index);
         if (m_processors.isEmpty())
             client->setTraceEventCallback(0);
     }
@@ -109,76 +108,148 @@ TimelineTraceEventProcessor::TimelineTraceEventProcessor(WeakPtr<InspectorTimeli
     : m_timelineAgent(timelineAgent)
     , m_inspectorClient(client)
     , m_pageId(reinterpret_cast<unsigned long long>(m_timelineAgent.get()->page()))
+    , m_firstRasterStartTime(0)
+    , m_lastRasterEndTime(0)
+    , m_frameRasterTime(0)
+    , m_layerId(0)
 {
+    registerHandler(InstrumentationEvents::BeginFrame, TracePhaseInstant, &TimelineTraceEventProcessor::onBeginFrame);
+    registerHandler(InstrumentationEvents::PaintLayer, TracePhaseBegin, &TimelineTraceEventProcessor::onPaintLayerBegin);
+    registerHandler(InstrumentationEvents::PaintLayer, TracePhaseEnd, &TimelineTraceEventProcessor::onPaintLayerEnd);
+    registerHandler(InstrumentationEvents::RasterTask, TracePhaseBegin, &TimelineTraceEventProcessor::onRasterTaskBegin);
+    registerHandler(InstrumentationEvents::RasterTask, TracePhaseEnd, &TimelineTraceEventProcessor::onRasterTaskEnd);
+    registerHandler(InstrumentationEvents::Layer, TracePhaseDeleteObject, &TimelineTraceEventProcessor::onLayerDeleted);
+    registerHandler(InstrumentationEvents::Paint, TracePhaseInstant, &TimelineTraceEventProcessor::onPaint);
+
     TraceEventDispatcher::instance()->addProcessor(this, m_inspectorClient);
 }
 
 TimelineTraceEventProcessor::~TimelineTraceEventProcessor()
 {
+}
+
+void TimelineTraceEventProcessor::registerHandler(const char* name, TraceEventPhase phase, TraceEventHandler handler)
+{
+    m_handlersByType.set(std::make_pair(name, phase), handler);
+}
+
+void TimelineTraceEventProcessor::shutdown()
+{
     TraceEventDispatcher::instance()->removeProcessor(this, m_inspectorClient);
 }
 
+size_t TimelineTraceEventProcessor::TraceEvent::findParameter(const char* name) const
+{
+    for (int i = 0; i < m_argumentCount; ++i) {
+        if (!strcmp(name, m_argumentNames[i]))
+            return i;
+    }
+    return notFound;
+}
+
 const TimelineTraceEventProcessor::TraceValueUnion& TimelineTraceEventProcessor::TraceEvent::parameter(const char* name, TraceValueTypes expectedType) const
 {
     static TraceValueUnion missingValue;
-
-    for (int i = 0; i < m_argumentCount; ++i) {
-        if (!strcmp(name, m_argumentNames[i])) {
-            if (m_argumentTypes[i] != expectedType) {
-                ASSERT_NOT_REACHED();
-                return missingValue;
-            }
-            return *reinterpret_cast<const TraceValueUnion*>(m_argumentValues + i);
-        }
+    size_t index = findParameter(name);
+    if (index == notFound || m_argumentTypes[index] != expectedType) {
+        ASSERT_NOT_REACHED();
+        return missingValue;
     }
-    ASSERT_NOT_REACHED();
-    return missingValue;
+    return *reinterpret_cast<const TraceValueUnion*>(m_argumentValues + index);
 }
 
-void TimelineTraceEventProcessor::processEventOnAnyThread(TraceEventPhase phase, const char* name, unsigned long long,
+void TimelineTraceEventProcessor::processEventOnAnyThread(TraceEventPhase phase, const char* name, unsigned long long id,
     int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues,
     unsigned char)
 {
-    HashMap<String, EventTypeEntry>::iterator it = m_handlersByType.find(name);
+    HandlersMap::iterator it = m_handlersByType.find(std::make_pair(name, phase));
     if (it == m_handlersByType.end())
         return;
 
-    TraceEvent event(WTF::monotonicallyIncreasingTime(), phase, name, currentThread(), numArgs, argNames, argTypes, argValues);
+    TraceEvent event(WTF::monotonicallyIncreasingTime(), phase, name, id, currentThread(), numArgs, argNames, argTypes, argValues);
 
     if (!isMainThread()) {
         MutexLocker locker(m_backgroundEventsMutex);
         m_backgroundEvents.append(event);
         return;
     }
+    (this->*(it->value))(event);
+}
 
-    processEvent(it->value, event);
+void TimelineTraceEventProcessor::onBeginFrame(const TraceEvent& event)
+{
+    flushRasterizerStatistics();
 }
 
-void TimelineTraceEventProcessor::processEvent(const EventTypeEntry& eventTypeEntry, const TraceEvent& event)
+void TimelineTraceEventProcessor::onPaintLayerBegin(const TraceEvent& event)
 {
-    TraceEventHandler handler = 0;
-    switch (event.phase()) {
-    case TracePhaseBegin:
-        handler = eventTypeEntry.m_begin;
-        break;
-    case TracePhaseEnd:
-        handler = eventTypeEntry.m_end;
-        break;
-    case TracePhaseInstant:
-        handler = eventTypeEntry.m_instant;
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    if (!handler) {
-        ASSERT_NOT_REACHED();
+    m_layerId = event.asUInt(InstrumentationEventArguments::LayerId);
+    ASSERT(m_layerId);
+}
+
+void TimelineTraceEventProcessor::onPaintLayerEnd(const TraceEvent&)
+{
+    m_layerId = 0;
+}
+
+void TimelineTraceEventProcessor::onRasterTaskBegin(const TraceEvent& event)
+{
+    unsigned long long layerId = event.asUInt(InstrumentationEventArguments::LayerId);
+    ThreadIdentifier threadIdentifier = event.threadIdentifier();
+    ASSERT(m_rasterStartTimeByThread.get(threadIdentifier) == HashTraits<double>::emptyValue());
+    double timestamp = m_knownLayers.contains(layerId) ? event.timestamp() : 0;
+    m_rasterStartTimeByThread.set(threadIdentifier, timestamp);
+}
+
+void TimelineTraceEventProcessor::onRasterTaskEnd(const TraceEvent& event)
+{
+    HashMap<ThreadIdentifier, double>::iterator it = m_rasterStartTimeByThread.find(event.threadIdentifier());
+    if (it == m_rasterStartTimeByThread.end())
         return;
+    double startTime = it->value;
+    double endTime = event.timestamp();
+    if (startTime == HashTraits<double>::emptyValue()) // Rasterizing unknown layer.
+        return;
+    m_frameRasterTime += endTime - startTime;
+    it->value = HashTraits<double>::emptyValue();
+    if (!m_firstRasterStartTime || m_firstRasterStartTime > startTime)
+        m_firstRasterStartTime = startTime;
+    m_lastRasterEndTime = endTime;
+}
+
+void TimelineTraceEventProcessor::onLayerDeleted(const TraceEvent& event)
+{
+    unsigned long long id = event.id();
+    ASSERT(id);
+    processBackgroundEvents();
+    m_knownLayers.remove(id);
+}
+
+void TimelineTraceEventProcessor::onPaint(const TraceEvent& event)
+{
+    if (!m_layerId)
+        return;
+
+    unsigned long long pageId = event.asUInt(InstrumentationEventArguments::PageId);
+    if (pageId == m_pageId)
+        m_knownLayers.add(m_layerId);
+}
+
+void TimelineTraceEventProcessor::flushRasterizerStatistics()
+{
+    processBackgroundEvents();
+    if (m_lastRasterEndTime) {
+        RefPtr<InspectorObject> data = TimelineRecordFactory::createRasterData(m_frameRasterTime, m_rasterStartTimeByThread.size());
+        sendTimelineRecord(data, TimelineRecordType::Rasterize, m_firstRasterStartTime, m_lastRasterEndTime, "multiple");
     }
-    (this->*handler)(event);
+    m_firstRasterStartTime = 0;
+    m_lastRasterEndTime = 0;
+    m_frameRasterTime = 0;
 }
 
 void TimelineTraceEventProcessor::sendTimelineRecord(PassRefPtr<InspectorObject> data, const String& recordType, double startTime, double endTime, const String& thread)
 {
+    ASSERT(isMainThread());
     InspectorTimelineAgent* timelineAgent = m_timelineAgent.get();
     if (!timelineAgent)
         return;
@@ -187,6 +258,7 @@ void TimelineTraceEventProcessor::sendTimelineRecord(PassRefPtr<InspectorObject>
 
 void TimelineTraceEventProcessor::processBackgroundEvents()
 {
+    ASSERT(isMainThread());
     Vector<TraceEvent> events;
     {
         MutexLocker locker(m_backgroundEventsMutex);
@@ -195,7 +267,9 @@ void TimelineTraceEventProcessor::processBackgroundEvents()
     }
     for (size_t i = 0, size = events.size(); i < size; ++i) {
         const TraceEvent& event = events[i];
-        processEvent(m_handlersByType.find(event.name())->value, event);
+        HandlersMap::iterator it = m_handlersByType.find(std::make_pair(event.name(), event.phase()));
+        ASSERT(it != m_handlersByType.end() && it->value);
+        (this->*(it->value))(event);
     }
 }
 
index ffcdcc8..54d6928 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (C) 2012 Google Inc. All rights reserved.
+* Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -55,16 +55,19 @@ public:
     enum TraceEventPhase {
         TracePhaseBegin = 'B',
         TracePhaseEnd = 'E',
-        TracePhaseInstant = 'I'
+        TracePhaseInstant = 'I',
+        TracePhaseCreateObject = 'N',
+        TracePhaseDeleteObject = 'D'
     };
 
     TimelineTraceEventProcessor(WeakPtr<InspectorTimelineAgent>, InspectorClient*);
     ~TimelineTraceEventProcessor();
 
+    void shutdown();
     void processEventOnAnyThread(TraceEventPhase, const char* name, unsigned long long id,
         int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues,
         unsigned char flags);
-    
+
 private:
     // FIXME: use the definition in TraceEvent.h once we expose the latter to all plaforms.
     union TraceValueUnion {
@@ -93,39 +96,51 @@ private:
         {
         }
 
-        TraceEvent(double timestamp, TraceEventPhase phase, const char* name, ThreadIdentifier threadIdentifier,
+        TraceEvent(double timestamp, TraceEventPhase phase, const char* name, unsigned long long id, ThreadIdentifier threadIdentifier,
             int argumentCount, const char* const* argumentNames, const unsigned char* argumentTypes, const unsigned long long* argumentValues)
             : m_timestamp(timestamp)
             , m_phase(phase)
             , m_name(name)
             , m_threadIdentifier(threadIdentifier)
             , m_argumentCount(argumentCount)
-            , m_argumentNames(argumentNames)
-            , m_argumentTypes(argumentTypes)
-            , m_argumentValues(argumentValues)
         {
+            if (m_argumentCount > MaxArguments) {
+                ASSERT_NOT_REACHED();
+                m_argumentCount = MaxArguments;
+            }
+            for (int i = 0; i < m_argumentCount; ++i) {
+                m_argumentNames[i] = argumentNames[i];
+                m_argumentTypes[i] = argumentTypes[i];
+                m_argumentValues[i] = argumentValues[i];
+            }
         }
 
         double timestamp() const { return m_timestamp; }
         TraceEventPhase phase() const { return m_phase; }
         const char* name() const { return m_name; }
+        unsigned long long id() const { return m_id; }
         ThreadIdentifier threadIdentifier() const { return m_threadIdentifier; }
         int argumentCount() const { return m_argumentCount; }
 
         bool asBool(const char* name) const
-        { 
+        {
             return parameter(name, TypeBool).m_bool;
         }
         long long asInt(const char* name) const
-        { 
-            return parameter(name, TypeInt).m_int;
+        {
+            size_t index = findParameter(name);
+            if (index == notFound || (m_argumentTypes[index] != TypeInt && m_argumentTypes[index] != TypeUInt)) {
+                ASSERT_NOT_REACHED();
+                return 0;
+            }
+            return reinterpret_cast<const TraceValueUnion*>(m_argumentValues + index)->m_int;
         }
-        unsigned long long asUInt(const char* name) const 
-        { 
-            return parameter(name, TypeUInt).m_uint;
+        unsigned long long asUInt(const char* name) const
+        {
+            return asInt(name);
         }
         double asDouble(const char* name) const
-        { 
+        {
             return parameter(name, TypeDouble).m_double;
         }
         const char* asString(const char* name) const
@@ -134,58 +149,57 @@ private:
         }
 
     private:
+        enum { MaxArguments = 2 };
+
+        size_t findParameter(const char*) const;
         const TraceValueUnion& parameter(const char* name, TraceValueTypes expectedType) const;
 
         double m_timestamp;
         TraceEventPhase m_phase;
         const char* m_name;
+        unsigned long long m_id;
         ThreadIdentifier m_threadIdentifier;
         int m_argumentCount;
-        const char* const* m_argumentNames;
-        const unsigned char* m_argumentTypes;
-        const unsigned long long* m_argumentValues;
+        const char* m_argumentNames[MaxArguments];
+        unsigned char m_argumentTypes[MaxArguments];
+        unsigned long long m_argumentValues[MaxArguments];
     };
 
     typedef void (TimelineTraceEventProcessor::*TraceEventHandler)(const TraceEvent&);
 
-    struct EventTypeEntry {
-        EventTypeEntry()
-            : m_begin(0)
-            , m_end(0)
-            , m_instant(0)
-        {
-        }
-        explicit EventTypeEntry(TraceEventHandler instant)
-            : m_begin(0)
-            , m_end(0)
-            , m_instant(instant)
-        {
-        }
-        EventTypeEntry(TraceEventHandler begin, TraceEventHandler end)
-            : m_begin(begin)
-            , m_end(end)
-            , m_instant(0)
-        {
-        }
+    void processBackgroundEvents();
+    void sendTimelineRecord(PassRefPtr<InspectorObject> data, const String& recordType, double startTime, double endTime, const String& Thread);
 
-        TraceEventHandler m_begin;
-        TraceEventHandler m_end;
-        TraceEventHandler m_instant;
-    };
+    void onBeginFrame(const TraceEvent&);
+    void onPaintLayerBegin(const TraceEvent&);
+    void onPaintLayerEnd(const TraceEvent&);
+    void onRasterTaskBegin(const TraceEvent&);
+    void onRasterTaskEnd(const TraceEvent&);
+    void onLayerDeleted(const TraceEvent&);
+    void onPaint(const TraceEvent&);
 
-    void processBackgroundEvents();
-    void sendTimelineRecord(PassRefPtr<InspectorObject> data, const String& recordType, double startTime, double endTime, const String& thread);
-    void processEvent(const EventTypeEntry&, const TraceEvent&);
+    void flushRasterizerStatistics();
+
+    void registerHandler(const char* name, TraceEventPhase, TraceEventHandler);
 
     WeakPtr<InspectorTimelineAgent> m_timelineAgent;
     InspectorClient* m_inspectorClient;
 
-    HashMap<String, EventTypeEntry> m_handlersByType;
+    typedef HashMap<std::pair<String, int>, TraceEventHandler> HandlersMap;
+    HandlersMap m_handlersByType;
     Mutex m_backgroundEventsMutex;
     Vector<TraceEvent> m_backgroundEvents;
     unsigned long long m_pageId;
-};
 
+    HashSet<unsigned long long> m_knownLayers;
+    HashMap<ThreadIdentifier, double> m_rasterStartTimeByThread;
+    double m_firstRasterStartTime;
+    double m_lastRasterEndTime;
+    double m_frameRasterTime;
+    double m_frameRasterPixels;
+
+    unsigned long long m_layerId;
+};
 
 } // namespace WebCore
 
index 6dad21d..3e5ade1 100644 (file)
@@ -56,6 +56,7 @@ WebInspector.TimelineModel.RecordType = {
     InvalidateLayout: "InvalidateLayout",
     Layout: "Layout",
     Paint: "Paint",
+    Rasterize: "Rasterize",
     ScrollLayer: "ScrollLayer",
     DecodeImage: "DecodeImage",
     ResizeImage: "ResizeImage",
index 7ff42d7..25e8932 100644 (file)
@@ -76,6 +76,7 @@ WebInspector.TimelinePresentationModel._initRecordStyles = function()
     recordStyles[recordTypes.InvalidateLayout] = { title: WebInspector.UIString("Invalidate Layout"), category: categories["rendering"] };
     recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: categories["rendering"] };
     recordStyles[recordTypes.Paint] = { title: WebInspector.UIString("Paint"), category: categories["painting"] };
+    recordStyles[recordTypes.Rasterize] = { title: WebInspector.UIString("Rasterize"), category: categories["painting"] };
     recordStyles[recordTypes.ScrollLayer] = { title: WebInspector.UIString("Scroll"), category: categories["painting"] };
     recordStyles[recordTypes.DecodeImage] = { title: WebInspector.UIString("Image Decode"), category: categories["painting"] };
     recordStyles[recordTypes.ResizeImage] = { title: WebInspector.UIString("Image Resize"), category: categories["painting"] };