OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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/heap_profiler.h" | 5 #include "vm/heap_profiler.h" |
6 | 6 |
7 #include "vm/dart_api_state.h" | 7 #include "vm/dart_api_state.h" |
8 #include "vm/object.h" | 8 #include "vm/object.h" |
9 #include "vm/raw_object.h" | 9 #include "vm/raw_object.h" |
10 #include "vm/stack_frame.h" | 10 #include "vm/stack_frame.h" |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 | 129 |
130 | 130 |
131 const RawObject* HeapProfiler::ObjectId(const RawObject* raw_obj) { | 131 const RawObject* HeapProfiler::ObjectId(const RawObject* raw_obj) { |
132 if (!raw_obj->IsHeapObject()) { | 132 if (!raw_obj->IsHeapObject()) { |
133 // To describe an immediate object in HPROF we record its value | 133 // To describe an immediate object in HPROF we record its value |
134 // and write fake INSTANCE_DUMP subrecord in the HEAP_DUMP record. | 134 // and write fake INSTANCE_DUMP subrecord in the HEAP_DUMP record. |
135 const RawSmi* raw_smi = reinterpret_cast<const RawSmi*>(raw_obj); | 135 const RawSmi* raw_smi = reinterpret_cast<const RawSmi*>(raw_obj); |
136 if (smi_table_.find(raw_smi) == smi_table_.end()) { | 136 if (smi_table_.find(raw_smi) == smi_table_.end()) { |
137 smi_table_.insert(raw_smi); | 137 smi_table_.insert(raw_smi); |
138 } | 138 } |
139 } else if (raw_obj->GetClassId() == kNullClassId) { | 139 } else if (raw_obj->GetClassId() == kNullCid) { |
140 // Instances of the Null type are translated to NULL so they can | 140 // Instances of the Null type are translated to NULL so they can |
141 // be printed as "null" in HAT. | 141 // be printed as "null" in HAT. |
142 return NULL; | 142 return NULL; |
143 } | 143 } |
144 return raw_obj; | 144 return raw_obj; |
145 } | 145 } |
146 | 146 |
147 | 147 |
148 const RawClass* HeapProfiler::ClassId(const RawClass* raw_class) { | 148 const RawClass* HeapProfiler::ClassId(const RawClass* raw_class) { |
149 // A unique LOAD_CLASS record must be written for each class object. | 149 // A unique LOAD_CLASS record must be written for each class object. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 | 195 |
196 | 196 |
197 void HeapProfiler::WriteRoot(const RawObject* raw_obj) { | 197 void HeapProfiler::WriteRoot(const RawObject* raw_obj) { |
198 SubRecord sub(kRootUnknown, this); | 198 SubRecord sub(kRootUnknown, this); |
199 sub.WritePointer(ObjectId(raw_obj)); | 199 sub.WritePointer(ObjectId(raw_obj)); |
200 } | 200 } |
201 | 201 |
202 | 202 |
203 void HeapProfiler::WriteObject(const RawObject* raw_obj) { | 203 void HeapProfiler::WriteObject(const RawObject* raw_obj) { |
204 ASSERT(raw_obj->IsHeapObject()); | 204 ASSERT(raw_obj->IsHeapObject()); |
205 ObjectKind kind = raw_obj->GetObjectKind(); | 205 intptr_t class_id = raw_obj->GetClassId(); |
206 switch (kind) { | 206 switch (class_id) { |
207 case kFreeListElement: { | 207 case kFreeListElement: { |
208 // Free space has an object-like encoding. Heap profiles only | 208 // Free space has an object-like encoding. Heap profiles only |
209 // care about live objects so we skip over these records. | 209 // care about live objects so we skip over these records. |
210 break; | 210 break; |
211 } | 211 } |
212 case Class::kInstanceKind: { | 212 case kClassCid: { |
213 const RawClass* raw_class = reinterpret_cast<const RawClass*>(raw_obj); | 213 const RawClass* raw_class = reinterpret_cast<const RawClass*>(raw_obj); |
214 if (raw_class->ptr()->instance_kind_ == kFreeListElement) { | 214 if (raw_class->ptr()->id_ == kFreeListElement) { |
215 // Skip over the FreeListElement class. This class exists to | 215 // Skip over the FreeListElement class. This class exists to |
216 // describe free space. | 216 // describe free space. |
217 break; | 217 break; |
218 } | 218 } |
219 WriteClassDump(raw_class); | 219 WriteClassDump(raw_class); |
220 break; | 220 break; |
221 } | 221 } |
222 case Array::kInstanceKind: | 222 case kArrayCid: |
223 case ImmutableArray::kInstanceKind: { | 223 case kImmutableArrayCid: { |
224 WriteObjectArrayDump(reinterpret_cast<const RawArray*>(raw_obj)); | 224 WriteObjectArrayDump(reinterpret_cast<const RawArray*>(raw_obj)); |
225 break; | 225 break; |
226 } | 226 } |
227 case Int8Array::kInstanceKind: | 227 case kInt8ArrayCid: |
228 case Uint8Array::kInstanceKind: { | 228 case kUint8ArrayCid: { |
229 const RawInt8Array* raw_int8_array = | 229 const RawInt8Array* raw_int8_array = |
230 reinterpret_cast<const RawInt8Array*>(raw_obj); | 230 reinterpret_cast<const RawInt8Array*>(raw_obj); |
231 WritePrimitiveArrayDump(raw_int8_array, | 231 WritePrimitiveArrayDump(raw_int8_array, |
232 kByte, | 232 kByte, |
233 &raw_int8_array->data_[0]); | 233 &raw_int8_array->data_[0]); |
234 break; | 234 break; |
235 } | 235 } |
236 case Int16Array::kInstanceKind: | 236 case kInt16ArrayCid: |
237 case Uint16Array::kInstanceKind: { | 237 case kUint16ArrayCid: { |
238 const RawInt16Array* raw_int16_array = | 238 const RawInt16Array* raw_int16_array = |
239 reinterpret_cast<const RawInt16Array*>(raw_obj); | 239 reinterpret_cast<const RawInt16Array*>(raw_obj); |
240 WritePrimitiveArrayDump(raw_int16_array, | 240 WritePrimitiveArrayDump(raw_int16_array, |
241 kShort, | 241 kShort, |
242 &raw_int16_array->data_[0]); | 242 &raw_int16_array->data_[0]); |
243 break; | 243 break; |
244 } | 244 } |
245 case Int32Array::kInstanceKind: | 245 case kInt32ArrayCid: |
246 case Uint32Array::kInstanceKind: { | 246 case kUint32ArrayCid: { |
247 const RawInt32Array* raw_int32_array = | 247 const RawInt32Array* raw_int32_array = |
248 reinterpret_cast<const RawInt32Array*>(raw_obj); | 248 reinterpret_cast<const RawInt32Array*>(raw_obj); |
249 WritePrimitiveArrayDump(raw_int32_array, | 249 WritePrimitiveArrayDump(raw_int32_array, |
250 kInt, | 250 kInt, |
251 &raw_int32_array->data_[0]); | 251 &raw_int32_array->data_[0]); |
252 break; | 252 break; |
253 } | 253 } |
254 case Int64Array::kInstanceKind: | 254 case kInt64ArrayCid: |
255 case Uint64Array::kInstanceKind: { | 255 case kUint64ArrayCid: { |
256 const RawInt64Array* raw_int64_array = | 256 const RawInt64Array* raw_int64_array = |
257 reinterpret_cast<const RawInt64Array*>(raw_obj); | 257 reinterpret_cast<const RawInt64Array*>(raw_obj); |
258 WritePrimitiveArrayDump(raw_int64_array, | 258 WritePrimitiveArrayDump(raw_int64_array, |
259 kLong, | 259 kLong, |
260 &raw_int64_array->data_[0]); | 260 &raw_int64_array->data_[0]); |
261 break; | 261 break; |
262 } | 262 } |
263 case Float32Array::kInstanceKind: { | 263 case kFloat32ArrayCid: { |
264 const RawFloat32Array* raw_float32_array = | 264 const RawFloat32Array* raw_float32_array = |
265 reinterpret_cast<const RawFloat32Array*>(raw_obj); | 265 reinterpret_cast<const RawFloat32Array*>(raw_obj); |
266 WritePrimitiveArrayDump(raw_float32_array, | 266 WritePrimitiveArrayDump(raw_float32_array, |
267 kFloat, | 267 kFloat, |
268 &raw_float32_array->data_[0]); | 268 &raw_float32_array->data_[0]); |
269 break; | 269 break; |
270 } | 270 } |
271 case Float64Array::kInstanceKind: { | 271 case kFloat64ArrayCid: { |
272 const RawFloat64Array* raw_float64_array = | 272 const RawFloat64Array* raw_float64_array = |
273 reinterpret_cast<const RawFloat64Array*>(raw_obj); | 273 reinterpret_cast<const RawFloat64Array*>(raw_obj); |
274 WritePrimitiveArrayDump(raw_float64_array, | 274 WritePrimitiveArrayDump(raw_float64_array, |
275 kDouble, | 275 kDouble, |
276 &raw_float64_array->data_[0]); | 276 &raw_float64_array->data_[0]); |
277 break; | 277 break; |
278 } | 278 } |
279 case OneByteString::kInstanceKind: | 279 case kOneByteStringCid: |
280 case TwoByteString::kInstanceKind: | 280 case kTwoByteStringCid: |
281 case FourByteString::kInstanceKind: | 281 case kFourByteStringCid: |
282 case ExternalOneByteString::kInstanceKind: | 282 case kExternalOneByteStringCid: |
283 case ExternalTwoByteString::kInstanceKind: | 283 case kExternalTwoByteStringCid: |
284 case ExternalFourByteString::kInstanceKind: { | 284 case kExternalFourByteStringCid: { |
285 WriteInstanceDump(StringId(reinterpret_cast<const RawString*>(raw_obj))); | 285 WriteInstanceDump(StringId(reinterpret_cast<const RawString*>(raw_obj))); |
286 break; | 286 break; |
287 } | 287 } |
288 default: | 288 default: |
289 WriteInstanceDump(raw_obj); | 289 WriteInstanceDump(raw_obj); |
290 } | 290 } |
291 } | 291 } |
292 | 292 |
293 | 293 |
294 void HeapProfiler::Write(const void* data, intptr_t size) { | 294 void HeapProfiler::Write(const void* data, intptr_t size) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 | 336 |
337 | 337 |
338 // STRING IN UTF8 - 0x01 | 338 // STRING IN UTF8 - 0x01 |
339 // | 339 // |
340 // Format: | 340 // Format: |
341 // ID - ID for this string | 341 // ID - ID for this string |
342 // [u1]* - UTF8 characters for string (NOT NULL terminated) | 342 // [u1]* - UTF8 characters for string (NOT NULL terminated) |
343 void HeapProfiler::WriteStringInUtf8(const RawString* raw_string) { | 343 void HeapProfiler::WriteStringInUtf8(const RawString* raw_string) { |
344 intptr_t length = 0; | 344 intptr_t length = 0; |
345 char* characters = NULL; | 345 char* characters = NULL; |
346 ObjectKind kind = raw_string->GetObjectKind(); | 346 intptr_t class_id = raw_string->GetClassId(); |
347 if (kind == OneByteString::kInstanceKind) { | 347 if (class_id == kOneByteStringCid) { |
348 const RawOneByteString* onestr = | 348 const RawOneByteString* onestr = |
349 reinterpret_cast<const RawOneByteString*>(raw_string); | 349 reinterpret_cast<const RawOneByteString*>(raw_string); |
350 for (intptr_t i = 0; i < Smi::Value(onestr->ptr()->length_); ++i) { | 350 for (intptr_t i = 0; i < Smi::Value(onestr->ptr()->length_); ++i) { |
351 length += Utf8::Length(onestr->ptr()->data_[i]); | 351 length += Utf8::Length(onestr->ptr()->data_[i]); |
352 } | 352 } |
353 characters = new char[length]; | 353 characters = new char[length]; |
354 for (intptr_t i = 0, j = 0; i < Smi::Value(onestr->ptr()->length_); ++i) { | 354 for (intptr_t i = 0, j = 0; i < Smi::Value(onestr->ptr()->length_); ++i) { |
355 int32_t ch = onestr->ptr()->data_[i]; | 355 int32_t ch = onestr->ptr()->data_[i]; |
356 j += Utf8::Encode(ch, &characters[j]); | 356 j += Utf8::Encode(ch, &characters[j]); |
357 } | 357 } |
358 } else if (kind == TwoByteString::kInstanceKind) { | 358 } else if (class_id == kTwoByteStringCid) { |
359 const RawTwoByteString* twostr = | 359 const RawTwoByteString* twostr = |
360 reinterpret_cast<const RawTwoByteString*>(raw_string); | 360 reinterpret_cast<const RawTwoByteString*>(raw_string); |
361 for (intptr_t i = 0; i < Smi::Value(twostr->ptr()->length_); ++i) { | 361 for (intptr_t i = 0; i < Smi::Value(twostr->ptr()->length_); ++i) { |
362 length += Utf8::Length(twostr->ptr()->data_[i]); | 362 length += Utf8::Length(twostr->ptr()->data_[i]); |
363 } | 363 } |
364 characters = new char[length]; | 364 characters = new char[length]; |
365 for (intptr_t i = 0, j = 0; i < Smi::Value(twostr->ptr()->length_); ++i) { | 365 for (intptr_t i = 0, j = 0; i < Smi::Value(twostr->ptr()->length_); ++i) { |
366 int32_t ch = twostr->ptr()->data_[i]; | 366 int32_t ch = twostr->ptr()->data_[i]; |
367 j += Utf8::Encode(ch, &characters[j]); | 367 j += Utf8::Encode(ch, &characters[j]); |
368 } | 368 } |
369 } else { | 369 } else { |
370 ASSERT(kind == FourByteString::kInstanceKind); | 370 ASSERT(class_id == kFourByteStringCid); |
371 const RawFourByteString* fourstr = | 371 const RawFourByteString* fourstr = |
372 reinterpret_cast<const RawFourByteString*>(raw_string); | 372 reinterpret_cast<const RawFourByteString*>(raw_string); |
373 for (intptr_t i = 0; i < Smi::Value(fourstr->ptr()->length_); ++i) { | 373 for (intptr_t i = 0; i < Smi::Value(fourstr->ptr()->length_); ++i) { |
374 length += Utf8::Length(fourstr->ptr()->data_[i]); | 374 length += Utf8::Length(fourstr->ptr()->data_[i]); |
375 } | 375 } |
376 characters = new char[length]; | 376 characters = new char[length]; |
377 for (intptr_t i = 0, j = 0; i < Smi::Value(fourstr->ptr()->length_); ++i) { | 377 for (intptr_t i = 0, j = 0; i < Smi::Value(fourstr->ptr()->length_); ++i) { |
378 int32_t ch = fourstr->ptr()->data_[i]; | 378 int32_t ch = fourstr->ptr()->data_[i]; |
379 j += Utf8::Encode(ch, &characters[j]); | 379 j += Utf8::Encode(ch, &characters[j]); |
380 } | 380 } |
(...skipping 25 matching lines...) Expand all Loading... |
406 // ID - class name string ID | 406 // ID - class name string ID |
407 void HeapProfiler::WriteLoadClass(const RawClass* raw_class) { | 407 void HeapProfiler::WriteLoadClass(const RawClass* raw_class) { |
408 Record record(kLoadClass, this); | 408 Record record(kLoadClass, this); |
409 // class serial number (always > 0) | 409 // class serial number (always > 0) |
410 record.Write32(1); | 410 record.Write32(1); |
411 // class object ID | 411 // class object ID |
412 record.WritePointer(raw_class); | 412 record.WritePointer(raw_class); |
413 // stack trace serial number | 413 // stack trace serial number |
414 record.Write32(0); | 414 record.Write32(0); |
415 if (raw_class->ptr()->name_ == String::null()) { | 415 if (raw_class->ptr()->name_ == String::null()) { |
416 intptr_t class_index = Object::GetSingletonClassIndex(raw_class); | 416 intptr_t class_id = raw_class->ptr()->id_; |
417 const char* name = Object::GetSingletonClassName(class_index); | 417 const char* name = Object::GetSingletonClassName(class_id); |
418 record.WritePointer(StringId(name)); | 418 record.WritePointer(StringId(name)); |
419 } else { | 419 } else { |
420 record.WritePointer(StringId(raw_class->ptr()->name_)); | 420 record.WritePointer(StringId(raw_class->ptr()->name_)); |
421 } | 421 } |
422 } | 422 } |
423 | 423 |
424 | 424 |
425 // STACK TRACE - 0x05 | 425 // STACK TRACE - 0x05 |
426 // | 426 // |
427 // u4 - stack trace serial number | 427 // u4 - stack trace serial number |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 } | 691 } |
692 } | 692 } |
693 | 693 |
694 | 694 |
695 void HeapProfilerRootVisitor::VisitPointers(RawObject** first, | 695 void HeapProfilerRootVisitor::VisitPointers(RawObject** first, |
696 RawObject** last) { | 696 RawObject** last) { |
697 for (RawObject** current = first; current <= last; current++) { | 697 for (RawObject** current = first; current <= last; current++) { |
698 RawObject* raw_obj = *current; | 698 RawObject* raw_obj = *current; |
699 if (raw_obj->IsHeapObject()) { | 699 if (raw_obj->IsHeapObject()) { |
700 // Skip visits of FreeListElements. | 700 // Skip visits of FreeListElements. |
701 if (raw_obj->GetObjectKind() == kFreeListElement) { | 701 if (raw_obj->GetClassId() == kFreeListElement) { |
702 // Only the class of the free list element should ever be visited. | 702 // Only the class of the free list element should ever be visited. |
703 ASSERT(first == last); | 703 ASSERT(first == last); |
704 return; | 704 return; |
705 } | 705 } |
706 uword obj_addr = RawObject::ToAddr(raw_obj); | 706 uword obj_addr = RawObject::ToAddr(raw_obj); |
707 if (!Isolate::Current()->heap()->Contains(obj_addr) && | 707 if (!Isolate::Current()->heap()->Contains(obj_addr) && |
708 !Dart::vm_isolate()->heap()->Contains(obj_addr)) { | 708 !Dart::vm_isolate()->heap()->Contains(obj_addr)) { |
709 FATAL1("Invalid object pointer encountered 0x%lx\n", obj_addr); | 709 FATAL1("Invalid object pointer encountered 0x%lx\n", obj_addr); |
710 } | 710 } |
711 } | 711 } |
712 profiler_->WriteRoot(raw_obj); | 712 profiler_->WriteRoot(raw_obj); |
713 } | 713 } |
714 } | 714 } |
715 | 715 |
716 | 716 |
717 void HeapProfilerWeakRootVisitor::VisitHandle(uword addr) { | 717 void HeapProfilerWeakRootVisitor::VisitHandle(uword addr) { |
718 FinalizablePersistentHandle* handle = | 718 FinalizablePersistentHandle* handle = |
719 reinterpret_cast<FinalizablePersistentHandle*>(addr); | 719 reinterpret_cast<FinalizablePersistentHandle*>(addr); |
720 RawObject* raw_obj = handle->raw(); | 720 RawObject* raw_obj = handle->raw(); |
721 visitor_->VisitPointer(&raw_obj); | 721 visitor_->VisitPointer(&raw_obj); |
722 } | 722 } |
723 | 723 |
724 | 724 |
725 void HeapProfilerObjectVisitor::VisitObject(RawObject* raw_obj) { | 725 void HeapProfilerObjectVisitor::VisitObject(RawObject* raw_obj) { |
726 profiler_->WriteObject(raw_obj); | 726 profiler_->WriteObject(raw_obj); |
727 } | 727 } |
728 | 728 |
729 } // namespace dart | 729 } // namespace dart |
OLD | NEW |