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

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

Issue 10452006: Implement a heap profiler for the Dart managed heap. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 7 months 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 (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_profiler.h"
6
7 #include <stdio.h>
8 #include <arpa/inet.h>
9 #include <sys/time.h>
10
11 #include "vm/dart_api_state.h"
12 #include "vm/object.h"
13 #include "vm/raw_object.h"
14 #include "vm/stack_frame.h"
15 #include "vm/unicode.h"
16
17 namespace dart {
18
19 HeapProfiler::Buffer::~Buffer() {
20 delete[] data_;
21 }
22
23
24 void HeapProfiler::Buffer::Write(const uint8_t* data, intptr_t size) {
25 EnsureCapacity(size);
26 memmove(&data_[size_], data, size);
27 size_ += size;
28 }
29
30
31 void HeapProfiler::Buffer::EnsureCapacity(intptr_t size) {
32 if ((size + size_) > capacity_) {
33 intptr_t new_capacity = Utils::RoundUpToPowerOfTwo(capacity_ + size);
34 uint8_t* new_data = new uint8_t[new_capacity];
35 memmove(new_data, data_, size_);
36 capacity_ = new_capacity;
37 data_ = new_data;
38 }
39 }
40
41
42 void HeapProfiler::Record::Write(const uint8_t* value, intptr_t size) {
43 body_.Write(value, size);
44 }
45
46
47 void HeapProfiler::Record::Write8(uint8_t value) {
48 body_.Write(&value, sizeof(value));
49 }
50
51
52 void HeapProfiler::Record::Write16(uint16_t value) {
53 value = htons(value);
54 body_.Write(reinterpret_cast<uint8_t*>(&value), sizeof(value));
55 }
56
57
58 void HeapProfiler::Record::Write32(uint32_t value) {
59 value = htonl(value);
60 body_.Write(reinterpret_cast<uint8_t*>(&value), sizeof(value));
61 }
62
63
64 void HeapProfiler::Record::Write64(uint64_t value) {
65 uint16_t x = 0xFF;
66 if (*reinterpret_cast<uint8_t*>(&x) == 0xFF) {
67 uint64_t hi = static_cast<uint64_t>(htonl(value & 0xFFFFFFFF)) << 32;
68 uint64_t lo = htonl(value >> 32);
69 value = hi | lo;
70 }
71 body_.Write(reinterpret_cast<uint8_t*>(&value), sizeof(value));
72 }
73
74
75 void HeapProfiler::Record::WritePointer(const void* value) {
76 if (sizeof(value) == 4) {
77 Write32(reinterpret_cast<uint32_t>(value));
78 } else {
79 ASSERT(sizeof(value) == 8);
80 Write64(reinterpret_cast<uint64_t>(value));
81 }
82 }
83
84
85 HeapProfiler::SubRecord::SubRecord(uint8_t sub_tag, HeapProfiler* profiler)
86 : record_(profiler->heap_dump_record_) {
87 record_->Write8(sub_tag);
88 }
89
90
91 HeapProfiler::SubRecord::~SubRecord() {
92 }
93
94
95 void HeapProfiler::SubRecord::Write(const uint8_t* value, intptr_t size) {
96 record_->Write(value, size);
97 }
98
99
100 void HeapProfiler::SubRecord::Write8(uint8_t value) {
101 record_->Write8(value);
102 }
103
104
105 void HeapProfiler::SubRecord::Write16(uint16_t value) {
106 record_->Write16(value);
107 }
108
109
110 void HeapProfiler::SubRecord::Write32(uint32_t value) {
111 record_->Write32(value);
112 }
113
114
115 void HeapProfiler::SubRecord::Write64(uint64_t value) {
116 record_->Write64(value);
117 }
118
119
120 void HeapProfiler::SubRecord::WritePointer(const void* value) {
121 record_->WritePointer(value);
122 }
123
124
125 HeapProfiler::HeapProfiler(Dart_HeapProfileWriteCallback callback, void* stream)
126 : write_callback_(callback),
127 output_stream_(stream),
128 heap_dump_record_(NULL) {
129 WriteHeader();
130 WriteStackTrace();
131 heap_dump_record_ = new Record(kHeapDump, this);
132 }
133
134
135 HeapProfiler::~HeapProfiler() {
136 delete heap_dump_record_;
137 }
138
139
140 const RawObject* HeapProfiler::ObjectId(const RawObject* raw_obj) {
141 if (!raw_obj->IsHeapObject()) {
142 const RawSmi* raw_smi = reinterpret_cast<const RawSmi*>(raw_obj);
143 if (smi_table_.find(raw_smi) == smi_table_.end()) {
144 smi_table_.insert(raw_smi);
turnidge 2012/05/29 17:50:01 Add comment?
cshapiro 2012/06/01 04:27:02 Done.
145 }
146 } else if (raw_obj->GetClassIndex() == kNullClassIndex) {
147 return NULL;
148 }
149 return raw_obj;
150 }
151
152
153 const RawClass* HeapProfiler::ClassId(const RawClass* raw_class) {
154 if (class_table_.find(raw_class) == class_table_.end()) {
155 class_table_.insert(raw_class);
turnidge 2012/05/29 17:50:01 Add comment?
cshapiro 2012/06/01 04:27:02 Done.
156 WriteLoadClass(raw_class);
157 }
158 return raw_class;
159 }
160
161
162 const char* HeapProfiler::StringId(const char* c_string) {
163 const RawString* ptr = reinterpret_cast<const RawString*>(c_string);
164 if (string_table_.find(ptr) == string_table_.end()) {
165 string_table_.insert(ptr);
turnidge 2012/05/29 17:50:01 Add comment?
cshapiro 2012/06/01 04:27:02 Done.
166 WriteStringInUtf8(c_string);
167 }
168 return c_string;
169 }
170
171
172 const RawString* HeapProfiler::StringId(const RawString* raw_string) {
173 if (string_table_.find(raw_string) == string_table_.end()) {
174 string_table_.insert(raw_string);
175 WriteStringInUtf8(raw_string);
176 }
177 return raw_string;
178 }
179
180
181 void HeapProfiler::WriteRoot(const RawObject* raw_obj) {
182 SubRecord sub(kRootUnknown, this);
183 sub.WritePointer(ObjectId(raw_obj));
184 }
185
186
187 void HeapProfiler::WriteObject(const RawObject* raw_obj) {
188 ASSERT(raw_obj->IsHeapObject());
189 if (FreeListElement::IsSpecialClass(raw_obj)) {
turnidge 2012/05/29 17:50:01 What does this mean? Add comment?
cshapiro 2012/06/01 04:27:02 Good question. It means the raw_obj is actually a
190 return;
191 }
192 ObjectKind kind = raw_obj->ptr()->class_->ptr()->instance_kind_;
193 switch (kind) {
194 case Class::kInstanceKind: {
195 WriteClassDump(reinterpret_cast<const RawClass*>(raw_obj));
196 break;
197 }
198 case Array::kInstanceKind:
199 case ImmutableArray::kInstanceKind: {
200 WriteObjectArrayDump(reinterpret_cast<const RawArray*>(raw_obj));
201 break;
202 }
203 case Int8Array::kInstanceKind:
204 case Uint8Array::kInstanceKind: {
205 const RawInt8Array* raw_int8_array =
206 reinterpret_cast<const RawInt8Array*>(raw_obj);
207 WritePrimitiveArrayDump(raw_int8_array,
208 kByte,
209 &raw_int8_array->data_[0]);
210 break;
211 }
212 case Int16Array::kInstanceKind:
213 case Uint16Array::kInstanceKind: {
214 const RawInt16Array* raw_int16_array =
215 reinterpret_cast<const RawInt16Array*>(raw_obj);
216 WritePrimitiveArrayDump(raw_int16_array,
217 kShort,
218 &raw_int16_array->data_[0]);
219 break;
220 }
221 case Int32Array::kInstanceKind:
222 case Uint32Array::kInstanceKind: {
223 const RawInt32Array* raw_int32_array =
224 reinterpret_cast<const RawInt32Array*>(raw_obj);
225 WritePrimitiveArrayDump(raw_int32_array,
226 kInt,
227 &raw_int32_array->data_[0]);
228 break;
229 }
230 case Int64Array::kInstanceKind:
231 case Uint64Array::kInstanceKind: {
232 const RawInt64Array* raw_int64_array =
233 reinterpret_cast<const RawInt64Array*>(raw_obj);
234 WritePrimitiveArrayDump(raw_int64_array,
235 kLong,
236 &raw_int64_array->data_[0]);
237 break;
238 }
239 case Float32Array::kInstanceKind: {
240 const RawFloat32Array* raw_float32_array =
241 reinterpret_cast<const RawFloat32Array*>(raw_obj);
242 WritePrimitiveArrayDump(raw_float32_array,
243 kFloat,
244 &raw_float32_array->data_[0]);
245 break;
246 }
247 case Float64Array::kInstanceKind: {
248 const RawFloat64Array* raw_float64_array =
249 reinterpret_cast<const RawFloat64Array*>(raw_obj);
250 WritePrimitiveArrayDump(raw_float64_array,
251 kDouble,
252 &raw_float64_array->data_[0]);
253 break;
254 }
255 case OneByteString::kInstanceKind:
256 case TwoByteString::kInstanceKind:
257 case FourByteString::kInstanceKind:
258 case ExternalOneByteString::kInstanceKind:
259 case ExternalTwoByteString::kInstanceKind:
260 case ExternalFourByteString::kInstanceKind: {
261 WriteInstanceDump(StringId(reinterpret_cast<const RawString*>(raw_obj)));
262 break;
263 }
264 default:
265 WriteInstanceDump(raw_obj);
266 }
267 }
268
269
270 void HeapProfiler::Write(const void* data, intptr_t size) {
271 (*write_callback_)(data, size, output_stream_);
272 }
273
274
275 // Header
276 //
277 // Format:
278 // [u1]* - format name
279 // u4 - size of identifiers
280 // u4 - high word of number of milliseconds since 0:00 GMT, 1/1/70
281 // u4 - low word of number of milliseconds since 0:00 GMT, 1/1/70
282 void HeapProfiler::WriteHeader() {
283 const char magic[] = "JAVA PROFILE 1.0.1";
284 Write(magic, sizeof(magic));
285 uint32_t size = htonl(kWordSize);
286 Write(&size, sizeof(size));
287 timeval tv;
288 int result = gettimeofday(&tv, NULL);
289 ASSERT(result != -1);
290 uint64_t milliseconds = (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
291 uint32_t hi = htonl((uint32_t)((milliseconds >> 32) & 0x00000000FFFFFFFF));
292 Write(&hi, sizeof(hi));
293 uint32_t lo = htonl((uint32_t)(milliseconds & 0x00000000FFFFFFFF));
294 Write(&lo, sizeof(lo));
295 }
296
297
298 // Record
299 //
300 // Format:
301 // u1 - TAG: denoting the type of the record
302 // u4 - TIME: number of microseconds since the time stamp in the header
303 // u4 - LENGTH: number of bytes that follow this u4 field and belong
304 // to this record
305 // [u1]* - BODY: as many bytes as specified in the above u4 field
306 void HeapProfiler::WriteRecord(const Record& record) {
307 uint8_t tag = record.Tag();
308 Write(&tag, sizeof(tag));
309 uint32_t time = htonl(record.Time());
310 Write(&time, sizeof(time));
311 uint32_t length = htonl(record.Length());
312 Write(&length, sizeof(length));
313 Write(record.Body(), record.Length());
314 }
315
316
317 // STRING IN UTF8 - 0x01
318 //
319 // Format:
320 // ID - ID for this string
321 // [u1]* - UTF8 characters for string (NOT NULL terminated)
322 void HeapProfiler::WriteStringInUtf8(const RawString* raw_string) {
323 intptr_t length = 0;
324 char* characters = NULL;
325 ObjectKind kind = raw_string->ptr()->class_->ptr()->instance_kind_;
326 if (kind == OneByteString::kInstanceKind) {
327 const RawOneByteString* onestr =
328 reinterpret_cast<const RawOneByteString*>(raw_string);
329 for (intptr_t i = 0; i < Smi::Value(onestr->ptr()->length_); ++i) {
330 length += Utf8::Length(onestr->ptr()->data_[i]);
331 }
332 characters = new char[length];
333 for (intptr_t i = 0, j = 0; i < Smi::Value(onestr->ptr()->length_); ++i) {
334 int32_t ch = onestr->ptr()->data_[i];
335 j += Utf8::Encode(ch, &characters[j]);
336 }
337 } else if (kind == TwoByteString::kInstanceKind) {
338 const RawTwoByteString* twostr =
339 reinterpret_cast<const RawTwoByteString*>(raw_string);
340 for (intptr_t i = 0; i < Smi::Value(twostr->ptr()->length_); ++i) {
341 length += Utf8::Length(twostr->ptr()->data_[i]);
342 }
343 characters = new char[length];
344 for (intptr_t i = 0, j = 0; i < Smi::Value(twostr->ptr()->length_); ++i) {
345 int32_t ch = twostr->ptr()->data_[i];
346 j += Utf8::Encode(ch, &characters[j]);
347 }
348 } else {
349 ASSERT(kind == FourByteString::kInstanceKind);
350 const RawFourByteString* fourstr =
351 reinterpret_cast<const RawFourByteString*>(raw_string);
352 for (intptr_t i = 0; i < Smi::Value(fourstr->ptr()->length_); ++i) {
353 length += Utf8::Length(fourstr->ptr()->data_[i]);
354 }
355 characters = new char[length];
356 for (intptr_t i = 0, j = 0; i < Smi::Value(fourstr->ptr()->length_); ++i) {
357 int32_t ch = fourstr->ptr()->data_[i];
358 j += Utf8::Encode(ch, &characters[j]);
359 }
360 }
361 Record record(kStringInUtf8, this);
362 record.WritePointer(ObjectId(raw_string));
363 for (intptr_t i = 0; i < length; ++i) {
364 record.Write8(characters[i]);
365 }
366 delete[] characters;
367 }
368
369
370 void HeapProfiler::WriteStringInUtf8(const char* c_string) {
371 Record record(kStringInUtf8, this);
372 record.WritePointer(c_string);
373 for (; *c_string != '\0'; ++c_string) {
374 record.Write8(*c_string);
375 }
376 }
377
378
379 // LOAD CLASS - 0x02
380 //
381 // Format:
382 // u4 - class serial number (always > 0)
383 // ID - class object ID
384 // u4 - stack trace serial number
385 // ID - class name string ID
386 void HeapProfiler::WriteLoadClass(const RawClass* raw_class) {
387 Record record(kLoadClass, this);
388 // class serial number (always > 0)
389 record.Write32(1);
390 // class object ID
391 record.WritePointer(raw_class);
392 // stack trace serial number
393 record.Write32(0);
394 if (raw_class->ptr()->name_ == String::null()) {
395 intptr_t class_index = Object::GetSingletonClassIndex(raw_class);
396 const char* name = Object::GetSingletonClassName(class_index);
397 record.WritePointer(StringId(name));
398 } else {
399 record.WritePointer(StringId(raw_class->ptr()->name_));
400 }
401 }
402
403
404 // STACK TRACE - 0x05
405 //
406 // u4 - stack trace serial number
407 // u4 - thread serial number
408 // u4 - number of frames
409 // [ID]* - series of stack frame ID's
410 void HeapProfiler::WriteStackTrace() {
411 Record record(kStackTrace, this);
412 // stack trace serial number
413 record.Write32(0);
414 // thread serial number
415 record.Write32(0);
416 // number of frames
417 record.Write32(0);
418 }
419
420
421 // HEAP SUMMARY - 0x07
422 //
423 // Format:
424 // u4 - total live bytes
425 // u4 - total live instances
426 // u8 - total bytes allocated
427 // u8 - total instances allocated
428 void HeapProfiler::WriteHeapSummary(uint32_t total_live_bytes,
429 uint32_t total_live_instances,
430 uint64_t total_bytes_allocated,
431 uint64_t total_instances_allocated) {
432 Record record(kHeapSummary, this);
433 record.Write32(total_live_bytes);
434 record.Write32(total_live_instances);
435 record.Write32(total_bytes_allocated);
436 record.Write32(total_instances_allocated);
437 }
438
439
440 // HEAP DUMP - 0x0C
441 //
442 // Format:
443 // []*
444 void HeapProfiler::WriteHeapDump() {
445 Record record(kHeapDump, this);
446 }
447
448
449 // CLASS DUMP - 0x20
450 //
451 // Format:
452 // ID - class object ID
453 // u4 - stack trace serial number
454 // ID - super class object ID
455 // ID - class loader object ID
456 // ID - signers object ID
457 // ID - protection domain object ID
458 // ID - reserved
459 // ID - reserved
460 // u4 - instance size (in bytes)
461 // u2 - size of constant pool and number of records that follow:
462 // u2 - constant pool index
463 // u1 - type of entry: (See Basic Type)
464 // value - value of entry (u1, u2, u4, or u8 based on type of entry)
465 // u2 - Number of static fields:
466 // ID - static field name string ID
467 // u1 - type of field: (See Basic Type)
468 // value - value of entry (u1, u2, u4, or u8 based on type of field)
469 // u2 - Number of instance fields (not including super class's)
470 // ID - field name string ID
471 // u1 - type of field: (See Basic Type)
472 void HeapProfiler::WriteClassDump(const RawClass* raw_class) {
473 SubRecord sub(kClassDump, this);
474 // class object ID
475 sub.WritePointer(ClassId(raw_class));
476 // stack trace serial number
477 sub.Write32(0);
478 // super class object ID
479 if (raw_class == raw_class->ptr()->class_) {
480 sub.WritePointer(NULL);
481 } else {
482 sub.WritePointer(ClassId(raw_class->ptr()->class_));
483 }
484 // class loader object ID
485 sub.WritePointer(NULL);
486 // signers object ID
487 sub.WritePointer(NULL);
488 // protection domain object ID
489 sub.WritePointer(NULL);
490 // reserved
491 sub.WritePointer(NULL);
492 // reserved
493 sub.WritePointer(NULL);
494
495 intptr_t num_static_fields = 0;
496 intptr_t num_instance_fields = 0;
497
498 RawArray* raw_array = raw_class->ptr()->fields_;
499 if (raw_array != Array::null()) {
500 for (intptr_t i = 0; i < Smi::Value(raw_array->ptr()->length_); ++i) {
501 RawField* raw_field =
502 reinterpret_cast<RawField*>(raw_array->ptr()->data()[i]);
503 if (raw_field->ptr()->is_static_) {
504 ++num_static_fields;
505 } else {
506 ++num_instance_fields;
507 }
508 }
509 }
510 // instance size (in bytes)
511 sub.Write32(sizeof(RawClass));
512 // size of constant pool and number of records that follow:
513 sub.Write16(0);
514 // Number of static fields
515 sub.Write16(num_static_fields);
516 // Static fields:
517 if (raw_array != Array::null()) {
518 for (intptr_t i = 0; i < Smi::Value(raw_array->ptr()->length_); ++i) {
519 RawField* raw_field =
520 reinterpret_cast<RawField*>(raw_array->ptr()->data()[i]);
521 if (raw_field->ptr()->is_static_) {
522 ASSERT(raw_field->ptr()->name_ != String::null());
523 // static field name string ID
524 sub.WritePointer(StringId(raw_field->ptr()->name_));
525 // type of static field
526 sub.Write8(kObject);
527 // value of entry
528 sub.WritePointer(ObjectId(raw_field->ptr()->value_));
529 }
530 }
531 }
532 // Number of instance fields (not include super class's)
533 sub.Write16(num_instance_fields);
534 // Instance fields:
535 if (raw_array != Array::null()) {
536 for (intptr_t i = 0; i < Smi::Value(raw_array->ptr()->length_); ++i) {
537 RawField* raw_field =
538 reinterpret_cast<RawField*>(raw_array->ptr()->data()[i]);
539 if (!raw_field->ptr()->is_static_) {
540 ASSERT(raw_field->ptr()->name_ != String::null());
541 // field name string ID
542 sub.WritePointer(StringId(raw_field->ptr()->name_));
543 // type of field
544 sub.Write8(kObject);
545 }
546 }
547 }
548 }
549
550
551 // INSTANCE DUMP - 0x21
552 //
553 // Format:
554 // ID - object ID
555 // u4 - stack trace serial number
556 // ID - class object ID
557 // u4 - number of bytes that follow
558 // [value]* - instance field values (this class, followed by super class, etc)
559 void HeapProfiler::WriteInstanceDump(const RawObject* raw_obj) {
560 SubRecord sub(kInstanceDump, this);
561 // object ID
562 sub.WritePointer(raw_obj);
563 // stack trace serial number
564 sub.Write32(0);
565 // class object ID
566 sub.WritePointer(ClassId(raw_obj->ptr()->class_));
567 // number of bytes that follow
568 intptr_t num_instance_fields = 0;
569 for (RawClass* cls = raw_obj->ptr()->class_;
570 cls != cls->ptr()->class_;
571 cls = cls->ptr()->class_) {
572 RawArray* raw_array = cls->ptr()->fields_;
573 if (raw_array != Array::null()) {
574 intptr_t length = Smi::Value(raw_array->ptr()->length_);
575 for (intptr_t i = 0; i < length; ++i) {
576 RawField* raw_field =
577 reinterpret_cast<RawField*>(raw_array->ptr()->data()[i]);
578 if (!raw_field->ptr()->is_static_) {
579 ++num_instance_fields;
580 }
581 }
582 }
583 }
584 sub.Write32(num_instance_fields * kWordSize);
585 // instance field values (this class, followed by super class, etc)
586 for (RawClass* cls = raw_obj->ptr()->class_;
587 cls != cls->ptr()->class_;
588 cls = cls->ptr()->class_) {
589 RawArray* raw_array = cls->ptr()->fields_;
590 if (raw_array != Array::null()) {
591 intptr_t length = Smi::Value(raw_array->ptr()->length_);
592 uint8_t* base = reinterpret_cast<uint8_t*>(raw_obj->ptr());
593 for (intptr_t i = 0; i < length; ++i) {
594 RawField* raw_field =
595 reinterpret_cast<RawField*>(raw_array->ptr()->data()[i]);
596 if (!raw_field->ptr()->is_static_) {
597 intptr_t offset =
598 Smi::Value(reinterpret_cast<RawSmi*>(raw_field->ptr()->value_));
599 RawObject* ptr = *reinterpret_cast<RawObject**>(base + offset);
600 sub.WritePointer(ObjectId(ptr));
601 }
602 }
603 }
604 }
605 }
606
607
608 // OBJECT ARRAY DUMP - 0x22
609 //
610 // Format:
611 // ID - array object ID
612 // u4 - stack trace serial number
613 // u4 - number of elements
614 // ID - array class object ID
615 // [ID]* - elements
616 void HeapProfiler::WriteObjectArrayDump(const RawArray* raw_array) {
617 SubRecord sub(kObjectArrayDump, this);
618 // array object ID
619 sub.WritePointer(raw_array);
620 // stack trace serial number
621 sub.Write32(0);
622 // number of elements
623 intptr_t length = Smi::Value(raw_array->ptr()->length_);
624 sub.Write32(length);
625 // array class object ID
626 sub.WritePointer(NULL);
627 // elements
628 for (intptr_t i = 0; i < length; ++i) {
629 sub.WritePointer(ObjectId(raw_array->ptr()->data()[i]));
630 }
631 }
632
633
634 // PRIMITIVE ARRAY DUMP - 0x23
635 //
636 // Format:
637 // ID - array object ID
638 // u4 - stack trace serial number
639 // u4 - number of elements
640 // u1 - element type
641 // [u1]* - elements
642 void HeapProfiler::WritePrimitiveArrayDump(const RawByteArray* raw_byte_array,
643 uint8_t tag,
644 const void* data) {
645 SubRecord sub(kPrimitiveArrayDump, this);
646 // array object ID
647 sub.WritePointer(raw_byte_array);
648 // stack trace serial number
649 sub.Write32(0);
650 // number of elements
651 intptr_t length = Smi::Value(raw_byte_array->ptr()->length_);
652 sub.Write32(length);
653 // element type
654 sub.Write8(tag);
655 // elements (packed)
656 for (intptr_t i = 0; i < length; ++i) {
657 if (tag == kByte) {
658 sub.Write8(reinterpret_cast<const int8_t*>(data)[i]);
659 } else if (tag == kShort) {
660 sub.Write16(reinterpret_cast<const int16_t*>(data)[i]);
661 break;
662 } else if (tag == kInt || tag == kFloat) {
663 sub.Write32(reinterpret_cast<const int32_t*>(data)[i]);
664 } else {
665 ASSERT(tag == kLong || tag == kDouble);
666 sub.Write64(reinterpret_cast<const int64_t*>(data)[i]);
667 }
668 }
669 }
670
671
672 void HeapProfilerRootVisitor::VisitPointers(RawObject** first,
673 RawObject** last) {
674 for (RawObject** current = first; current <= last; current++) {
675 RawObject* raw_obj = *current;
676 if (raw_obj->IsHeapObject()) {
677 // Skip visits of FreeListElements.
678 if (FreeListElement::IsSpecialClass(raw_obj)) {
679 // Only the class of the free list element should ever be visited.
680 ASSERT(first == last);
681 return;
682 }
683 uword obj_addr = RawObject::ToAddr(raw_obj);
684 if (!Isolate::Current()->heap()->Contains(obj_addr) &&
685 !Dart::vm_isolate()->heap()->Contains(obj_addr)) {
686 FATAL1("Invalid object pointer encountered 0x%lx\n", obj_addr);
687 }
688 }
689 profiler_->WriteRoot(raw_obj);
690 }
691 }
692
693
694 void HeapProfilerWeakRootVisitor::VisitHandle(uword addr) {
695 FinalizablePersistentHandle* handle =
696 reinterpret_cast<FinalizablePersistentHandle*>(addr);
697 RawObject* raw_obj = handle->raw();
698 visitor_->VisitPointer(&raw_obj);
699 }
700
701
702 void HeapProfilerObjectVisitor::VisitObject(RawObject* raw_obj) {
703 profiler_->WriteObject(raw_obj);
704 }
705
706 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698