| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 return name[type]; | 158 return name[type]; |
| 159 } | 159 } |
| 160 | 160 |
| 161 | 161 |
| 162 const char* GetObjectTypeDesc(HeapObject* heap_obj) { | 162 const char* GetObjectTypeDesc(HeapObject* heap_obj) { |
| 163 LiveObjectType type = GetObjectType(heap_obj); | 163 LiveObjectType type = GetObjectType(heap_obj); |
| 164 return GetObjectTypeDesc(type); | 164 return GetObjectTypeDesc(type); |
| 165 } | 165 } |
| 166 | 166 |
| 167 | 167 |
| 168 bool IsOfType(LiveObjectType type, HeapObject *obj) { | 168 bool IsOfType(LiveObjectType type, HeapObject* obj) { |
| 169 // Note: there are types that are more general (e.g. JSObject) that would | 169 // Note: there are types that are more general (e.g. JSObject) that would |
| 170 // have passed the Is##type_() test for more specialized types (e.g. | 170 // have passed the Is##type_() test for more specialized types (e.g. |
| 171 // JSFunction). If we find a more specialized match but we're looking for | 171 // JSFunction). If we find a more specialized match but we're looking for |
| 172 // the general type, then we should reject the ones that matches the | 172 // the general type, then we should reject the ones that matches the |
| 173 // specialized type. | 173 // specialized type. |
| 174 #define CHECK_OBJECT_TYPE(type_, name) \ | 174 #define CHECK_OBJECT_TYPE(type_, name) \ |
| 175 if (obj->Is##type_()) return (type == kType##type_); | 175 if (obj->Is##type_()) return (type == kType##type_); |
| 176 | 176 |
| 177 FOR_EACH_LIVE_OBJECT_TYPE(CHECK_OBJECT_TYPE) | 177 FOR_EACH_LIVE_OBJECT_TYPE(CHECK_OBJECT_TYPE) |
| 178 #undef CHECK_OBJECT_TYPE | 178 #undef CHECK_OBJECT_TYPE |
| (...skipping 25 matching lines...) Expand all Loading... |
| 204 break; | 204 break; |
| 205 case 'o': | 205 case 'o': |
| 206 if (strcmp(key_str, "old-pointer") == 0) return OLD_POINTER_SPACE; | 206 if (strcmp(key_str, "old-pointer") == 0) return OLD_POINTER_SPACE; |
| 207 if (strcmp(key_str, "old-data") == 0) return OLD_DATA_SPACE; | 207 if (strcmp(key_str, "old-data") == 0) return OLD_DATA_SPACE; |
| 208 break; | 208 break; |
| 209 } | 209 } |
| 210 return kInvalidSpace; | 210 return kInvalidSpace; |
| 211 } | 211 } |
| 212 | 212 |
| 213 | 213 |
| 214 static bool InSpace(AllocationSpace space, HeapObject *heap_obj) { | 214 static bool InSpace(AllocationSpace space, HeapObject* heap_obj) { |
| 215 Heap* heap = ISOLATE->heap(); | 215 Heap* heap = ISOLATE->heap(); |
| 216 if (space != LO_SPACE) { | 216 if (space != LO_SPACE) { |
| 217 return heap->InSpace(heap_obj, space); | 217 return heap->InSpace(heap_obj, space); |
| 218 } | 218 } |
| 219 | 219 |
| 220 // This is an optimization to speed up the check for an object in the LO | 220 // This is an optimization to speed up the check for an object in the LO |
| 221 // space by exclusion because we know that all object pointers passed in | 221 // space by exclusion because we know that all object pointers passed in |
| 222 // here are guaranteed to be in the heap. Hence, it is safe to infer | 222 // here are guaranteed to be in the heap. Hence, it is safe to infer |
| 223 // using an exclusion test. | 223 // using an exclusion test. |
| 224 // Note: calling Heap::InSpace(heap_obj, LO_SPACE) is too slow for our | 224 // Note: calling Heap::InSpace(heap_obj, LO_SPACE) is too slow for our |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 if (obj->IsJSArray()) { | 491 if (obj->IsJSArray()) { |
| 492 JSArray* jsarray = JSArray::cast(obj); | 492 JSArray* jsarray = JSArray::cast(obj); |
| 493 double length = jsarray->length()->Number(); | 493 double length = jsarray->length()->Number(); |
| 494 OS::SNPrintF(buffer_v, | 494 OS::SNPrintF(buffer_v, |
| 495 "%p <%s> len %g", | 495 "%p <%s> len %g", |
| 496 reinterpret_cast<void*>(obj), | 496 reinterpret_cast<void*>(obj), |
| 497 GetObjectTypeDesc(obj), | 497 GetObjectTypeDesc(obj), |
| 498 length); | 498 length); |
| 499 | 499 |
| 500 } else if (obj->IsString()) { | 500 } else if (obj->IsString()) { |
| 501 String *str = String::cast(obj); | 501 String* str = String::cast(obj); |
| 502 // Only grab up to 160 chars in case they are double byte. | 502 // Only grab up to 160 chars in case they are double byte. |
| 503 // We'll only dump 80 of them after we compact them. | 503 // We'll only dump 80 of them after we compact them. |
| 504 const int kMaxCharToDump = 80; | 504 const int kMaxCharToDump = 80; |
| 505 const int kMaxBufferSize = kMaxCharToDump * 2; | 505 const int kMaxBufferSize = kMaxCharToDump * 2; |
| 506 SmartArrayPointer<char> str_sp = str->ToCString(DISALLOW_NULLS, | 506 SmartArrayPointer<char> str_sp = str->ToCString(DISALLOW_NULLS, |
| 507 ROBUST_STRING_TRAVERSAL, | 507 ROBUST_STRING_TRAVERSAL, |
| 508 0, | 508 0, |
| 509 kMaxBufferSize); | 509 kMaxBufferSize); |
| 510 char* str_cstr = *str_sp; | 510 char* str_cstr = *str_sp; |
| 511 int length = CompactString(str_cstr); | 511 int length = CompactString(str_cstr); |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 static const int kNumberOfEntries = kNumberOfTypes; | 835 static const int kNumberOfEntries = kNumberOfTypes; |
| 836 | 836 |
| 837 private: | 837 private: |
| 838 int counts_[kNumberOfEntries]; | 838 int counts_[kNumberOfEntries]; |
| 839 int sizes_[kNumberOfEntries]; | 839 int sizes_[kNumberOfEntries]; |
| 840 int total_count_; | 840 int total_count_; |
| 841 int total_size_; | 841 int total_size_; |
| 842 bool found_root_; | 842 bool found_root_; |
| 843 bool found_weak_root_; | 843 bool found_weak_root_; |
| 844 | 844 |
| 845 LolFilter *filter_; | 845 LolFilter* filter_; |
| 846 }; | 846 }; |
| 847 | 847 |
| 848 | 848 |
| 849 // Abstraction for a summary writer. | 849 // Abstraction for a summary writer. |
| 850 class SummaryWriter { | 850 class SummaryWriter { |
| 851 public: | 851 public: |
| 852 virtual ~SummaryWriter() {} | 852 virtual ~SummaryWriter() {} |
| 853 virtual void Write(LiveObjectSummary* summary) = 0; | 853 virtual void Write(LiveObjectSummary* summary) = 0; |
| 854 }; | 854 }; |
| 855 | 855 |
| 856 | 856 |
| 857 // A summary writer for filling in a summary of lol lists and diffs. | 857 // A summary writer for filling in a summary of lol lists and diffs. |
| 858 class LolSummaryWriter: public SummaryWriter { | 858 class LolSummaryWriter: public SummaryWriter { |
| 859 public: | 859 public: |
| 860 LolSummaryWriter(LiveObjectList *older_lol, | 860 LolSummaryWriter(LiveObjectList* older_lol, |
| 861 LiveObjectList *newer_lol) | 861 LiveObjectList* newer_lol) |
| 862 : older_(older_lol), newer_(newer_lol) { | 862 : older_(older_lol), newer_(newer_lol) { |
| 863 } | 863 } |
| 864 | 864 |
| 865 void Write(LiveObjectSummary* summary) { | 865 void Write(LiveObjectSummary* summary) { |
| 866 LolFilter* filter = summary->filter(); | 866 LolFilter* filter = summary->filter(); |
| 867 | 867 |
| 868 // Fill the summary with the lol object details. | 868 // Fill the summary with the lol object details. |
| 869 LolIterator it(older_, newer_); | 869 LolIterator it(older_, newer_); |
| 870 for (it.Init(); !it.Done(); it.Next()) { | 870 for (it.Init(); !it.Done(); it.Next()) { |
| 871 HeapObject* heap_obj = it.Obj(); | 871 HeapObject* heap_obj = it.Obj(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 937 | 937 |
| 938 LiveObjectList::~LiveObjectList() { | 938 LiveObjectList::~LiveObjectList() { |
| 939 DeleteArray<Element>(elements_); | 939 DeleteArray<Element>(elements_); |
| 940 delete prev_; | 940 delete prev_; |
| 941 } | 941 } |
| 942 | 942 |
| 943 | 943 |
| 944 int LiveObjectList::GetTotalObjCountAndSize(int* size_p) { | 944 int LiveObjectList::GetTotalObjCountAndSize(int* size_p) { |
| 945 int size = 0; | 945 int size = 0; |
| 946 int count = 0; | 946 int count = 0; |
| 947 LiveObjectList *lol = this; | 947 LiveObjectList* lol = this; |
| 948 do { | 948 do { |
| 949 // Only compute total size if requested i.e. when size_p is not null. | 949 // Only compute total size if requested i.e. when size_p is not null. |
| 950 if (size_p != NULL) { | 950 if (size_p != NULL) { |
| 951 Element* elements = lol->elements_; | 951 Element* elements = lol->elements_; |
| 952 for (int i = 0; i < lol->obj_count_; i++) { | 952 for (int i = 0; i < lol->obj_count_; i++) { |
| 953 HeapObject* heap_obj = elements[i].obj_; | 953 HeapObject* heap_obj = elements[i].obj_; |
| 954 size += heap_obj->Size(); | 954 size += heap_obj->Size(); |
| 955 } | 955 } |
| 956 } | 956 } |
| 957 count += lol->obj_count_; | 957 count += lol->obj_count_; |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1176 | 1176 |
| 1177 return *result; | 1177 return *result; |
| 1178 } | 1178 } |
| 1179 | 1179 |
| 1180 | 1180 |
| 1181 // Delete doesn't actually deletes an lol. It just marks it as invisible since | 1181 // Delete doesn't actually deletes an lol. It just marks it as invisible since |
| 1182 // its contents are considered to be part of subsequent lists as well. The | 1182 // its contents are considered to be part of subsequent lists as well. The |
| 1183 // only time we'll actually delete the lol is when we Reset() or if the lol is | 1183 // only time we'll actually delete the lol is when we Reset() or if the lol is |
| 1184 // invisible, and its element count reaches 0. | 1184 // invisible, and its element count reaches 0. |
| 1185 bool LiveObjectList::Delete(int id) { | 1185 bool LiveObjectList::Delete(int id) { |
| 1186 LiveObjectList *lol = last(); | 1186 LiveObjectList* lol = last(); |
| 1187 while (lol != NULL) { | 1187 while (lol != NULL) { |
| 1188 if (lol->id() == id) { | 1188 if (lol->id() == id) { |
| 1189 break; | 1189 break; |
| 1190 } | 1190 } |
| 1191 lol = lol->prev_; | 1191 lol = lol->prev_; |
| 1192 } | 1192 } |
| 1193 | 1193 |
| 1194 // If no lol is found for this id, then we fail to delete. | 1194 // If no lol is found for this id, then we fail to delete. |
| 1195 if (lol == NULL) return false; | 1195 if (lol == NULL) return false; |
| 1196 | 1196 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) { | 1239 if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) { |
| 1240 return Failure::Exception(); // Fail: 0 is not a valid lol id. | 1240 return Failure::Exception(); // Fail: 0 is not a valid lol id. |
| 1241 } | 1241 } |
| 1242 if (newer_id < older_id) { | 1242 if (newer_id < older_id) { |
| 1243 // They are not in the expected order. Swap them. | 1243 // They are not in the expected order. Swap them. |
| 1244 int temp = older_id; | 1244 int temp = older_id; |
| 1245 older_id = newer_id; | 1245 older_id = newer_id; |
| 1246 newer_id = temp; | 1246 newer_id = temp; |
| 1247 } | 1247 } |
| 1248 | 1248 |
| 1249 LiveObjectList *newer_lol = FindLolForId(newer_id, last()); | 1249 LiveObjectList* newer_lol = FindLolForId(newer_id, last()); |
| 1250 LiveObjectList *older_lol = FindLolForId(older_id, newer_lol); | 1250 LiveObjectList* older_lol = FindLolForId(older_id, newer_lol); |
| 1251 | 1251 |
| 1252 // If the id is defined, and we can't find a LOL for it, then we have an | 1252 // If the id is defined, and we can't find a LOL for it, then we have an |
| 1253 // invalid id. | 1253 // invalid id. |
| 1254 if ((newer_id != 0) && (newer_lol == NULL)) { | 1254 if ((newer_id != 0) && (newer_lol == NULL)) { |
| 1255 return Failure::Exception(); // Fail: the newer lol id is invalid. | 1255 return Failure::Exception(); // Fail: the newer lol id is invalid. |
| 1256 } | 1256 } |
| 1257 if ((older_id != 0) && (older_lol == NULL)) { | 1257 if ((older_id != 0) && (older_lol == NULL)) { |
| 1258 return Failure::Exception(); // Fail: the older lol id is invalid. | 1258 return Failure::Exception(); // Fail: the older lol id is invalid. |
| 1259 } | 1259 } |
| 1260 | 1260 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) { | 1358 if ((older_id < 0) || (newer_id < 0) || (last() == NULL)) { |
| 1359 return Failure::Exception(); // Fail: 0 is not a valid lol id. | 1359 return Failure::Exception(); // Fail: 0 is not a valid lol id. |
| 1360 } | 1360 } |
| 1361 if (newer_id < older_id) { | 1361 if (newer_id < older_id) { |
| 1362 // They are not in the expected order. Swap them. | 1362 // They are not in the expected order. Swap them. |
| 1363 int temp = older_id; | 1363 int temp = older_id; |
| 1364 older_id = newer_id; | 1364 older_id = newer_id; |
| 1365 newer_id = temp; | 1365 newer_id = temp; |
| 1366 } | 1366 } |
| 1367 | 1367 |
| 1368 LiveObjectList *newer_lol = FindLolForId(newer_id, last()); | 1368 LiveObjectList* newer_lol = FindLolForId(newer_id, last()); |
| 1369 LiveObjectList *older_lol = FindLolForId(older_id, newer_lol); | 1369 LiveObjectList* older_lol = FindLolForId(older_id, newer_lol); |
| 1370 | 1370 |
| 1371 // If the id is defined, and we can't find a LOL for it, then we have an | 1371 // If the id is defined, and we can't find a LOL for it, then we have an |
| 1372 // invalid id. | 1372 // invalid id. |
| 1373 if ((newer_id != 0) && (newer_lol == NULL)) { | 1373 if ((newer_id != 0) && (newer_lol == NULL)) { |
| 1374 return Failure::Exception(); // Fail: the newer lol id is invalid. | 1374 return Failure::Exception(); // Fail: the newer lol id is invalid. |
| 1375 } | 1375 } |
| 1376 if ((older_id != 0) && (older_lol == NULL)) { | 1376 if ((older_id != 0) && (older_lol == NULL)) { |
| 1377 return Failure::Exception(); // Fail: the older lol id is invalid. | 1377 return Failure::Exception(); // Fail: the older lol id is invalid. |
| 1378 } | 1378 } |
| 1379 | 1379 |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 NONE, | 1619 NONE, |
| 1620 kNonStrictMode); | 1620 kNonStrictMode); |
| 1621 if (maybe_result->IsFailure()) return maybe_result; | 1621 if (maybe_result->IsFailure()) return maybe_result; |
| 1622 | 1622 |
| 1623 return *result; | 1623 return *result; |
| 1624 } | 1624 } |
| 1625 | 1625 |
| 1626 | 1626 |
| 1627 // Deletes all captured lols. | 1627 // Deletes all captured lols. |
| 1628 void LiveObjectList::Reset() { | 1628 void LiveObjectList::Reset() { |
| 1629 LiveObjectList *lol = last(); | 1629 LiveObjectList* lol = last(); |
| 1630 // Just delete the last. Each lol will delete it's prev automatically. | 1630 // Just delete the last. Each lol will delete it's prev automatically. |
| 1631 delete lol; | 1631 delete lol; |
| 1632 | 1632 |
| 1633 next_element_id_ = 1; | 1633 next_element_id_ = 1; |
| 1634 list_count_ = 0; | 1634 list_count_ = 0; |
| 1635 last_id_ = 0; | 1635 last_id_ = 0; |
| 1636 first_ = NULL; | 1636 first_ = NULL; |
| 1637 last_ = NULL; | 1637 last_ = NULL; |
| 1638 } | 1638 } |
| 1639 | 1639 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1708 } | 1708 } |
| 1709 | 1709 |
| 1710 HeapObject* target_; | 1710 HeapObject* target_; |
| 1711 Handle<HeapObject> handle_to_skip_; | 1711 Handle<HeapObject> handle_to_skip_; |
| 1712 bool found_; | 1712 bool found_; |
| 1713 }; | 1713 }; |
| 1714 | 1714 |
| 1715 | 1715 |
| 1716 inline bool AddRootRetainerIfFound(const LolVisitor& visitor, | 1716 inline bool AddRootRetainerIfFound(const LolVisitor& visitor, |
| 1717 LolFilter* filter, | 1717 LolFilter* filter, |
| 1718 LiveObjectSummary *summary, | 1718 LiveObjectSummary* summary, |
| 1719 void (*SetRootFound)(LiveObjectSummary *s), | 1719 void (*SetRootFound)(LiveObjectSummary* s), |
| 1720 int start, | 1720 int start, |
| 1721 int dump_limit, | 1721 int dump_limit, |
| 1722 int* total_count, | 1722 int* total_count, |
| 1723 Handle<FixedArray> retainers_arr, | 1723 Handle<FixedArray> retainers_arr, |
| 1724 int* count, | 1724 int* count, |
| 1725 int* index, | 1725 int* index, |
| 1726 const char* root_name, | 1726 const char* root_name, |
| 1727 Handle<String> id_sym, | 1727 Handle<String> id_sym, |
| 1728 Handle<String> desc_sym, | 1728 Handle<String> desc_sym, |
| 1729 Handle<String> size_sym, | 1729 Handle<String> size_sym, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1755 desc, | 1755 desc, |
| 1756 error); | 1756 error); |
| 1757 } | 1757 } |
| 1758 } | 1758 } |
| 1759 } | 1759 } |
| 1760 } | 1760 } |
| 1761 return true; | 1761 return true; |
| 1762 } | 1762 } |
| 1763 | 1763 |
| 1764 | 1764 |
| 1765 inline void SetFoundRoot(LiveObjectSummary *summary) { | 1765 inline void SetFoundRoot(LiveObjectSummary* summary) { |
| 1766 summary->set_found_root(); | 1766 summary->set_found_root(); |
| 1767 } | 1767 } |
| 1768 | 1768 |
| 1769 | 1769 |
| 1770 inline void SetFoundWeakRoot(LiveObjectSummary *summary) { | 1770 inline void SetFoundWeakRoot(LiveObjectSummary* summary) { |
| 1771 summary->set_found_weak_root(); | 1771 summary->set_found_weak_root(); |
| 1772 } | 1772 } |
| 1773 | 1773 |
| 1774 | 1774 |
| 1775 int LiveObjectList::GetRetainers(Handle<HeapObject> target, | 1775 int LiveObjectList::GetRetainers(Handle<HeapObject> target, |
| 1776 Handle<JSObject> instance_filter, | 1776 Handle<JSObject> instance_filter, |
| 1777 Handle<FixedArray> retainers_arr, | 1777 Handle<FixedArray> retainers_arr, |
| 1778 int start, | 1778 int start, |
| 1779 int dump_limit, | 1779 int dump_limit, |
| 1780 int* total_count, | 1780 int* total_count, |
| 1781 LolFilter* filter, | 1781 LolFilter* filter, |
| 1782 LiveObjectSummary *summary, | 1782 LiveObjectSummary* summary, |
| 1783 JSFunction* arguments_function, | 1783 JSFunction* arguments_function, |
| 1784 Handle<Object> error) { | 1784 Handle<Object> error) { |
| 1785 HandleScope scope; | 1785 HandleScope scope; |
| 1786 | 1786 |
| 1787 // Scratch handles. | 1787 // Scratch handles. |
| 1788 Handle<JSObject> detail; | 1788 Handle<JSObject> detail; |
| 1789 Handle<String> desc; | 1789 Handle<String> desc; |
| 1790 Handle<HeapObject> retainer; | 1790 Handle<HeapObject> retainer; |
| 1791 | 1791 |
| 1792 Isolate* isolate = Isolate::Current(); | 1792 Isolate* isolate = Isolate::Current(); |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2260 | 2260 |
| 2261 HeapObject* obj2 = HeapObject::cast(GetObj(obj_id2)); | 2261 HeapObject* obj2 = HeapObject::cast(GetObj(obj_id2)); |
| 2262 if (obj2 == HEAP->undefined_value()) { | 2262 if (obj2 == HEAP->undefined_value()) { |
| 2263 return obj2; | 2263 return obj2; |
| 2264 } | 2264 } |
| 2265 | 2265 |
| 2266 return GetPathPrivate(obj1, obj2); | 2266 return GetPathPrivate(obj1, obj2); |
| 2267 } | 2267 } |
| 2268 | 2268 |
| 2269 | 2269 |
| 2270 void LiveObjectList::DoProcessNonLive(HeapObject *obj) { | 2270 void LiveObjectList::DoProcessNonLive(HeapObject* obj) { |
| 2271 // We should only be called if we have at least one lol to search. | 2271 // We should only be called if we have at least one lol to search. |
| 2272 ASSERT(last() != NULL); | 2272 ASSERT(last() != NULL); |
| 2273 Element* element = last()->Find(obj); | 2273 Element* element = last()->Find(obj); |
| 2274 if (element != NULL) { | 2274 if (element != NULL) { |
| 2275 NullifyNonLivePointer(&element->obj_); | 2275 NullifyNonLivePointer(&element->obj_); |
| 2276 } | 2276 } |
| 2277 } | 2277 } |
| 2278 | 2278 |
| 2279 | 2279 |
| 2280 void LiveObjectList::IterateElementsPrivate(ObjectVisitor* v) { | 2280 void LiveObjectList::IterateElementsPrivate(ObjectVisitor* v) { |
| 2281 LiveObjectList* lol = last(); | 2281 LiveObjectList* lol = last(); |
| 2282 while (lol != NULL) { | 2282 while (lol != NULL) { |
| 2283 Element* elements = lol->elements_; | 2283 Element* elements = lol->elements_; |
| 2284 int count = lol->obj_count_; | 2284 int count = lol->obj_count_; |
| 2285 for (int i = 0; i < count; i++) { | 2285 for (int i = 0; i < count; i++) { |
| 2286 HeapObject** p = &elements[i].obj_; | 2286 HeapObject** p = &elements[i].obj_; |
| 2287 v->VisitPointer(reinterpret_cast<Object **>(p)); | 2287 v->VisitPointer(reinterpret_cast<Object** >(p)); |
| 2288 } | 2288 } |
| 2289 lol = lol->prev_; | 2289 lol = lol->prev_; |
| 2290 } | 2290 } |
| 2291 } | 2291 } |
| 2292 | 2292 |
| 2293 | 2293 |
| 2294 // Purpose: Called by GCEpilogue to purge duplicates. Not to be called by | 2294 // Purpose: Called by GCEpilogue to purge duplicates. Not to be called by |
| 2295 // anyone else. | 2295 // anyone else. |
| 2296 void LiveObjectList::PurgeDuplicates() { | 2296 void LiveObjectList::PurgeDuplicates() { |
| 2297 bool is_sorted = false; | 2297 bool is_sorted = false; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2382 // to the start of these free chunks. Since there is no free or move event | 2382 // to the start of these free chunks. Since there is no free or move event |
| 2383 // for the free chunks, their addresses will show up 2 times: once for their | 2383 // for the free chunks, their addresses will show up 2 times: once for their |
| 2384 // original free ByteArray selves, and once for the newly promoted youngGen | 2384 // original free ByteArray selves, and once for the newly promoted youngGen |
| 2385 // object. Hence, we can get a duplicate address in the LOL again. | 2385 // object. Hence, we can get a duplicate address in the LOL again. |
| 2386 // | 2386 // |
| 2387 // We need to eliminate these dups because the LOL implementation expects to | 2387 // We need to eliminate these dups because the LOL implementation expects to |
| 2388 // only have at most one unique LOL reference to any object at any time. | 2388 // only have at most one unique LOL reference to any object at any time. |
| 2389 PurgeDuplicates(); | 2389 PurgeDuplicates(); |
| 2390 | 2390 |
| 2391 // After the GC, sweep away all free'd Elements and compact. | 2391 // After the GC, sweep away all free'd Elements and compact. |
| 2392 LiveObjectList *prev = NULL; | 2392 LiveObjectList* prev = NULL; |
| 2393 LiveObjectList *next = NULL; | 2393 LiveObjectList* next = NULL; |
| 2394 | 2394 |
| 2395 // Iterating from the youngest lol to the oldest lol. | 2395 // Iterating from the youngest lol to the oldest lol. |
| 2396 for (LiveObjectList *lol = last(); lol; lol = prev) { | 2396 for (LiveObjectList* lol = last(); lol; lol = prev) { |
| 2397 Element* elements = lol->elements_; | 2397 Element* elements = lol->elements_; |
| 2398 prev = lol->prev(); // Save the prev. | 2398 prev = lol->prev(); // Save the prev. |
| 2399 | 2399 |
| 2400 // Remove any references to collected objects. | 2400 // Remove any references to collected objects. |
| 2401 int i = 0; | 2401 int i = 0; |
| 2402 while (i < lol->obj_count_) { | 2402 while (i < lol->obj_count_) { |
| 2403 Element& element = elements[i]; | 2403 Element& element = elements[i]; |
| 2404 if (!element.obj_->IsHeapObject()) { | 2404 if (!element.obj_->IsHeapObject()) { |
| 2405 // If the HeapObject address was converted into a SMI, then this | 2405 // If the HeapObject address was converted into a SMI, then this |
| 2406 // is a dead object. Copy the last element over this one. | 2406 // is a dead object. Copy the last element over this one. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2439 continue; | 2439 continue; |
| 2440 } | 2440 } |
| 2441 | 2441 |
| 2442 } else { | 2442 } else { |
| 2443 // If the obj_count_ is less than the capacity and the difference is | 2443 // If the obj_count_ is less than the capacity and the difference is |
| 2444 // greater than a specified threshold, then we should shrink the list. | 2444 // greater than a specified threshold, then we should shrink the list. |
| 2445 int diff = lol->capacity_ - new_count; | 2445 int diff = lol->capacity_ - new_count; |
| 2446 const int kMaxUnusedSpace = 64; | 2446 const int kMaxUnusedSpace = 64; |
| 2447 if (diff > kMaxUnusedSpace) { // Threshold for shrinking. | 2447 if (diff > kMaxUnusedSpace) { // Threshold for shrinking. |
| 2448 // Shrink the list. | 2448 // Shrink the list. |
| 2449 Element *new_elements = NewArray<Element>(new_count); | 2449 Element* new_elements = NewArray<Element>(new_count); |
| 2450 memcpy(new_elements, elements, new_count * sizeof(Element)); | 2450 memcpy(new_elements, elements, new_count * sizeof(Element)); |
| 2451 | 2451 |
| 2452 DeleteArray<Element>(elements); | 2452 DeleteArray<Element>(elements); |
| 2453 lol->elements_ = new_elements; | 2453 lol->elements_ = new_elements; |
| 2454 lol->capacity_ = new_count; | 2454 lol->capacity_ = new_count; |
| 2455 } | 2455 } |
| 2456 ASSERT(lol->obj_count_ == new_count); | 2456 ASSERT(lol->obj_count_ == new_count); |
| 2457 | 2457 |
| 2458 lol->Sort(); // We've moved objects. Re-sort in case. | 2458 lol->Sort(); // We've moved objects. Re-sort in case. |
| 2459 } | 2459 } |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2622 i++, heap_obj, Heap::new_space()->FromSpaceStart()); | 2622 i++, heap_obj, Heap::new_space()->FromSpaceStart()); |
| 2623 } | 2623 } |
| 2624 } | 2624 } |
| 2625 } | 2625 } |
| 2626 #endif // VERIFY_LOL | 2626 #endif // VERIFY_LOL |
| 2627 | 2627 |
| 2628 | 2628 |
| 2629 } } // namespace v8::internal | 2629 } } // namespace v8::internal |
| 2630 | 2630 |
| 2631 #endif // LIVE_OBJECT_LIST | 2631 #endif // LIVE_OBJECT_LIST |
| OLD | NEW |