Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 12 matching lines...) Expand all Loading... | |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "heap-snapshot-generator-inl.h" | 30 #include "heap-snapshot-generator-inl.h" |
| 31 | 31 |
| 32 #include "allocation-tracker.h" | 32 #include "allocation-tracker.h" |
| 33 #include "code-stubs.h" | |
| 33 #include "heap-profiler.h" | 34 #include "heap-profiler.h" |
| 34 #include "debug.h" | 35 #include "debug.h" |
| 35 #include "types.h" | 36 #include "types.h" |
| 36 | 37 |
| 37 namespace v8 { | 38 namespace v8 { |
| 38 namespace internal { | 39 namespace internal { |
| 39 | 40 |
| 40 | 41 |
| 41 HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to) | 42 HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to) |
| 42 : type_(type), | 43 : type_(type), |
| (...skipping 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1103 HeapObject* parent_obj, | 1104 HeapObject* parent_obj, |
| 1104 int parent) | 1105 int parent) |
| 1105 : generator_(generator), | 1106 : generator_(generator), |
| 1106 parent_obj_(parent_obj), | 1107 parent_obj_(parent_obj), |
| 1107 parent_(parent), | 1108 parent_(parent), |
| 1108 next_index_(0) { | 1109 next_index_(0) { |
| 1109 } | 1110 } |
| 1110 void VisitCodeEntry(Address entry_address) { | 1111 void VisitCodeEntry(Address entry_address) { |
| 1111 Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); | 1112 Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); |
| 1112 generator_->SetInternalReference(parent_obj_, parent_, "code", code); | 1113 generator_->SetInternalReference(parent_obj_, parent_, "code", code); |
| 1113 generator_->TagObject(code, "(code)"); | 1114 generator_->TagCodeObject(code); |
| 1114 } | 1115 } |
| 1115 void VisitPointers(Object** start, Object** end) { | 1116 void VisitPointers(Object** start, Object** end) { |
| 1116 for (Object** p = start; p < end; p++) { | 1117 for (Object** p = start; p < end; p++) { |
| 1117 if (CheckVisitedAndUnmark(p)) continue; | 1118 if (CheckVisitedAndUnmark(p)) continue; |
| 1118 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); | 1119 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); |
| 1119 } | 1120 } |
| 1120 } | 1121 } |
| 1121 static void MarkVisitedField(HeapObject* obj, int offset) { | 1122 static void MarkVisitedField(HeapObject* obj, int offset) { |
| 1122 if (offset < 0) return; | 1123 if (offset < 0) return; |
| 1123 Address field = obj->address() + offset; | 1124 Address field = obj->address() + offset; |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1363 TagObject(map->dependent_code(), "(dependent code)"); | 1364 TagObject(map->dependent_code(), "(dependent code)"); |
| 1364 SetInternalReference(map, entry, | 1365 SetInternalReference(map, entry, |
| 1365 "dependent_code", map->dependent_code(), | 1366 "dependent_code", map->dependent_code(), |
| 1366 Map::kDependentCodeOffset); | 1367 Map::kDependentCodeOffset); |
| 1367 } | 1368 } |
| 1368 | 1369 |
| 1369 | 1370 |
| 1370 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( | 1371 void V8HeapExplorer::ExtractSharedFunctionInfoReferences( |
| 1371 int entry, SharedFunctionInfo* shared) { | 1372 int entry, SharedFunctionInfo* shared) { |
| 1372 HeapObject* obj = shared; | 1373 HeapObject* obj = shared; |
| 1374 StringsStorage* names = collection_->names(); | |
| 1375 Object* shared_name = shared->DebugName(); | |
|
alph
2013/10/31 12:55:46
nit: DebugName returns String, so you should not n
loislo
2013/10/31 14:41:14
Done.
| |
| 1376 const char* name = NULL; | |
| 1377 if (shared_name != *heap_->isolate()->factory()->empty_string()) { | |
| 1378 name = names->GetName(Name::cast(shared_name)); | |
| 1379 TagObject(shared->code(), names->GetFormatted("(code for %s)", name)); | |
| 1380 } else { | |
| 1381 TagObject(shared->code(), names->GetFormatted("(%s code)", | |
| 1382 Code::Kind2String(shared->code()->kind()))); | |
|
yurys
2013/10/31 14:24:02
style: indent 4 characters
loislo
2013/10/31 14:41:14
Done.
| |
| 1383 } | |
| 1384 | |
| 1373 SetInternalReference(obj, entry, | 1385 SetInternalReference(obj, entry, |
| 1374 "name", shared->name(), | 1386 "name", shared->name(), |
| 1375 SharedFunctionInfo::kNameOffset); | 1387 SharedFunctionInfo::kNameOffset); |
| 1376 TagObject(shared->code(), "(code)"); | |
| 1377 SetInternalReference(obj, entry, | 1388 SetInternalReference(obj, entry, |
| 1378 "code", shared->code(), | 1389 "code", shared->code(), |
| 1379 SharedFunctionInfo::kCodeOffset); | 1390 SharedFunctionInfo::kCodeOffset); |
| 1380 TagObject(shared->scope_info(), "(function scope info)"); | 1391 TagObject(shared->scope_info(), "(function scope info)"); |
| 1381 SetInternalReference(obj, entry, | 1392 SetInternalReference(obj, entry, |
| 1382 "scope_info", shared->scope_info(), | 1393 "scope_info", shared->scope_info(), |
| 1383 SharedFunctionInfo::kScopeInfoOffset); | 1394 SharedFunctionInfo::kScopeInfoOffset); |
| 1384 SetInternalReference(obj, entry, | 1395 SetInternalReference(obj, entry, |
| 1385 "instance_class_name", shared->instance_class_name(), | 1396 "instance_class_name", shared->instance_class_name(), |
| 1386 SharedFunctionInfo::kInstanceClassNameOffset); | 1397 SharedFunctionInfo::kInstanceClassNameOffset); |
| 1387 SetInternalReference(obj, entry, | 1398 SetInternalReference(obj, entry, |
| 1388 "script", shared->script(), | 1399 "script", shared->script(), |
| 1389 SharedFunctionInfo::kScriptOffset); | 1400 SharedFunctionInfo::kScriptOffset); |
| 1390 TagObject(shared->construct_stub(), "(code)"); | 1401 const char* construct_stub_name = name ? |
| 1402 names->GetFormatted("(construct stub code for %s)", name) : | |
| 1403 "(construct stub code)"; | |
| 1404 TagObject(shared->construct_stub(), construct_stub_name); | |
| 1391 SetInternalReference(obj, entry, | 1405 SetInternalReference(obj, entry, |
| 1392 "construct_stub", shared->construct_stub(), | 1406 "construct_stub", shared->construct_stub(), |
| 1393 SharedFunctionInfo::kConstructStubOffset); | 1407 SharedFunctionInfo::kConstructStubOffset); |
| 1394 SetInternalReference(obj, entry, | 1408 SetInternalReference(obj, entry, |
| 1395 "function_data", shared->function_data(), | 1409 "function_data", shared->function_data(), |
| 1396 SharedFunctionInfo::kFunctionDataOffset); | 1410 SharedFunctionInfo::kFunctionDataOffset); |
| 1397 SetInternalReference(obj, entry, | 1411 SetInternalReference(obj, entry, |
| 1398 "debug_info", shared->debug_info(), | 1412 "debug_info", shared->debug_info(), |
| 1399 SharedFunctionInfo::kDebugInfoOffset); | 1413 SharedFunctionInfo::kDebugInfoOffset); |
| 1400 SetInternalReference(obj, entry, | 1414 SetInternalReference(obj, entry, |
| 1401 "inferred_name", shared->inferred_name(), | 1415 "inferred_name", shared->inferred_name(), |
| 1402 SharedFunctionInfo::kInferredNameOffset); | 1416 SharedFunctionInfo::kInferredNameOffset); |
| 1417 SetInternalReference(obj, entry, | |
| 1418 "optimized_code_map", shared->optimized_code_map(), | |
| 1419 SharedFunctionInfo::kOptimizedCodeMapOffset); | |
| 1403 SetWeakReference(obj, entry, | 1420 SetWeakReference(obj, entry, |
| 1404 1, shared->initial_map(), | 1421 1, shared->initial_map(), |
| 1405 SharedFunctionInfo::kInitialMapOffset); | 1422 SharedFunctionInfo::kInitialMapOffset); |
| 1406 } | 1423 } |
| 1407 | 1424 |
| 1408 | 1425 |
| 1409 void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { | 1426 void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { |
| 1410 HeapObject* obj = script; | 1427 HeapObject* obj = script; |
| 1411 SetInternalReference(obj, entry, | 1428 SetInternalReference(obj, entry, |
| 1412 "source", script->source(), | 1429 "source", script->source(), |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1442 SetInternalReference(code_cache, entry, | 1459 SetInternalReference(code_cache, entry, |
| 1443 "default_cache", code_cache->default_cache(), | 1460 "default_cache", code_cache->default_cache(), |
| 1444 CodeCache::kDefaultCacheOffset); | 1461 CodeCache::kDefaultCacheOffset); |
| 1445 TagObject(code_cache->normal_type_cache(), "(code type cache)"); | 1462 TagObject(code_cache->normal_type_cache(), "(code type cache)"); |
| 1446 SetInternalReference(code_cache, entry, | 1463 SetInternalReference(code_cache, entry, |
| 1447 "type_cache", code_cache->normal_type_cache(), | 1464 "type_cache", code_cache->normal_type_cache(), |
| 1448 CodeCache::kNormalTypeCacheOffset); | 1465 CodeCache::kNormalTypeCacheOffset); |
| 1449 } | 1466 } |
| 1450 | 1467 |
| 1451 | 1468 |
| 1469 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { | |
| 1470 StringsStorage* names = collection_->names(); | |
| 1471 if (external_name) { | |
| 1472 TagObject(code, names->GetFormatted("(%s code)", external_name)); | |
| 1473 return; | |
| 1474 } | |
| 1475 switch (code->kind()) { | |
| 1476 case Code::STUB: { | |
|
yurys
2013/10/31 14:24:02
if (code->kind() == Code::STUB) { would be more co
alph
2013/10/31 14:28:38
... and make the function overloaded ;-)
loislo
2013/10/31 14:41:14
Done.
loislo
2013/10/31 14:41:14
Done.
| |
| 1477 TagObject(code, names->GetFormatted("(%s code)", | |
| 1478 CodeStub::MajorName(static_cast<CodeStub::Major>(code->major_key()), | |
| 1479 true))); | |
| 1480 break; | |
| 1481 } | |
| 1482 default: { | |
| 1483 break; | |
| 1484 } | |
| 1485 } | |
| 1486 } | |
| 1487 | |
| 1488 | |
| 1452 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { | 1489 void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { |
| 1490 TagCodeObject(code); | |
| 1453 TagObject(code->relocation_info(), "(code relocation info)"); | 1491 TagObject(code->relocation_info(), "(code relocation info)"); |
| 1454 SetInternalReference(code, entry, | 1492 SetInternalReference(code, entry, |
| 1455 "relocation_info", code->relocation_info(), | 1493 "relocation_info", code->relocation_info(), |
| 1456 Code::kRelocationInfoOffset); | 1494 Code::kRelocationInfoOffset); |
| 1457 SetInternalReference(code, entry, | 1495 SetInternalReference(code, entry, |
| 1458 "handler_table", code->handler_table(), | 1496 "handler_table", code->handler_table(), |
| 1459 Code::kHandlerTableOffset); | 1497 Code::kHandlerTableOffset); |
| 1460 TagObject(code->deoptimization_data(), "(code deopt data)"); | 1498 TagObject(code->deoptimization_data(), "(code deopt data)"); |
| 1461 SetInternalReference(code, entry, | 1499 SetInternalReference(code, entry, |
| 1462 "deoptimization_data", code->deoptimization_data(), | 1500 "deoptimization_data", code->deoptimization_data(), |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1688 class RootsReferencesExtractor : public ObjectVisitor { | 1726 class RootsReferencesExtractor : public ObjectVisitor { |
| 1689 private: | 1727 private: |
| 1690 struct IndexTag { | 1728 struct IndexTag { |
| 1691 IndexTag(int index, VisitorSynchronization::SyncTag tag) | 1729 IndexTag(int index, VisitorSynchronization::SyncTag tag) |
| 1692 : index(index), tag(tag) { } | 1730 : index(index), tag(tag) { } |
| 1693 int index; | 1731 int index; |
| 1694 VisitorSynchronization::SyncTag tag; | 1732 VisitorSynchronization::SyncTag tag; |
| 1695 }; | 1733 }; |
| 1696 | 1734 |
| 1697 public: | 1735 public: |
| 1698 RootsReferencesExtractor() | 1736 explicit RootsReferencesExtractor(Heap* heap) |
| 1699 : collecting_all_references_(false), | 1737 : collecting_all_references_(false), |
| 1700 previous_reference_count_(0) { | 1738 previous_reference_count_(0), |
| 1739 heap_(heap) { | |
| 1701 } | 1740 } |
| 1702 | 1741 |
| 1703 void VisitPointers(Object** start, Object** end) { | 1742 void VisitPointers(Object** start, Object** end) { |
| 1704 if (collecting_all_references_) { | 1743 if (collecting_all_references_) { |
| 1705 for (Object** p = start; p < end; p++) all_references_.Add(*p); | 1744 for (Object** p = start; p < end; p++) all_references_.Add(*p); |
| 1706 } else { | 1745 } else { |
| 1707 for (Object** p = start; p < end; p++) strong_references_.Add(*p); | 1746 for (Object** p = start; p < end; p++) strong_references_.Add(*p); |
| 1708 } | 1747 } |
| 1709 } | 1748 } |
| 1710 | 1749 |
| 1711 void SetCollectingAllReferences() { collecting_all_references_ = true; } | 1750 void SetCollectingAllReferences() { collecting_all_references_ = true; } |
| 1712 | 1751 |
| 1713 void FillReferences(V8HeapExplorer* explorer) { | 1752 void FillReferences(V8HeapExplorer* explorer) { |
| 1714 ASSERT(strong_references_.length() <= all_references_.length()); | 1753 ASSERT(strong_references_.length() <= all_references_.length()); |
| 1754 Builtins* builtins = heap_->isolate()->builtins(); | |
| 1715 for (int i = 0; i < reference_tags_.length(); ++i) { | 1755 for (int i = 0; i < reference_tags_.length(); ++i) { |
| 1716 explorer->SetGcRootsReference(reference_tags_[i].tag); | 1756 explorer->SetGcRootsReference(reference_tags_[i].tag); |
| 1717 } | 1757 } |
| 1718 int strong_index = 0, all_index = 0, tags_index = 0; | 1758 int strong_index = 0, all_index = 0, tags_index = 0, prev_tag_index = 0; |
|
alph
2013/10/31 12:55:46
maybe prev_tag_index -> tag_first_index ?
| |
| 1719 while (all_index < all_references_.length()) { | 1759 while (all_index < all_references_.length()) { |
| 1720 if (strong_index < strong_references_.length() && | 1760 if (strong_index < strong_references_.length() && |
| 1721 strong_references_[strong_index] == all_references_[all_index]) { | 1761 strong_references_[strong_index] == all_references_[all_index]) { |
| 1722 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, | 1762 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
| 1723 false, | 1763 false, |
| 1724 all_references_[all_index++]); | 1764 all_references_[all_index]); |
| 1725 ++strong_index; | 1765 ++strong_index; |
| 1726 } else { | 1766 } else { |
| 1727 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, | 1767 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, |
| 1728 true, | 1768 true, |
| 1729 all_references_[all_index++]); | 1769 all_references_[all_index]); |
| 1730 } | 1770 } |
| 1731 if (reference_tags_[tags_index].index == all_index) ++tags_index; | 1771 if (reference_tags_[tags_index].tag == VisitorSynchronization::kBuiltins |
| 1772 && all_references_[all_index]->IsCode()) { | |
|
yurys
2013/10/31 14:24:02
This should always be a code. But we can leave thi
loislo
2013/10/31 14:41:14
I'll make ASSERT(all_references_[all_index]->IsCod
| |
| 1773 explorer->TagCodeObject(Code::cast(all_references_[all_index]), | |
| 1774 builtins->name(all_index - prev_tag_index)); | |
|
yurys
2013/10/31 14:24:02
Can we replace this prev_tag_index with builtin_in
alph
2013/10/31 14:28:38
I'd event move the increment inside if
loislo
2013/10/31 14:41:14
Done.
| |
| 1775 } | |
| 1776 ++all_index; | |
| 1777 if (reference_tags_[tags_index].index == all_index) { | |
|
yurys
2013/10/31 14:24:02
As discussed offline this should be
while (refere
yurys
2013/11/01 14:55:04
On the second look the current implementation is c
| |
| 1778 prev_tag_index = all_index; | |
| 1779 ++tags_index; | |
| 1780 } | |
| 1732 } | 1781 } |
| 1733 } | 1782 } |
| 1734 | 1783 |
| 1735 void Synchronize(VisitorSynchronization::SyncTag tag) { | 1784 void Synchronize(VisitorSynchronization::SyncTag tag) { |
| 1736 if (collecting_all_references_ && | 1785 if (collecting_all_references_ && |
| 1737 previous_reference_count_ != all_references_.length()) { | 1786 previous_reference_count_ != all_references_.length()) { |
| 1738 previous_reference_count_ = all_references_.length(); | 1787 previous_reference_count_ = all_references_.length(); |
| 1739 reference_tags_.Add(IndexTag(previous_reference_count_, tag)); | 1788 reference_tags_.Add(IndexTag(previous_reference_count_, tag)); |
| 1740 } | 1789 } |
| 1741 } | 1790 } |
| 1742 | 1791 |
| 1743 private: | 1792 private: |
| 1744 bool collecting_all_references_; | 1793 bool collecting_all_references_; |
| 1745 List<Object*> strong_references_; | 1794 List<Object*> strong_references_; |
| 1746 List<Object*> all_references_; | 1795 List<Object*> all_references_; |
| 1747 int previous_reference_count_; | 1796 int previous_reference_count_; |
| 1748 List<IndexTag> reference_tags_; | 1797 List<IndexTag> reference_tags_; |
| 1798 Heap* heap_; | |
| 1749 }; | 1799 }; |
| 1750 | 1800 |
| 1751 | 1801 |
| 1752 bool V8HeapExplorer::IterateAndExtractReferences( | 1802 bool V8HeapExplorer::IterateAndExtractReferences( |
| 1753 SnapshotFillerInterface* filler) { | 1803 SnapshotFillerInterface* filler) { |
| 1754 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); | 1804 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); |
| 1755 | 1805 |
| 1756 filler_ = filler; | 1806 filler_ = filler; |
| 1757 bool interrupted = false; | 1807 bool interrupted = false; |
| 1758 | 1808 |
| 1759 // Heap iteration with filtering must be finished in any case. | 1809 // Heap iteration with filtering must be finished in any case. |
| 1760 for (HeapObject* obj = iterator.next(); | 1810 for (HeapObject* obj = iterator.next(); |
| 1761 obj != NULL; | 1811 obj != NULL; |
| 1762 obj = iterator.next(), progress_->ProgressStep()) { | 1812 obj = iterator.next(), progress_->ProgressStep()) { |
| 1763 if (!interrupted) { | 1813 if (!interrupted) { |
| 1764 ExtractReferences(obj); | 1814 ExtractReferences(obj); |
| 1765 if (!progress_->ProgressReport(false)) interrupted = true; | 1815 if (!progress_->ProgressReport(false)) interrupted = true; |
| 1766 } | 1816 } |
| 1767 } | 1817 } |
| 1768 if (interrupted) { | 1818 if (interrupted) { |
| 1769 filler_ = NULL; | 1819 filler_ = NULL; |
| 1770 return false; | 1820 return false; |
| 1771 } | 1821 } |
| 1772 | 1822 |
| 1773 SetRootGcRootsReference(); | 1823 SetRootGcRootsReference(); |
| 1774 RootsReferencesExtractor extractor; | 1824 RootsReferencesExtractor extractor(heap_); |
| 1775 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); | 1825 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); |
| 1776 extractor.SetCollectingAllReferences(); | 1826 extractor.SetCollectingAllReferences(); |
| 1777 heap_->IterateRoots(&extractor, VISIT_ALL); | 1827 heap_->IterateRoots(&extractor, VISIT_ALL); |
| 1778 extractor.FillReferences(this); | 1828 extractor.FillReferences(this); |
| 1779 filler_ = NULL; | 1829 filler_ = NULL; |
| 1780 return progress_->ProgressReport(true); | 1830 return progress_->ProgressReport(true); |
| 1781 } | 1831 } |
| 1782 | 1832 |
| 1783 | 1833 |
| 1784 bool V8HeapExplorer::IsEssentialObject(Object* object) { | 1834 bool V8HeapExplorer::IsEssentialObject(Object* object) { |
| (...skipping 1241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3026 writer_->AddString("\"<dummy>\""); | 3076 writer_->AddString("\"<dummy>\""); |
| 3027 for (int i = 1; i < sorted_strings.length(); ++i) { | 3077 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 3028 writer_->AddCharacter(','); | 3078 writer_->AddCharacter(','); |
| 3029 SerializeString(sorted_strings[i]); | 3079 SerializeString(sorted_strings[i]); |
| 3030 if (writer_->aborted()) return; | 3080 if (writer_->aborted()) return; |
| 3031 } | 3081 } |
| 3032 } | 3082 } |
| 3033 | 3083 |
| 3034 | 3084 |
| 3035 } } // namespace v8::internal | 3085 } } // namespace v8::internal |
| OLD | NEW |