| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <cstdlib> | 5 #include <cstdlib> |
| 6 | 6 |
| 7 #include "vm/atomic.h" | 7 #include "vm/atomic.h" |
| 8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
| 9 #include "vm/json_stream.h" | 9 #include "vm/json_stream.h" |
| 10 #include "vm/lockers.h" | 10 #include "vm/lockers.h" |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 const bool use_ring_recorder = true; | 131 const bool use_ring_recorder = true; |
| 132 // Some flags require that we use the endless recorder. | 132 // Some flags require that we use the endless recorder. |
| 133 const bool use_endless_recorder = | 133 const bool use_endless_recorder = |
| 134 (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline; | 134 (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline; |
| 135 if (use_endless_recorder) { | 135 if (use_endless_recorder) { |
| 136 recorder_ = new TimelineEventEndlessRecorder(); | 136 recorder_ = new TimelineEventEndlessRecorder(); |
| 137 } else if (use_ring_recorder) { | 137 } else if (use_ring_recorder) { |
| 138 recorder_ = new TimelineEventRingRecorder(); | 138 recorder_ = new TimelineEventRingRecorder(); |
| 139 } | 139 } |
| 140 enabled_streams_ = GetEnabledByDefaultTimelineStreams(); | 140 enabled_streams_ = GetEnabledByDefaultTimelineStreams(); |
| 141 vm_stream_.Init("VM", HasStream(enabled_streams_, "VM"), NULL); | |
| 142 vm_api_stream_.Init("API", | |
| 143 HasStream(enabled_streams_, "API"), | |
| 144 &stream_API_enabled_); | |
| 145 // Global overrides. | 141 // Global overrides. |
| 146 #define ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \ | 142 #define TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \ |
| 147 stream_##name##_enabled_ = HasStream(enabled_streams_, #name); | 143 stream_##name##_enabled_ = HasStream(enabled_streams_, #name); \ |
| 148 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT) | 144 stream_##name##_.Init(#name, \ |
| 149 #undef ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT | 145 stream_##name##_enabled_, \ |
| 146 &stream_##name##_enabled_); |
| 147 TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAG_DEFAULT) |
| 148 #undef TIMELINE_STREAM_FLAG_DEFAULT |
| 150 } | 149 } |
| 151 | 150 |
| 152 | 151 |
| 153 void Timeline::SetVMStreamEnabled(bool enabled) { | |
| 154 vm_stream_.set_enabled(enabled); | |
| 155 } | |
| 156 | |
| 157 | |
| 158 void Timeline::StreamStateChange(const char* stream_name, | 152 void Timeline::StreamStateChange(const char* stream_name, |
| 159 bool prev, | 153 bool prev, |
| 160 bool curr) { | 154 bool curr) { |
| 161 if (prev == curr) { | 155 if (prev == curr) { |
| 162 return; | 156 return; |
| 163 } | 157 } |
| 164 if (strcmp(stream_name, "Embedder") == 0) { | 158 if (strcmp(stream_name, "Embedder") == 0) { |
| 165 if (curr && (Timeline::get_start_recording_cb() != NULL)) { | 159 if (curr && (Timeline::get_start_recording_cb() != NULL)) { |
| 166 Timeline::get_start_recording_cb()(); | 160 Timeline::get_start_recording_cb()(); |
| 167 } else if (!curr && (Timeline::get_stop_recording_cb() != NULL)) { | 161 } else if (!curr && (Timeline::get_stop_recording_cb() != NULL)) { |
| 168 Timeline::get_stop_recording_cb()(); | 162 Timeline::get_stop_recording_cb()(); |
| 169 } | 163 } |
| 170 } | 164 } |
| 171 } | 165 } |
| 172 | 166 |
| 173 | 167 |
| 174 void Timeline::Shutdown() { | 168 void Timeline::Shutdown() { |
| 175 ASSERT(recorder_ != NULL); | 169 ASSERT(recorder_ != NULL); |
| 176 if (FLAG_timeline_dir != NULL) { | 170 if (FLAG_timeline_dir != NULL) { |
| 177 recorder_->WriteTo(FLAG_timeline_dir); | 171 recorder_->WriteTo(FLAG_timeline_dir); |
| 178 } | 172 } |
| 179 // Disable global streams. | 173 // Disable global streams. |
| 180 vm_stream_.set_enabled(false); | 174 #define TIMELINE_STREAM_DISABLE(name, not_used) \ |
| 181 vm_api_stream_.set_enabled(false); | |
| 182 #define ISOLATE_TIMELINE_STREAM_DISABLE(name, not_used) \ | |
| 183 stream_##name##_enabled_ = false; | 175 stream_##name##_enabled_ = false; |
| 184 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DISABLE) | 176 TIMELINE_STREAM_LIST(TIMELINE_STREAM_DISABLE) |
| 185 #undef ISOLATE_TIMELINE_STREAM_DISABLE | 177 #undef TIMELINE_STREAM_DISABLE |
| 186 delete recorder_; | 178 delete recorder_; |
| 187 recorder_ = NULL; | 179 recorder_ = NULL; |
| 188 if (enabled_streams_ != NULL) { | 180 if (enabled_streams_ != NULL) { |
| 189 FreeEnabledByDefaultTimelineStreams(enabled_streams_); | 181 FreeEnabledByDefaultTimelineStreams(enabled_streams_); |
| 190 enabled_streams_ = NULL; | 182 enabled_streams_ = NULL; |
| 191 } | 183 } |
| 192 } | 184 } |
| 193 | 185 |
| 194 | 186 |
| 195 TimelineEventRecorder* Timeline::recorder() { | 187 TimelineEventRecorder* Timeline::recorder() { |
| 196 return recorder_; | 188 return recorder_; |
| 197 } | 189 } |
| 198 | 190 |
| 199 | 191 |
| 200 void Timeline::SetupIsolateStreams(Isolate* isolate) { | |
| 201 if (!FLAG_support_timeline) { | |
| 202 return; | |
| 203 } | |
| 204 #define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default) \ | |
| 205 isolate->Get##name##Stream()->Init( \ | |
| 206 #name, \ | |
| 207 (enabled_by_default || HasStream(enabled_streams_, #name)), \ | |
| 208 Timeline::Stream##name##EnabledFlag()); | |
| 209 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT); | |
| 210 #undef ISOLATE_TIMELINE_STREAM_INIT | |
| 211 } | |
| 212 | |
| 213 | |
| 214 TimelineStream* Timeline::GetVMStream() { | |
| 215 return &vm_stream_; | |
| 216 } | |
| 217 | |
| 218 | |
| 219 TimelineStream* Timeline::GetVMApiStream() { | |
| 220 return &vm_api_stream_; | |
| 221 } | |
| 222 | |
| 223 | |
| 224 void Timeline::ReclaimCachedBlocksFromThreads() { | 192 void Timeline::ReclaimCachedBlocksFromThreads() { |
| 225 TimelineEventRecorder* recorder = Timeline::recorder(); | 193 TimelineEventRecorder* recorder = Timeline::recorder(); |
| 226 if (recorder == NULL) { | 194 if (recorder == NULL) { |
| 227 return; | 195 return; |
| 228 } | 196 } |
| 229 | 197 |
| 230 // Iterate over threads. | 198 // Iterate over threads. |
| 231 OSThreadIterator it; | 199 OSThreadIterator it; |
| 232 while (it.HasNext()) { | 200 while (it.HasNext()) { |
| 233 OSThread* thread = it.Next(); | 201 OSThread* thread = it.Next(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 249 TimelineEventRecorder* recorder = Timeline::recorder(); | 217 TimelineEventRecorder* recorder = Timeline::recorder(); |
| 250 if (recorder == NULL) { | 218 if (recorder == NULL) { |
| 251 obj.AddProperty("recorderName", "null"); | 219 obj.AddProperty("recorderName", "null"); |
| 252 } else { | 220 } else { |
| 253 obj.AddProperty("recorderName", recorder->name()); | 221 obj.AddProperty("recorderName", recorder->name()); |
| 254 } | 222 } |
| 255 { | 223 { |
| 256 JSONArray availableStreams(&obj, "availableStreams"); | 224 JSONArray availableStreams(&obj, "availableStreams"); |
| 257 #define ADD_STREAM_NAME(name, not_used) \ | 225 #define ADD_STREAM_NAME(name, not_used) \ |
| 258 availableStreams.AddValue(#name); | 226 availableStreams.AddValue(#name); |
| 259 ISOLATE_TIMELINE_STREAM_LIST(ADD_STREAM_NAME); | 227 TIMELINE_STREAM_LIST(ADD_STREAM_NAME); |
| 260 #undef ADD_STREAM_NAME | 228 #undef ADD_STREAM_NAME |
| 261 availableStreams.AddValue("VM"); | |
| 262 } | 229 } |
| 263 { | 230 { |
| 264 JSONArray recordedStreams(&obj, "recordedStreams"); | 231 JSONArray recordedStreams(&obj, "recordedStreams"); |
| 265 #define ADD_RECORDED_STREAM_NAME(name, not_used) \ | 232 #define ADD_RECORDED_STREAM_NAME(name, not_used) \ |
| 266 if (stream_##name##_enabled_) { \ | 233 if (stream_##name##_enabled_) { \ |
| 267 recordedStreams.AddValue(#name); \ | 234 recordedStreams.AddValue(#name); \ |
| 268 } | 235 } |
| 269 ISOLATE_TIMELINE_STREAM_LIST(ADD_RECORDED_STREAM_NAME); | 236 TIMELINE_STREAM_LIST(ADD_RECORDED_STREAM_NAME); |
| 270 #undef ADD_RECORDED_STREAM_NAME | 237 #undef ADD_RECORDED_STREAM_NAME |
| 271 if (vm_stream_.enabled()) { | |
| 272 recordedStreams.AddValue("VM"); | |
| 273 } | |
| 274 } | 238 } |
| 275 } | 239 } |
| 276 | 240 |
| 277 | 241 |
| 278 void Timeline::Clear() { | 242 void Timeline::Clear() { |
| 279 TimelineEventRecorder* recorder = Timeline::recorder(); | 243 TimelineEventRecorder* recorder = Timeline::recorder(); |
| 280 if (recorder == NULL) { | 244 if (recorder == NULL) { |
| 281 return; | 245 return; |
| 282 } | 246 } |
| 283 ReclaimCachedBlocksFromThreads(); | 247 ReclaimCachedBlocksFromThreads(); |
| 284 recorder->Clear(); | 248 recorder->Clear(); |
| 285 } | 249 } |
| 286 | 250 |
| 287 | 251 |
| 288 TimelineEventRecorder* Timeline::recorder_ = NULL; | 252 TimelineEventRecorder* Timeline::recorder_ = NULL; |
| 289 TimelineStream Timeline::vm_stream_; | |
| 290 TimelineStream Timeline::vm_api_stream_; | |
| 291 MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL; | 253 MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL; |
| 292 Dart_EmbedderTimelineStartRecording Timeline::start_recording_cb_ = NULL; | 254 Dart_EmbedderTimelineStartRecording Timeline::start_recording_cb_ = NULL; |
| 293 Dart_EmbedderTimelineStopRecording Timeline::stop_recording_cb_ = NULL; | 255 Dart_EmbedderTimelineStopRecording Timeline::stop_recording_cb_ = NULL; |
| 294 Dart_EmbedderTimelineGetTimeline Timeline::get_timeline_cb_ = NULL; | |
| 295 | 256 |
| 296 #define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default) \ | 257 #define TIMELINE_STREAM_DEFINE(name, enabled_by_default) \ |
| 297 bool Timeline::stream_##name##_enabled_ = enabled_by_default; | 258 bool Timeline::stream_##name##_enabled_ = enabled_by_default; \ |
| 298 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DEFINE_FLAG) | 259 TimelineStream Timeline::stream_##name##_; |
| 299 #undef ISOLATE_TIMELINE_STREAM_DEFINE_FLAG | 260 TIMELINE_STREAM_LIST(TIMELINE_STREAM_DEFINE) |
| 261 #undef TIMELINE_STREAM_DEFINE |
| 300 | 262 |
| 301 TimelineEvent::TimelineEvent() | 263 TimelineEvent::TimelineEvent() |
| 302 : timestamp0_(0), | 264 : timestamp0_(0), |
| 303 timestamp1_(0), | 265 timestamp1_(0), |
| 304 arguments_(NULL), | 266 arguments_(NULL), |
| 305 arguments_length_(0), | 267 arguments_length_(0), |
| 306 state_(0), | 268 state_(0), |
| 307 label_(NULL), | 269 label_(NULL), |
| 308 category_(""), | 270 category_(""), |
| 309 thread_(OSThread::kInvalidThreadId), | 271 thread_(OSThread::kInvalidThreadId), |
| (...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 #if defined(DEBUG) | 982 #if defined(DEBUG) |
| 1021 Thread* T = Thread::Current(); | 983 Thread* T = Thread::Current(); |
| 1022 if (T != NULL) { | 984 if (T != NULL) { |
| 1023 T->DecrementNoSafepointScopeDepth(); | 985 T->DecrementNoSafepointScopeDepth(); |
| 1024 } | 986 } |
| 1025 #endif // defined(DEBUG) | 987 #endif // defined(DEBUG) |
| 1026 thread_block_lock->Unlock(); | 988 thread_block_lock->Unlock(); |
| 1027 } | 989 } |
| 1028 | 990 |
| 1029 | 991 |
| 1030 void TimelineEventRecorder::PrintEmbedderJSONEvents(JSONStream* events) { | |
| 1031 if (Timeline::get_get_timeline_cb() != NULL) { | |
| 1032 events->PrintCommaIfNeeded(); | |
| 1033 Timeline::get_get_timeline_cb()(AppendJSONStreamConsumer, events); | |
| 1034 } | |
| 1035 } | |
| 1036 | |
| 1037 | |
| 1038 void TimelineEventRecorder::WriteTo(const char* directory) { | 992 void TimelineEventRecorder::WriteTo(const char* directory) { |
| 1039 if (!FLAG_support_service) { | 993 if (!FLAG_support_service) { |
| 1040 return; | 994 return; |
| 1041 } | 995 } |
| 1042 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | 996 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
| 1043 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | 997 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
| 1044 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | 998 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
| 1045 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { | 999 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { |
| 1046 return; | 1000 return; |
| 1047 } | 1001 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1167 TimelineEventFilter* filter) { | 1121 TimelineEventFilter* filter) { |
| 1168 if (!FLAG_support_service) { | 1122 if (!FLAG_support_service) { |
| 1169 return; | 1123 return; |
| 1170 } | 1124 } |
| 1171 JSONObject topLevel(js); | 1125 JSONObject topLevel(js); |
| 1172 topLevel.AddProperty("type", "_Timeline"); | 1126 topLevel.AddProperty("type", "_Timeline"); |
| 1173 { | 1127 { |
| 1174 JSONArray events(&topLevel, "traceEvents"); | 1128 JSONArray events(&topLevel, "traceEvents"); |
| 1175 PrintJSONMeta(&events); | 1129 PrintJSONMeta(&events); |
| 1176 PrintJSONEvents(&events, filter); | 1130 PrintJSONEvents(&events, filter); |
| 1177 PrintEmbedderJSONEvents(js); | |
| 1178 } | 1131 } |
| 1179 } | 1132 } |
| 1180 | 1133 |
| 1181 | 1134 |
| 1182 void TimelineEventRingRecorder::PrintTraceEvent(JSONStream* js, | 1135 void TimelineEventRingRecorder::PrintTraceEvent(JSONStream* js, |
| 1183 TimelineEventFilter* filter) { | 1136 TimelineEventFilter* filter) { |
| 1184 if (!FLAG_support_service) { | 1137 if (!FLAG_support_service) { |
| 1185 return; | 1138 return; |
| 1186 } | 1139 } |
| 1187 JSONArray events(js); | 1140 JSONArray events(js); |
| 1188 PrintJSONEvents(&events, filter); | 1141 PrintJSONEvents(&events, filter); |
| 1189 PrintEmbedderJSONEvents(js); | |
| 1190 } | 1142 } |
| 1191 | 1143 |
| 1192 | 1144 |
| 1193 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlockLocked() { | 1145 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlockLocked() { |
| 1194 return blocks_[0]; | 1146 return blocks_[0]; |
| 1195 } | 1147 } |
| 1196 | 1148 |
| 1197 | 1149 |
| 1198 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() { | 1150 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() { |
| 1199 // TODO(johnmccutchan): This function should only hand out blocks | 1151 // TODO(johnmccutchan): This function should only hand out blocks |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 TimelineEventFilter* filter) { | 1254 TimelineEventFilter* filter) { |
| 1303 if (!FLAG_support_service) { | 1255 if (!FLAG_support_service) { |
| 1304 return; | 1256 return; |
| 1305 } | 1257 } |
| 1306 JSONObject topLevel(js); | 1258 JSONObject topLevel(js); |
| 1307 topLevel.AddProperty("type", "_Timeline"); | 1259 topLevel.AddProperty("type", "_Timeline"); |
| 1308 { | 1260 { |
| 1309 JSONArray events(&topLevel, "traceEvents"); | 1261 JSONArray events(&topLevel, "traceEvents"); |
| 1310 PrintJSONMeta(&events); | 1262 PrintJSONMeta(&events); |
| 1311 PrintJSONEvents(&events, filter); | 1263 PrintJSONEvents(&events, filter); |
| 1312 PrintEmbedderJSONEvents(js); | |
| 1313 } | 1264 } |
| 1314 } | 1265 } |
| 1315 | 1266 |
| 1316 | 1267 |
| 1317 void TimelineEventEndlessRecorder::PrintTraceEvent( | 1268 void TimelineEventEndlessRecorder::PrintTraceEvent( |
| 1318 JSONStream* js, | 1269 JSONStream* js, |
| 1319 TimelineEventFilter* filter) { | 1270 TimelineEventFilter* filter) { |
| 1320 if (!FLAG_support_service) { | 1271 if (!FLAG_support_service) { |
| 1321 return; | 1272 return; |
| 1322 } | 1273 } |
| 1323 JSONArray events(js); | 1274 JSONArray events(js); |
| 1324 PrintJSONEvents(&events, filter); | 1275 PrintJSONEvents(&events, filter); |
| 1325 PrintEmbedderJSONEvents(js); | |
| 1326 } | 1276 } |
| 1327 | 1277 |
| 1328 | 1278 |
| 1329 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() { | 1279 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() { |
| 1330 return head_; | 1280 return head_; |
| 1331 } | 1281 } |
| 1332 | 1282 |
| 1333 | 1283 |
| 1334 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { | 1284 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { |
| 1335 return ThreadBlockStartEvent(); | 1285 return ThreadBlockStartEvent(); |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1554 TimelineEventBlock* TimelineEventBlockIterator::Next() { | 1504 TimelineEventBlock* TimelineEventBlockIterator::Next() { |
| 1555 ASSERT(current_ != NULL); | 1505 ASSERT(current_ != NULL); |
| 1556 TimelineEventBlock* r = current_; | 1506 TimelineEventBlock* r = current_; |
| 1557 current_ = current_->next(); | 1507 current_ = current_->next(); |
| 1558 return r; | 1508 return r; |
| 1559 } | 1509 } |
| 1560 | 1510 |
| 1561 #endif // !PRODUCT | 1511 #endif // !PRODUCT |
| 1562 | 1512 |
| 1563 } // namespace dart | 1513 } // namespace dart |
| OLD | NEW |