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