| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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 "vm/json_stream.h" | 5 #include "vm/json_stream.h" |
| 6 #include "vm/os.h" | 6 #include "vm/os.h" |
| 7 #include "vm/trace_buffer.h" | 7 #include "vm/trace_buffer.h" |
| 8 | 8 |
| 9 namespace dart { | 9 namespace dart { |
| 10 | 10 |
| 11 TraceBuffer::TraceBuffer(intptr_t capacity) : ring_capacity_(capacity) { | 11 TraceBuffer::TraceBuffer(intptr_t initial_capacity, intptr_t maximum_capacity) |
| 12 : capacity_(initial_capacity), |
| 13 max_capacity_(maximum_capacity) { |
| 14 size_ = 0; |
| 12 ring_cursor_ = 0; | 15 ring_cursor_ = 0; |
| 13 Init(); | 16 Init(); |
| 14 } | 17 } |
| 15 | 18 |
| 16 | 19 |
| 17 TraceBuffer::~TraceBuffer() { | 20 TraceBuffer::~TraceBuffer() { |
| 18 ASSERT(ring_ != NULL); | 21 ASSERT(ring_ != NULL); |
| 19 Clear(); | 22 Clear(); |
| 20 free(ring_); | 23 free(ring_); |
| 21 } | 24 } |
| 22 | 25 |
| 23 | 26 |
| 24 void TraceBuffer::Init() { | 27 void TraceBuffer::Init() { |
| 25 ring_ = reinterpret_cast<TraceBufferEntry*>( | 28 ring_ = reinterpret_cast<TraceBufferEntry*>( |
| 26 calloc(ring_capacity_, sizeof(TraceBufferEntry))); // NOLINT | 29 calloc(capacity_, sizeof(TraceBufferEntry))); // NOLINT |
| 30 } |
| 31 |
| 32 |
| 33 void TraceBuffer::Resize(intptr_t new_capacity) { |
| 34 ASSERT(new_capacity > capacity_); |
| 35 if (new_capacity > max_capacity_) { |
| 36 // Clamp to max_capacity_. |
| 37 new_capacity = max_capacity_; |
| 38 } |
| 39 ASSERT(new_capacity <= max_capacity_); |
| 40 ring_ = reinterpret_cast<TraceBufferEntry*>( |
| 41 realloc(ring_, sizeof(*ring_) * new_capacity)); |
| 42 // Initialize new TraceBufferEntries. |
| 43 for (intptr_t i = capacity_; i < new_capacity; i++) { |
| 44 ring_[i].micros = 0; |
| 45 ring_[i].message = NULL; |
| 46 } |
| 47 capacity_ = new_capacity; |
| 27 } | 48 } |
| 28 | 49 |
| 29 | 50 |
| 30 void TraceBuffer::Clear() { | 51 void TraceBuffer::Clear() { |
| 31 for (intptr_t i = 0; i < ring_capacity_; i++) { | 52 for (intptr_t i = 0; i < capacity_; i++) { |
| 32 TraceBufferEntry& entry = ring_[i]; | 53 TraceBufferEntry& entry = ring_[i]; |
| 33 entry.micros = 0; | 54 entry.micros = 0; |
| 34 free(entry.message); | 55 free(entry.message); |
| 35 entry.message = NULL; | 56 entry.message = NULL; |
| 36 } | 57 } |
| 37 ring_cursor_ = 0; | 58 ring_cursor_ = 0; |
| 59 size_ = 0; |
| 38 } | 60 } |
| 39 | 61 |
| 40 | 62 |
| 41 void TraceBuffer::Fill(TraceBufferEntry* entry, int64_t micros, char* msg) { | 63 void TraceBuffer::Fill(TraceBufferEntry* entry, int64_t micros, char* msg) { |
| 42 if (entry->message != NULL) { | 64 if (entry->message != NULL) { |
| 43 // Recycle TraceBufferEntry. | 65 // Recycle TraceBufferEntry. |
| 44 free(entry->message); | 66 free(entry->message); |
| 45 } | 67 } |
| 46 entry->message = msg; | 68 entry->message = msg; |
| 47 entry->micros = micros; | 69 entry->micros = micros; |
| 48 } | 70 } |
| 49 | 71 |
| 50 | 72 |
| 51 void TraceBuffer::AppendTrace(int64_t micros, char* message) { | 73 void TraceBuffer::AppendTrace(int64_t micros, char* message) { |
| 74 if (size_ < capacity_) { |
| 75 size_++; |
| 76 if ((size_ == capacity_) && |
| 77 (capacity_ < max_capacity_)) { |
| 78 // Double size. |
| 79 Resize(capacity_ * 2); |
| 80 } |
| 81 } |
| 52 const intptr_t index = ring_cursor_; | 82 const intptr_t index = ring_cursor_; |
| 53 TraceBufferEntry* trace_entry = &ring_[index]; | 83 TraceBufferEntry* trace_entry = &ring_[index]; |
| 54 Fill(trace_entry, micros, message); | 84 Fill(trace_entry, micros, message); |
| 55 ring_cursor_ = RingIndex(ring_cursor_ + 1); | 85 ring_cursor_ = RingIndex(ring_cursor_ + 1); |
| 56 } | 86 } |
| 57 | 87 |
| 58 | 88 |
| 59 void TraceBuffer::Trace(int64_t micros, const char* message) { | 89 void TraceBuffer::Trace(int64_t micros, const char* message) { |
| 60 ASSERT(message != NULL); | 90 ASSERT(message != NULL); |
| 61 char* message_copy = strdup(message); | 91 char* message_copy = strdup(message); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 76 va_end(args); | 106 va_end(args); |
| 77 char* p = reinterpret_cast<char*>(malloc(len+1)); | 107 char* p = reinterpret_cast<char*>(malloc(len+1)); |
| 78 va_start(args, format); | 108 va_start(args, format); |
| 79 intptr_t len2 = OS::VSNPrint(p, len+1, format, args); | 109 intptr_t len2 = OS::VSNPrint(p, len+1, format, args); |
| 80 va_end(args); | 110 va_end(args); |
| 81 ASSERT(len == len2); | 111 ASSERT(len == len2); |
| 82 AppendTrace(micros, p); | 112 AppendTrace(micros, p); |
| 83 } | 113 } |
| 84 | 114 |
| 85 | 115 |
| 86 void TraceBuffer::PrintToJSONStream(JSONStream* stream) const { | 116 void TraceBuffer::PrintToJSONObject(JSONObject* json_trace_buffer) const { |
| 87 JSONObject json_trace_buffer(stream); | 117 json_trace_buffer->AddProperty("type", "TraceBuffer"); |
| 88 json_trace_buffer.AddProperty("type", "TraceBuffer"); | 118 json_trace_buffer->AddProperty("id", ""); |
| 89 // TODO(johnmccutchan): Send cursor position in response. | 119 // TODO(johnmccutchan): Send cursor position in response. |
| 90 JSONArray json_trace_buffer_array(&json_trace_buffer, "members"); | 120 JSONArray json_trace_buffer_array(json_trace_buffer, "members"); |
| 91 // Scan forward until we find the first entry which isn't empty. | 121 // Scan forward until we find the first entry which isn't empty. |
| 92 // TODO(johnmccutchan): Accept cursor start position as input. | 122 // TODO(johnmccutchan): Accept cursor start position as input. |
| 93 intptr_t start = -1; | 123 intptr_t start = -1; |
| 94 for (intptr_t i = 0; i < ring_capacity_; i++) { | 124 for (intptr_t i = 0; i < capacity_; i++) { |
| 95 intptr_t index = RingIndex(i + ring_cursor_); | 125 intptr_t index = RingIndex(i + ring_cursor_); |
| 96 if (!ring_[index].empty()) { | 126 if (!ring_[index].empty()) { |
| 97 start = index; | 127 start = index; |
| 98 break; | 128 break; |
| 99 } | 129 } |
| 100 } | 130 } |
| 101 // No messages in trace buffer. | 131 // No messages in trace buffer. |
| 102 if (start == -1) { | 132 if (start == -1) { |
| 103 return; | 133 return; |
| 104 } | 134 } |
| 105 for (intptr_t i = 0; i < ring_capacity_; i++) { | 135 for (intptr_t i = 0; i < capacity_; i++) { |
| 106 intptr_t index = RingIndex(start + i); | 136 intptr_t index = RingIndex(start + i); |
| 107 const TraceBufferEntry& entry = ring_[index]; | 137 const TraceBufferEntry& entry = ring_[index]; |
| 108 if (entry.empty()) { | 138 if (entry.empty()) { |
| 109 // Empty entry, stop. | 139 // Empty entry, stop. |
| 110 break; | 140 break; |
| 111 } | 141 } |
| 112 JSONObject trace_entry(&json_trace_buffer_array); | 142 JSONObject trace_entry(&json_trace_buffer_array); |
| 113 trace_entry.AddProperty("type", "TraceBufferEntry"); | 143 trace_entry.AddProperty("type", "TraceBufferEntry"); |
| 114 double seconds = static_cast<double>(entry.micros) / | 144 trace_entry.AddProperty("id", ""); |
| 115 static_cast<double>(kMicrosecondsPerSecond); | 145 intptr_t millis = |
| 116 trace_entry.AddProperty("time", seconds); | 146 static_cast<intptr_t>(entry.micros / kMicrosecondsPerMillisecond); |
| 147 trace_entry.AddProperty("time", millis); |
| 117 trace_entry.AddProperty("message", entry.message); | 148 trace_entry.AddProperty("message", entry.message); |
| 118 } | 149 } |
| 119 } | 150 } |
| 120 | 151 |
| 152 |
| 153 void TraceBuffer::PrintToJSONStream(JSONStream* stream) const { |
| 154 JSONObject json_trace_buffer(stream); |
| 155 PrintToJSONObject(&json_trace_buffer); |
| 156 } |
| 157 |
| 121 } // namespace dart | 158 } // namespace dart |
| OLD | NEW |