Home | History | Annotate | Download | only in inspector
      1 /*
      2 * Copyright (C) 2013 Google Inc. All rights reserved.
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions are
      6 * met:
      7 *
      8 *     * Redistributions of source code must retain the above copyright
      9 * notice, this list of conditions and the following disclaimer.
     10 *     * Redistributions in binary form must reproduce the above
     11 * copyright notice, this list of conditions and the following disclaimer
     12 * in the documentation and/or other materials provided with the
     13 * distribution.
     14 *     * Neither the name of Google Inc. nor the names of its
     15 * contributors may be used to endorse or promote products derived from
     16 * this software without specific prior written permission.
     17 *
     18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 */
     30 
     31 #ifndef TimelineTraceEventProcessor_h
     32 #define TimelineTraceEventProcessor_h
     33 
     34 
     35 #include "core/inspector/InspectorTimelineAgent.h"
     36 #include "core/platform/JSONValues.h"
     37 #include "wtf/HashMap.h"
     38 #include "wtf/Threading.h"
     39 #include "wtf/Vector.h"
     40 #include "wtf/WeakPtr.h"
     41 #include "wtf/text/WTFString.h"
     42 
     43 namespace WebCore {
     44 
     45 class InspectorClient;
     46 class InspectorTimelineAgent;
     47 class Page;
     48 
     49 class TimelineRecordStack {
     50 private:
     51     struct Entry {
     52         Entry(PassRefPtr<JSONObject> record)
     53             : record(record)
     54             , children(JSONArray::create())
     55         {
     56         }
     57 
     58         RefPtr<JSONObject> record;
     59         RefPtr<JSONArray> children;
     60     };
     61 
     62 public:
     63     TimelineRecordStack() { }
     64     TimelineRecordStack(WeakPtr<InspectorTimelineAgent>);
     65 
     66     void addScopedRecord(PassRefPtr<JSONObject> record);
     67     void closeScopedRecord(double endTime);
     68     void addInstantRecord(PassRefPtr<JSONObject> record);
     69 
     70 #ifndef NDEBUG
     71     bool isOpenRecordOfType(const String& type);
     72 #endif
     73 
     74 private:
     75     void send(PassRefPtr<JSONObject>);
     76 
     77     WeakPtr<InspectorTimelineAgent> m_timelineAgent;
     78     Vector<Entry> m_stack;
     79 };
     80 
     81 class TimelineTraceEventProcessor : public ThreadSafeRefCounted<TimelineTraceEventProcessor> {
     82 public:
     83     // FIXME: re-use definitions in TraceEvent.h once it's promoted to all platforms.
     84     enum TraceEventPhase {
     85         TracePhaseBegin = 'B',
     86         TracePhaseEnd = 'E',
     87         TracePhaseInstant = 'I',
     88         TracePhaseCreateObject = 'N',
     89         TracePhaseDeleteObject = 'D'
     90     };
     91 
     92     TimelineTraceEventProcessor(WeakPtr<InspectorTimelineAgent>, InspectorClient*);
     93     ~TimelineTraceEventProcessor();
     94 
     95     void shutdown();
     96     void processEventOnAnyThread(TraceEventPhase, const char* name, unsigned long long id,
     97         int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues,
     98         unsigned char flags);
     99 
    100 private:
    101     // FIXME: use the definition in TraceEvent.h once we expose the latter to all plaforms.
    102     union TraceValueUnion {
    103         bool m_bool;
    104         unsigned long long m_uint;
    105         long long m_int;
    106         double m_double;
    107         const void* m_pointer;
    108         const char* m_string;
    109     };
    110 
    111     enum TraceValueTypes {
    112         TypeBool = 1,
    113         TypeUInt = 2,
    114         TypeInt = 3,
    115         TypeDouble = 4,
    116         TypePointer = 5,
    117         TypeString = 6,
    118         TypeCopyString = 7
    119     };
    120 
    121     struct TimelineThreadState {
    122         TimelineThreadState() { }
    123 
    124         TimelineThreadState(WeakPtr<InspectorTimelineAgent> timelineAgent)
    125             : recordStack(timelineAgent)
    126             , inKnownLayerTask(false)
    127         {
    128         }
    129 
    130         TimelineRecordStack recordStack;
    131         bool inKnownLayerTask;
    132     };
    133 
    134     class TraceEvent {
    135     public:
    136         TraceEvent()
    137             : m_name(0)
    138             , m_argumentCount(0)
    139         {
    140         }
    141 
    142         TraceEvent(double timestamp, TraceEventPhase phase, const char* name, unsigned long long id, ThreadIdentifier threadIdentifier,
    143             int argumentCount, const char* const* argumentNames, const unsigned char* argumentTypes, const unsigned long long* argumentValues)
    144             : m_timestamp(timestamp)
    145             , m_phase(phase)
    146             , m_name(name)
    147             , m_id(id)
    148             , m_threadIdentifier(threadIdentifier)
    149             , m_argumentCount(argumentCount)
    150         {
    151             if (m_argumentCount > MaxArguments) {
    152                 ASSERT_NOT_REACHED();
    153                 m_argumentCount = MaxArguments;
    154             }
    155             for (int i = 0; i < m_argumentCount; ++i) {
    156                 m_argumentNames[i] = argumentNames[i];
    157                 m_argumentTypes[i] = argumentTypes[i];
    158                 m_argumentValues[i] = argumentValues[i];
    159             }
    160         }
    161 
    162         double timestamp() const { return m_timestamp; }
    163         TraceEventPhase phase() const { return m_phase; }
    164         const char* name() const { return m_name; }
    165         unsigned long long id() const { return m_id; }
    166         ThreadIdentifier threadIdentifier() const { return m_threadIdentifier; }
    167         int argumentCount() const { return m_argumentCount; }
    168         bool isNull() const { return !m_name; }
    169 
    170         bool asBool(const char* name) const
    171         {
    172             return parameter(name, TypeBool).m_bool;
    173         }
    174         long long asInt(const char* name) const
    175         {
    176             size_t index = findParameter(name);
    177             if (index == notFound || (m_argumentTypes[index] != TypeInt && m_argumentTypes[index] != TypeUInt)) {
    178                 ASSERT_NOT_REACHED();
    179                 return 0;
    180             }
    181             return reinterpret_cast<const TraceValueUnion*>(m_argumentValues + index)->m_int;
    182         }
    183         unsigned long long asUInt(const char* name) const
    184         {
    185             return asInt(name);
    186         }
    187         double asDouble(const char* name) const
    188         {
    189             return parameter(name, TypeDouble).m_double;
    190         }
    191         const char* asString(const char* name) const
    192         {
    193             return parameter(name, TypeString).m_string;
    194         }
    195 
    196     private:
    197         enum { MaxArguments = 2 };
    198 
    199         size_t findParameter(const char*) const;
    200         const TraceValueUnion& parameter(const char* name, TraceValueTypes expectedType) const;
    201 
    202         double m_timestamp;
    203         TraceEventPhase m_phase;
    204         const char* m_name;
    205         unsigned long long m_id;
    206         ThreadIdentifier m_threadIdentifier;
    207         int m_argumentCount;
    208         const char* m_argumentNames[MaxArguments];
    209         unsigned char m_argumentTypes[MaxArguments];
    210         unsigned long long m_argumentValues[MaxArguments];
    211     };
    212 
    213     typedef void (TimelineTraceEventProcessor::*TraceEventHandler)(const TraceEvent&);
    214 
    215     TimelineThreadState& threadState(ThreadIdentifier thread)
    216     {
    217         ThreadStateMap::iterator it = m_threadStates.find(thread);
    218         if (it != m_threadStates.end())
    219             return it->value;
    220         return m_threadStates.add(thread, TimelineThreadState(m_timelineAgent)).iterator->value;
    221     }
    222     bool maybeEnterLayerTask(const TraceEvent&, TimelineThreadState&);
    223     void leaveLayerTask(TimelineThreadState&);
    224 
    225     void processBackgroundEvents();
    226     PassRefPtr<JSONObject> createRecord(const TraceEvent&, const String& recordType, PassRefPtr<JSONObject> data = 0);
    227 
    228     void registerHandler(const char* name, TraceEventPhase, TraceEventHandler);
    229 
    230     void onBeginFrame(const TraceEvent&);
    231     void onUpdateLayerBegin(const TraceEvent&);
    232     void onUpdateLayerEnd(const TraceEvent&);
    233     void onPaintLayerBegin(const TraceEvent&);
    234     void onPaintLayerEnd(const TraceEvent&);
    235     void onPaintSetupBegin(const TraceEvent&);
    236     void onPaintSetupEnd(const TraceEvent&);
    237     void onRasterTaskBegin(const TraceEvent&);
    238     void onRasterTaskEnd(const TraceEvent&);
    239     void onPaint(const TraceEvent&);
    240     void onImageDecodeTaskBegin(const TraceEvent&);
    241     void onImageDecodeTaskEnd(const TraceEvent&);
    242     void onImageDecodeBegin(const TraceEvent&);
    243     void onImageDecodeEnd(const TraceEvent&);
    244     void onLayerDeleted(const TraceEvent&);
    245 
    246     WeakPtr<InspectorTimelineAgent> m_timelineAgent;
    247     TimelineTimeConverter m_timeConverter;
    248     InspectorClient* m_inspectorClient;
    249     unsigned long long m_pageId;
    250     int m_layerTreeId;
    251 
    252     typedef HashMap<std::pair<String, int>, TraceEventHandler> HandlersMap;
    253     HandlersMap m_handlersByType;
    254     Mutex m_backgroundEventsMutex;
    255     Vector<TraceEvent> m_backgroundEvents;
    256 
    257     typedef HashMap<ThreadIdentifier, TimelineThreadState> ThreadStateMap;
    258     ThreadStateMap m_threadStates;
    259 
    260     HashMap<unsigned long long, long long> m_layerToNodeMap;
    261     unsigned long long m_layerId;
    262     double m_paintSetupStart;
    263     double m_paintSetupEnd;
    264 };
    265 
    266 } // namespace WebCore
    267 
    268 #endif // !defined(TimelineTraceEventProcessor_h)
    269