Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: runtime/vm/heap_trace.cc

Issue 11428067: Merge the Merlin heap tracing to top-of-trunk. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address review comments Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/heap_trace.h ('k') | runtime/vm/heap_trace_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, 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/heap_trace.h"
6
7 #include "include/dart_api.h"
8 #include "vm/dart_api_state.h"
9 #include "vm/debugger.h"
10 #include "vm/isolate.h"
11 #include "vm/object.h"
12 #include "vm/object_set.h"
13 #include "vm/object_store.h"
14 #include "vm/os.h"
15 #include "vm/stack_frame.h"
16 #include "vm/unicode.h"
17
18 namespace dart {
19
20 DEFINE_FLAG(bool, heap_trace, false, "Enable heap tracing.");
21
22 Dart_FileOpenCallback HeapTrace::open_callback_ = NULL;
23 Dart_FileWriteCallback HeapTrace::write_callback_ = NULL;
24 Dart_FileCloseCallback HeapTrace::close_callback_ = NULL;
25 bool HeapTrace::is_enabled_ = false;
26
27 class HeapTraceVisitor : public ObjectPointerVisitor {
28 public:
29 HeapTraceVisitor(Isolate* isolate,
30 HeapTrace* heap_trace,
31 ObjectSet* object_set)
32 : ObjectPointerVisitor(isolate),
33 heap_trace_(heap_trace),
34 vm_isolate_(Dart::vm_isolate()),
35 object_set_(object_set) {
36 }
37
38 void VisitPointers(RawObject** first, RawObject** last) {
39 for (RawObject** current = first; current <= last; current++) {
40 RawObject* raw_obj = *current;
41
42 // We only care about objects in the heap
43 // Also, since this visitor will frequently be encountering redudant
44 // roots, we use an object_set to skip the duplicates.
45 if (raw_obj->IsHeapObject() &&
46 raw_obj != reinterpret_cast<RawObject*>(0x1) &&
47 raw_obj != reinterpret_cast<RawObject*>(0xabababab) &&
48 !object_set_->Contains(raw_obj) &&
49 !vm_isolate_->heap()->Contains(RawObject::ToAddr(raw_obj))) {
50 object_set_->Add(raw_obj);
51 uword addr = RawObject::ToAddr(raw_obj);
52 heap_trace_->TraceSingleRoot(addr);
53 }
54 }
55 }
56
57 private:
58 HeapTrace* heap_trace_;
59 Isolate* vm_isolate_;
60 // TODO(cshapiro): replace with a sparse data structure.
61 ObjectSet* object_set_;
62 DISALLOW_COPY_AND_ASSIGN(HeapTraceVisitor);
63 };
64
65
66 class HeapTraceScopedHandleVisitor : public ObjectPointerVisitor {
67 public:
68 HeapTraceScopedHandleVisitor(Isolate* isolate, HeapTrace* heap_trace)
69 : ObjectPointerVisitor(isolate), heap_trace_(heap_trace) {
70 }
71
72 void VisitPointers(RawObject** first, RawObject** last) {
73 for (RawObject** current = first; current <= last; current++) {
74 RawObject* raw_obj = *current;
75 Heap* heap = isolate()->heap();
76
77 // We only care about objects in the heap
78 if (raw_obj->IsHeapObject() &&
79 raw_obj != reinterpret_cast<RawObject*>(0x1) &&
80 raw_obj != reinterpret_cast<RawObject*>(0xabababab) &&
81 heap->Contains(RawObject::ToAddr(raw_obj))) {
82 uword addr = RawObject::ToAddr(raw_obj);
83 heap_trace_->TraceScopedHandle(addr);
84 }
85 }
86 }
87
88 private:
89 HeapTrace* heap_trace_;
90 DISALLOW_COPY_AND_ASSIGN(HeapTraceScopedHandleVisitor);
91 };
92
93
94 class HeapTraceObjectStoreVisitor : public ObjectPointerVisitor {
95 public:
96 HeapTraceObjectStoreVisitor(Isolate* isolate, HeapTrace* heap_trace)
97 : ObjectPointerVisitor(isolate), heap_trace_(heap_trace) {
98 }
99
100 void VisitPointers(RawObject** first, RawObject** last) {
101 for (RawObject** current = first; current <= last; current++) {
102 RawObject* raw_obj = *current;
103
104 // We only care about obects in the heap.
105 if (raw_obj->IsHeapObject() &&
106 raw_obj != reinterpret_cast<RawObject*>(0x1) &&
107 raw_obj != reinterpret_cast<RawObject*>(0xabababab)) {
108 uword addr = RawObject::ToAddr(raw_obj);
109 heap_trace_->TraceObjectStorePointer(addr);
110 }
111 }
112 }
113
114 private:
115 HeapTrace* heap_trace_;
116 DISALLOW_COPY_AND_ASSIGN(HeapTraceObjectStoreVisitor);
117 };
118
119
120 class HeapTraceInitialHeapVisitor : public ObjectVisitor {
121 public:
122 HeapTraceInitialHeapVisitor(Isolate* isolate, HeapTrace* heap_trace)
123 : ObjectVisitor(isolate), heap_trace_(heap_trace) {}
124
125 void VisitObject(RawObject* raw_obj) {
126 heap_trace_->TraceSnapshotAlloc(raw_obj, raw_obj->Size());
127 }
128
129 private:
130 HeapTrace* heap_trace_;
131 DISALLOW_COPY_AND_ASSIGN(HeapTraceInitialHeapVisitor);
132 };
133
134
135 HeapTrace::HeapTrace() : isolate_initialized_(false), output_stream_(NULL) {
136 }
137
138
139 HeapTrace::~HeapTrace() {
140 if (isolate_initialized_) {
141 (*close_callback_)(output_stream_);
142 }
143 }
144
145
146 void HeapTrace::InitOnce(Dart_FileOpenCallback open_callback,
147 Dart_FileWriteCallback write_callback,
148 Dart_FileCloseCallback close_callback) {
149 ASSERT(open_callback != NULL);
150 ASSERT(write_callback != NULL);
151 ASSERT(close_callback != NULL);
152 HeapTrace::open_callback_ = open_callback;
153 HeapTrace::write_callback_ = write_callback;
154 HeapTrace::close_callback_ = close_callback;
155 HeapTrace::is_enabled_ = true;
156 }
157
158
159 ObjectSet* HeapTrace::CreateEmptyObjectSet() const {
160 Isolate* isolate = Isolate::Current();
161 uword start, end;
162 isolate->heap()->StartEndAddress(&start, &end);
163
164 Isolate* vm_isolate = Dart::vm_isolate();
165 uword vm_start, vm_end;
166 vm_isolate->heap()->StartEndAddress(&vm_start, &vm_end);
167
168 ObjectSet* allocated_set = new ObjectSet(Utils::Minimum(start, vm_start),
169 Utils::Maximum(end, vm_end));
170
171 return allocated_set;
172 }
173
174
175 void HeapTrace::ResizeObjectSet() {
176 Isolate* isolate = Isolate::Current();
177 uword start, end;
178 isolate->heap()->StartEndAddress(&start, &end);
179 Isolate* vm_isolate = Dart::vm_isolate();
180 uword vm_start, vm_end;
181 vm_isolate->heap()->StartEndAddress(&vm_start, &vm_end);
182 object_set_.Resize(Utils::Minimum(start, vm_start),
183 Utils::Maximum(end, vm_end));
184 }
185
186
187 void HeapTrace::Init(Isolate* isolate) {
188 // Do not trace the VM isolate
189 if (isolate == Dart::vm_isolate()) {
190 return;
191 }
192 ASSERT(isolate_initialized_ == false);
193 const char* format = "%s.htrace";
194 intptr_t len = OS::SNPrint(NULL, 0, format, isolate->name());
195 char* filename = new char[len + 1];
196 OS::SNPrint(filename, len + 1, format, isolate->name());
197 output_stream_ = (*open_callback_)(filename);
198 ASSERT(output_stream_ != NULL);
199 delete[] filename;
200 isolate_initialized_ = true;
201
202 HeapTraceObjectStoreVisitor object_store_visitor(isolate, this);
203 isolate->object_store()->VisitObjectPointers(&object_store_visitor);
204
205 // Visit any objects that may have been allocated during startup,
206 // before we started tracing.
207 HeapTraceInitialHeapVisitor heap_visitor(isolate, this);
208 isolate->heap()->IterateObjects(&heap_visitor);
209 TraceRoots(isolate);
210 }
211
212
213 // Allocation Record - 'A' (0x41)
214 //
215 // Format:
216 // 'A'
217 // uword - address of allocated object
218 // uword - size of allocated object
219 void HeapTrace::TraceAllocation(uword addr, intptr_t size) {
220 if (isolate_initialized_) {
221 {
222 AllocationRecord rec(this);
223 rec.Write(addr);
224 rec.Write(size);
225 }
226 TraceRoots(Isolate::Current());
227 }
228 }
229
230
231 // Snapshot Allocation Record - 'B' (0x41)
232 //
233 // Format:
234 // 'B'
235 // uword - address of allocated object
236 // uword - size of allocated object
237 void HeapTrace::TraceSnapshotAlloc(RawObject* obj, intptr_t size) {
238 if (isolate_initialized_) {
239 SnapshotAllocationRecord rec(this);
240 rec.Write(RawObject::ToAddr(obj));
241 rec.Write(static_cast<uword>(size));
242 }
243 }
244
245
246 // Allocate Zone Handle Record - 'Z' (0x5a)
247 //
248 // Format:
249 // 'Z'
250 // uword - handle address (where the handle is pointing)
251 // uword - zone address (address of the zone the handle is in)
252 void HeapTrace::TraceAllocateZoneHandle(uword handle, uword zone_addr) {
253 if (isolate_initialized_) {
254 AllocZoneHandleRecord rec(this);
255 rec.Write(handle);
256 rec.Write(zone_addr);
257 }
258 }
259
260
261 // Delete Zone Record - 'z' (0x7a)
262 //
263 // Format:
264 // 'z'
265 // uword - zone address (all the handles in that zone are now gone)
266 void HeapTrace::TraceDeleteZone(Zone* zone) {
267 if (isolate_initialized_) {
268 DeleteZoneRecord rec(this);
269 rec.Write(reinterpret_cast<uword>(zone));
270 }
271 }
272
273
274 // Delete Scoped Hanldes Record - 's' (0x73)
275 //
276 // Format:
277 // 's'
278 void HeapTrace::TraceDeleteScopedHandles() {
279 if (isolate_initialized_) {
280 DeleteScopedHandlesRecord rec(this);
281 }
282 }
283
284
285 // Copy Record - 'C' (0x43)
286 //
287 // Format:
288 // 'C'
289 // uword - old address
290 // uword - new address
291 void HeapTrace::TraceCopy(uword from_addr, uword to_addr) {
292 if (isolate_initialized_) {
293 CopyRecord rec(this);
294 rec.Write(from_addr);
295 rec.Write(to_addr);
296 }
297 }
298
299
300 // Object Store Recorda - 'O'(0x4f)
301 //
302 // Format:
303 // 'O'
304 // uword - address
305 void HeapTrace::TraceObjectStorePointer(uword addr) {
306 if (isolate_initialized_) {
307 ObjectStoreRecord rec(this);
308 rec.Write(addr);
309 }
310 }
311
312
313 // Promotion Records - 'P' (0x50)
314 //
315 // Format:
316 // 'P'
317 // uword - old address
318 // uword - new address
319 void HeapTrace::TracePromotion(uword old_addr, uword promoted_addr) {
320 if (isolate_initialized_) {
321 PromotionRecord rec(this);
322 rec.Write(old_addr);
323 rec.Write(promoted_addr);
324 }
325 }
326
327
328 // Death Range Record - 'L' (0x4c)
329 //
330 // Format:
331 // 'L'
332 // uword - inclusive start address of the space being left
333 // uword - exclusive end address of the space being left
334 void HeapTrace::TraceDeathRange(uword inclusive_start, uword exclusive_end) {
335 if (isolate_initialized_) {
336 DeathRangeRecord rec(this);
337 rec.Write(inclusive_start);
338 rec.Write(exclusive_end);
339 }
340 }
341
342
343 // Register Class Record - 'K' (0x4b)
344 //
345 // Format:
346 // 'K'
347 // uword - address ( the address of the class)
348 void HeapTrace::TraceRegisterClass(const Class& cls) {
349 if (isolate_initialized_) {
350 RegisterClassRecord rec(this);
351 rec.Write(RawObject::ToAddr(cls.raw()));
352 }
353 }
354
355
356 // Scoped Handle Record - 'H' (0x48)
357 //
358 // Format:
359 // 'H'
360 // uword - adress of the scoped handle (where it is pointing)
361 void HeapTrace::TraceScopedHandle(uword handle) {
362 if (isolate_initialized_) {
363 AllocScopedHandleRecord rec(this);
364 rec.Write(handle);
365 }
366 }
367
368
369 // Root Record - 'R' (0x52)
370 //
371 // Format:
372 // 'R'
373 // uword - address
374 void HeapTrace::TraceSingleRoot(uword root_addr) {
375 if (isolate_initialized_) {
376 RootRecord rec(this);
377 rec.Write(root_addr);
378 }
379 }
380
381
382 // Sweep Record - 'S'
383 //
384 // Format:
385 // 'S'
386 // uword - address
387 void HeapTrace::TraceSweep(uword sweept_addr) {
388 if (isolate_initialized_) {
389 SweepRecord rec(this);
390 rec.Write(sweept_addr);
391 }
392 }
393
394
395 // Does not output any records directly,
396 // but does call TraceSingleRoot
397 void HeapTrace::TraceRoots(Isolate* isolate) {
398 if (isolate_initialized_) {
399 ResizeObjectSet();
400 HeapTraceVisitor visitor(isolate, this, &object_set_);
401 HeapTraceScopedHandleVisitor handle_visitor(isolate, this);
402
403 bool visit_prologue_weak_handles = true;
404 bool validate_frames = false;
405
406 // Visit objects in per isolate stubs.
407 StubCode::VisitObjectPointers(&visitor);
408
409 // stack
410 StackFrameIterator frames_iterator(validate_frames);
411 StackFrame* frame = frames_iterator.NextFrame();
412 while (frame != NULL) {
413 frame->VisitObjectPointers(&visitor);
414 frame = frames_iterator.NextFrame();
415 }
416
417 if (isolate->api_state() != NULL) {
418 isolate->api_state()->VisitObjectPointers(&visitor,
419 visit_prologue_weak_handles);
420 }
421
422 // Visit the top context which is stored in the isolate.
423 RawContext* top_context = isolate->top_context();
424 visitor.VisitPointer(reinterpret_cast<RawObject**>(&top_context));
425
426 // Visit the currently active IC data array.
427 RawArray* ic_data_array = isolate->ic_data_array();
428 visitor.VisitPointer(reinterpret_cast<RawObject**>(&ic_data_array));
429
430 // Visit objects in the debugger.
431 isolate->debugger()->VisitObjectPointers(&visitor);
432
433 isolate->current_zone()->handles()->
434 VisitUnvisitedScopedHandles(&handle_visitor);
435
436 object_set_.FastClear();
437 }
438 }
439
440
441 // Store Record - 'U' (0x55)
442 //
443 // Format:
444 // 'U'
445 // uword - originating object address (where a pointer is being stored)
446 // uword - byte offset into origin where the pointer is being stored
447 // uword - value of the pointer being stored
448 void HeapTrace::TraceStoreIntoObject(uword object,
449 uword field_addr,
450 uword value) {
451 if (isolate_initialized_) {
452 // We don't care about pointers into the VM_Islate heap, so skip them.
453 // There should not be any pointers /out/ of the VM isolate; so we
454 // do not check object.
455 if (Isolate::Current()->heap()->Contains(value)) {
456 StoreRecord rec(this);
457 uword slot_offset = field_addr - object;
458
459 rec.Write(object);
460 rec.Write(slot_offset);
461 rec.Write(value);
462 }
463 }
464 }
465
466
467 // Mark Sweep Start Record - '{' (0x7b)
468 //
469 // Format:
470 // '{'
471 void HeapTrace::TraceMarkSweepStart() {
472 if (isolate_initialized_) {
473 MarkSweepStartRecord rec(this);
474 }
475 }
476
477
478 // Mark Sweep Finish Record - '}' (0x7d)
479 //
480 // Format:
481 // '}'
482 void HeapTrace::TraceMarkSweepFinish() {
483 if (isolate_initialized_) {
484 MarkSweepFinishRecord rec(this);
485 }
486 }
487
488 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/heap_trace.h ('k') | runtime/vm/heap_trace_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698