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

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

Powered by Google App Engine
This is Rietveld 408576698