OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 #include "vm/json_stream.h" |
| 6 #include "vm/os.h" |
| 7 #include "vm/trace_buffer.h" |
| 8 |
| 9 namespace dart { |
| 10 |
| 11 TraceBuffer::TraceBuffer(intptr_t capacity) : ring_capacity_(capacity) { |
| 12 ring_cursor_ = 0; |
| 13 Init(); |
| 14 } |
| 15 |
| 16 |
| 17 TraceBuffer::~TraceBuffer() { |
| 18 ASSERT(ring_ != NULL); |
| 19 Clear(); |
| 20 free(ring_); |
| 21 } |
| 22 |
| 23 |
| 24 void TraceBuffer::Init() { |
| 25 ring_ = reinterpret_cast<TraceBufferEntry*>( |
| 26 calloc(ring_capacity_, sizeof(TraceBufferEntry))); // NOLINT |
| 27 } |
| 28 |
| 29 |
| 30 void TraceBuffer::Clear() { |
| 31 for (intptr_t i = 0; i < ring_capacity_; i++) { |
| 32 TraceBufferEntry& entry = ring_[i]; |
| 33 entry.micros = 0; |
| 34 free(entry.message); |
| 35 entry.message = NULL; |
| 36 } |
| 37 ring_cursor_ = 0; |
| 38 } |
| 39 |
| 40 |
| 41 void TraceBuffer::Fill(TraceBufferEntry* entry, int64_t micros, char* msg) { |
| 42 if (entry->message != NULL) { |
| 43 // Recycle TraceBufferEntry. |
| 44 free(entry->message); |
| 45 } |
| 46 entry->message = msg; |
| 47 entry->micros = micros; |
| 48 } |
| 49 |
| 50 |
| 51 void TraceBuffer::AppendTrace(int64_t micros, char* message) { |
| 52 const intptr_t index = ring_cursor_; |
| 53 TraceBufferEntry* trace_entry = &ring_[index]; |
| 54 Fill(trace_entry, micros, message); |
| 55 ring_cursor_ = RingIndex(ring_cursor_ + 1); |
| 56 } |
| 57 |
| 58 |
| 59 void TraceBuffer::Trace(int64_t micros, const char* message) { |
| 60 ASSERT(message != NULL); |
| 61 char* message_copy = strdup(message); |
| 62 AppendTrace(micros, message_copy); |
| 63 } |
| 64 |
| 65 |
| 66 void TraceBuffer::Trace(const char* message) { |
| 67 Trace(OS::GetCurrentTimeMicros(), message); |
| 68 } |
| 69 |
| 70 |
| 71 void TraceBuffer::TraceF(const char* format, ...) { |
| 72 int64_t micros = OS::GetCurrentTimeMicros(); |
| 73 va_list args; |
| 74 va_start(args, format); |
| 75 intptr_t len = OS::VSNPrint(NULL, 0, format, args); |
| 76 va_end(args); |
| 77 char* p = reinterpret_cast<char*>(malloc(len+1)); |
| 78 va_start(args, format); |
| 79 intptr_t len2 = OS::VSNPrint(p, len+1, format, args); |
| 80 va_end(args); |
| 81 ASSERT(len == len2); |
| 82 AppendTrace(micros, p); |
| 83 } |
| 84 |
| 85 |
| 86 void TraceBuffer::PrintToJSONStream(JSONStream* stream) const { |
| 87 JSONObject json_trace_buffer(stream); |
| 88 json_trace_buffer.AddProperty("type", "TraceBuffer"); |
| 89 // TODO(johnmccutchan): Send cursor position in response. |
| 90 JSONArray json_trace_buffer_array(&json_trace_buffer, "members"); |
| 91 // Scan forward until we find the first entry which isn't empty. |
| 92 // TODO(johnmccutchan): Accept cursor start position as input. |
| 93 intptr_t start = -1; |
| 94 for (intptr_t i = 0; i < ring_capacity_; i++) { |
| 95 intptr_t index = RingIndex(i + ring_cursor_); |
| 96 if (!ring_[index].empty()) { |
| 97 start = index; |
| 98 break; |
| 99 } |
| 100 } |
| 101 // No messages in trace buffer. |
| 102 if (start == -1) { |
| 103 return; |
| 104 } |
| 105 for (intptr_t i = 0; i < ring_capacity_; i++) { |
| 106 intptr_t index = RingIndex(start + i); |
| 107 const TraceBufferEntry& entry = ring_[index]; |
| 108 if (entry.empty()) { |
| 109 // Empty entry, stop. |
| 110 break; |
| 111 } |
| 112 JSONObject trace_entry(&json_trace_buffer_array); |
| 113 trace_entry.AddProperty("type", "TraceBufferEntry"); |
| 114 double seconds = static_cast<double>(entry.micros) / |
| 115 static_cast<double>(kMicrosecondsPerSecond); |
| 116 trace_entry.AddProperty("time", seconds); |
| 117 trace_entry.AddProperty("message", entry.message); |
| 118 } |
| 119 } |
| 120 |
| 121 } // namespace dart |
OLD | NEW |