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