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 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1008 | 1008 |
1009 | 1009 |
1010 int HeapEntry::RetainedSize(bool exact) { | 1010 int HeapEntry::RetainedSize(bool exact) { |
1011 if (exact && (retained_size_ & kExactRetainedSizeTag) == 0) { | 1011 if (exact && (retained_size_ & kExactRetainedSizeTag) == 0) { |
1012 CalculateExactRetainedSize(); | 1012 CalculateExactRetainedSize(); |
1013 } | 1013 } |
1014 return retained_size_ & (~kExactRetainedSizeTag); | 1014 return retained_size_ & (~kExactRetainedSizeTag); |
1015 } | 1015 } |
1016 | 1016 |
1017 | 1017 |
| 1018 Handle<HeapObject> HeapEntry::GetHeapObject() { |
| 1019 return snapshot_->collection()->FindHeapObjectById(id()); |
| 1020 } |
| 1021 |
| 1022 |
1018 template<class Visitor> | 1023 template<class Visitor> |
1019 void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) { | 1024 void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) { |
1020 List<HeapEntry*> list(10); | 1025 List<HeapEntry*> list(10); |
1021 list.Add(this); | 1026 list.Add(this); |
1022 this->paint_reachable(); | 1027 this->paint_reachable(); |
1023 visitor->Apply(this); | 1028 visitor->Apply(this); |
1024 while (!list.is_empty()) { | 1029 while (!list.is_empty()) { |
1025 HeapEntry* entry = list.RemoveLast(); | 1030 HeapEntry* entry = list.RemoveLast(); |
1026 Vector<HeapGraphEdge> children = entry->children(); | 1031 Vector<HeapGraphEdge> children = entry->children(); |
1027 for (int i = 0; i < children.length(); ++i) { | 1032 for (int i = 0; i < children.length(); ++i) { |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1368 entries_map_(AddressesMatch), | 1373 entries_map_(AddressesMatch), |
1369 entries_(new List<EntryInfo>()) { } | 1374 entries_(new List<EntryInfo>()) { } |
1370 | 1375 |
1371 | 1376 |
1372 HeapObjectsMap::~HeapObjectsMap() { | 1377 HeapObjectsMap::~HeapObjectsMap() { |
1373 delete entries_; | 1378 delete entries_; |
1374 } | 1379 } |
1375 | 1380 |
1376 | 1381 |
1377 void HeapObjectsMap::SnapshotGenerationFinished() { | 1382 void HeapObjectsMap::SnapshotGenerationFinished() { |
1378 initial_fill_mode_ = false; | 1383 initial_fill_mode_ = false; |
1379 RemoveDeadEntries(); | 1384 RemoveDeadEntries(); |
1380 } | 1385 } |
1381 | 1386 |
1382 | 1387 |
1383 uint64_t HeapObjectsMap::FindObject(Address addr) { | 1388 uint64_t HeapObjectsMap::FindObject(Address addr) { |
1384 if (!initial_fill_mode_) { | 1389 if (!initial_fill_mode_) { |
1385 uint64_t existing = FindEntry(addr); | 1390 uint64_t existing = FindEntry(addr); |
1386 if (existing != 0) return existing; | 1391 if (existing != 0) return existing; |
1387 } | 1392 } |
1388 uint64_t id = next_id_; | 1393 uint64_t id = next_id_; |
1389 next_id_ += 2; | 1394 next_id_ += 2; |
1390 AddEntry(addr, id); | 1395 AddEntry(addr, id); |
1391 return id; | 1396 return id; |
1392 } | 1397 } |
1393 | 1398 |
1394 | 1399 |
1395 void HeapObjectsMap::MoveObject(Address from, Address to) { | 1400 void HeapObjectsMap::MoveObject(Address from, Address to) { |
1396 if (from == to) return; | 1401 if (from == to) return; |
1397 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); | 1402 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false); |
1398 if (entry != NULL) { | 1403 if (entry != NULL) { |
1399 void* value = entry->value; | 1404 void* value = entry->value; |
1400 entries_map_.Remove(from, AddressHash(from)); | 1405 entries_map_.Remove(from, AddressHash(from)); |
1401 entry = entries_map_.Lookup(to, AddressHash(to), true); | 1406 if (to != NULL) { |
1402 // We can have an entry at the new location, it is OK, as GC can overwrite | 1407 entry = entries_map_.Lookup(to, AddressHash(to), true); |
1403 // dead objects with alive objects being moved. | 1408 // We can have an entry at the new location, it is OK, as GC can overwrite |
1404 entry->value = value; | 1409 // dead objects with alive objects being moved. |
| 1410 entry->value = value; |
| 1411 } |
1405 } | 1412 } |
1406 } | 1413 } |
1407 | 1414 |
1408 | 1415 |
1409 void HeapObjectsMap::AddEntry(Address addr, uint64_t id) { | 1416 void HeapObjectsMap::AddEntry(Address addr, uint64_t id) { |
1410 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); | 1417 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); |
1411 ASSERT(entry->value == NULL); | 1418 ASSERT(entry->value == NULL); |
1412 entry->value = reinterpret_cast<void*>(entries_->length()); | 1419 entry->value = reinterpret_cast<void*>(entries_->length()); |
1413 entries_->Add(EntryInfo(id)); | 1420 entries_->Add(EntryInfo(id)); |
1414 } | 1421 } |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1515 | 1522 |
1516 | 1523 |
1517 void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) { | 1524 void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) { |
1518 snapshots_.RemoveElement(snapshot); | 1525 snapshots_.RemoveElement(snapshot); |
1519 unsigned uid = snapshot->uid(); | 1526 unsigned uid = snapshot->uid(); |
1520 snapshots_uids_.Remove(reinterpret_cast<void*>(uid), | 1527 snapshots_uids_.Remove(reinterpret_cast<void*>(uid), |
1521 static_cast<uint32_t>(uid)); | 1528 static_cast<uint32_t>(uid)); |
1522 } | 1529 } |
1523 | 1530 |
1524 | 1531 |
| 1532 Handle<HeapObject> HeapSnapshotsCollection::FindHeapObjectById(uint64_t id) { |
| 1533 // First perform a full GC in order to avoid dead objects. |
| 1534 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
| 1535 AssertNoAllocation no_allocation; |
| 1536 HeapObject* object = NULL; |
| 1537 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
| 1538 // Make sure that object with the given id is still reachable. |
| 1539 for (HeapObject* obj = iterator.next(); |
| 1540 obj != NULL; |
| 1541 obj = iterator.next()) { |
| 1542 if (ids_.FindObject(obj->address()) == id) { |
| 1543 ASSERT(object == NULL); |
| 1544 object = obj; |
| 1545 // Can't break -- kFilterUnreachable requires full heap traversal. |
| 1546 } |
| 1547 } |
| 1548 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>(); |
| 1549 } |
| 1550 |
| 1551 |
1525 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder = | 1552 HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder = |
1526 reinterpret_cast<HeapEntry*>(1); | 1553 reinterpret_cast<HeapEntry*>(1); |
1527 | 1554 |
1528 HeapEntriesMap::HeapEntriesMap() | 1555 HeapEntriesMap::HeapEntriesMap() |
1529 : entries_(HeapThingsMatch), | 1556 : entries_(HeapThingsMatch), |
1530 entries_count_(0), | 1557 entries_count_(0), |
1531 total_children_count_(0), | 1558 total_children_count_(0), |
1532 total_retainers_count_(0) { | 1559 total_retainers_count_(0) { |
1533 } | 1560 } |
1534 | 1561 |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1805 case ODDBALL_TYPE: return "system / Oddball"; | 1832 case ODDBALL_TYPE: return "system / Oddball"; |
1806 #define MAKE_STRUCT_CASE(NAME, Name, name) \ | 1833 #define MAKE_STRUCT_CASE(NAME, Name, name) \ |
1807 case NAME##_TYPE: return "system / "#Name; | 1834 case NAME##_TYPE: return "system / "#Name; |
1808 STRUCT_LIST(MAKE_STRUCT_CASE) | 1835 STRUCT_LIST(MAKE_STRUCT_CASE) |
1809 #undef MAKE_STRUCT_CASE | 1836 #undef MAKE_STRUCT_CASE |
1810 default: return "system"; | 1837 default: return "system"; |
1811 } | 1838 } |
1812 } | 1839 } |
1813 | 1840 |
1814 | 1841 |
1815 int V8HeapExplorer::EstimateObjectsCount() { | 1842 int V8HeapExplorer::EstimateObjectsCount(HeapIterator* iterator) { |
1816 HeapIterator iterator(HeapIterator::kFilterUnreachable); | |
1817 int objects_count = 0; | 1843 int objects_count = 0; |
1818 for (HeapObject* obj = iterator.next(); | 1844 for (HeapObject* obj = iterator->next(); |
1819 obj != NULL; | 1845 obj != NULL; |
1820 obj = iterator.next(), ++objects_count) {} | 1846 obj = iterator->next()) { |
| 1847 objects_count++; |
| 1848 } |
1821 return objects_count; | 1849 return objects_count; |
1822 } | 1850 } |
1823 | 1851 |
1824 | 1852 |
1825 class IndexedReferencesExtractor : public ObjectVisitor { | 1853 class IndexedReferencesExtractor : public ObjectVisitor { |
1826 public: | 1854 public: |
1827 IndexedReferencesExtractor(V8HeapExplorer* generator, | 1855 IndexedReferencesExtractor(V8HeapExplorer* generator, |
1828 HeapObject* parent_obj, | 1856 HeapObject* parent_obj, |
1829 HeapEntry* parent_entry) | 1857 HeapEntry* parent_entry) |
1830 : generator_(generator), | 1858 : generator_(generator), |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1938 "prototype", map->prototype(), Map::kPrototypeOffset); | 1966 "prototype", map->prototype(), Map::kPrototypeOffset); |
1939 SetInternalReference(obj, entry, | 1967 SetInternalReference(obj, entry, |
1940 "constructor", map->constructor(), | 1968 "constructor", map->constructor(), |
1941 Map::kConstructorOffset); | 1969 Map::kConstructorOffset); |
1942 if (!map->instance_descriptors()->IsEmpty()) { | 1970 if (!map->instance_descriptors()->IsEmpty()) { |
1943 TagObject(map->instance_descriptors(), "(map descriptors)"); | 1971 TagObject(map->instance_descriptors(), "(map descriptors)"); |
1944 SetInternalReference(obj, entry, | 1972 SetInternalReference(obj, entry, |
1945 "descriptors", map->instance_descriptors(), | 1973 "descriptors", map->instance_descriptors(), |
1946 Map::kInstanceDescriptorsOrBitField3Offset); | 1974 Map::kInstanceDescriptorsOrBitField3Offset); |
1947 } | 1975 } |
| 1976 if (map->prototype_transitions() != heap_->empty_fixed_array()) { |
| 1977 TagObject(map->prototype_transitions(), "(prototype transitions)"); |
| 1978 SetInternalReference(obj, |
| 1979 entry, |
| 1980 "prototype_transitions", |
| 1981 map->prototype_transitions(), |
| 1982 Map::kPrototypeTransitionsOffset); |
| 1983 } |
1948 SetInternalReference(obj, entry, | 1984 SetInternalReference(obj, entry, |
1949 "code_cache", map->code_cache(), | 1985 "code_cache", map->code_cache(), |
1950 Map::kCodeCacheOffset); | 1986 Map::kCodeCacheOffset); |
1951 } else if (obj->IsSharedFunctionInfo()) { | 1987 } else if (obj->IsSharedFunctionInfo()) { |
1952 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 1988 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
1953 SetInternalReference(obj, entry, | 1989 SetInternalReference(obj, entry, |
1954 "name", shared->name(), | 1990 "name", shared->name(), |
1955 SharedFunctionInfo::kNameOffset); | 1991 SharedFunctionInfo::kNameOffset); |
1956 SetInternalReference(obj, entry, | 1992 SetInternalReference(obj, entry, |
1957 "code", shared->unchecked_code(), | 1993 "code", shared->unchecked_code(), |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2168 void VisitPointers(Object** start, Object** end) { | 2204 void VisitPointers(Object** start, Object** end) { |
2169 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); | 2205 for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p); |
2170 } | 2206 } |
2171 private: | 2207 private: |
2172 V8HeapExplorer* explorer_; | 2208 V8HeapExplorer* explorer_; |
2173 }; | 2209 }; |
2174 | 2210 |
2175 | 2211 |
2176 bool V8HeapExplorer::IterateAndExtractReferences( | 2212 bool V8HeapExplorer::IterateAndExtractReferences( |
2177 SnapshotFillerInterface* filler) { | 2213 SnapshotFillerInterface* filler) { |
| 2214 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
| 2215 |
2178 filler_ = filler; | 2216 filler_ = filler; |
2179 HeapIterator iterator(HeapIterator::kFilterUnreachable); | |
2180 bool interrupted = false; | 2217 bool interrupted = false; |
| 2218 |
2181 // Heap iteration with filtering must be finished in any case. | 2219 // Heap iteration with filtering must be finished in any case. |
2182 for (HeapObject* obj = iterator.next(); | 2220 for (HeapObject* obj = iterator.next(); |
2183 obj != NULL; | 2221 obj != NULL; |
2184 obj = iterator.next(), progress_->ProgressStep()) { | 2222 obj = iterator.next(), progress_->ProgressStep()) { |
2185 if (!interrupted) { | 2223 if (!interrupted) { |
2186 ExtractReferences(obj); | 2224 ExtractReferences(obj); |
2187 if (!progress_->ProgressReport(false)) interrupted = true; | 2225 if (!progress_->ProgressReport(false)) interrupted = true; |
2188 } | 2226 } |
2189 } | 2227 } |
2190 if (interrupted) { | 2228 if (interrupted) { |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2736 private: | 2774 private: |
2737 HeapSnapshot* snapshot_; | 2775 HeapSnapshot* snapshot_; |
2738 HeapSnapshotsCollection* collection_; | 2776 HeapSnapshotsCollection* collection_; |
2739 HeapEntriesMap* entries_; | 2777 HeapEntriesMap* entries_; |
2740 }; | 2778 }; |
2741 | 2779 |
2742 | 2780 |
2743 bool HeapSnapshotGenerator::GenerateSnapshot() { | 2781 bool HeapSnapshotGenerator::GenerateSnapshot() { |
2744 v8_heap_explorer_.TagGlobalObjects(); | 2782 v8_heap_explorer_.TagGlobalObjects(); |
2745 | 2783 |
| 2784 // TODO(1562) Profiler assumes that any object that is in the heap after |
| 2785 // full GC is reachable from the root when computing dominators. |
| 2786 // This is not true for weakly reachable objects. |
| 2787 // As a temporary solution we call GC twice. |
| 2788 Isolate::Current()->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
| 2789 Isolate::Current()->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
| 2790 |
| 2791 #ifdef DEBUG |
| 2792 Heap* debug_heap = Isolate::Current()->heap(); |
| 2793 ASSERT(!debug_heap->old_data_space()->was_swept_conservatively()); |
| 2794 ASSERT(!debug_heap->old_pointer_space()->was_swept_conservatively()); |
| 2795 ASSERT(!debug_heap->code_space()->was_swept_conservatively()); |
| 2796 ASSERT(!debug_heap->cell_space()->was_swept_conservatively()); |
| 2797 ASSERT(!debug_heap->map_space()->was_swept_conservatively()); |
| 2798 #endif |
| 2799 |
| 2800 // The following code uses heap iterators, so we want the heap to be |
| 2801 // stable. It should follow TagGlobalObjects as that can allocate. |
2746 AssertNoAllocation no_alloc; | 2802 AssertNoAllocation no_alloc; |
2747 | 2803 |
| 2804 #ifdef DEBUG |
| 2805 debug_heap->Verify(); |
| 2806 #endif |
| 2807 |
2748 SetProgressTotal(4); // 2 passes + dominators + sizes. | 2808 SetProgressTotal(4); // 2 passes + dominators + sizes. |
2749 | 2809 |
| 2810 #ifdef DEBUG |
| 2811 debug_heap->Verify(); |
| 2812 #endif |
| 2813 |
2750 // Pass 1. Iterate heap contents to count entries and references. | 2814 // Pass 1. Iterate heap contents to count entries and references. |
2751 if (!CountEntriesAndReferences()) return false; | 2815 if (!CountEntriesAndReferences()) return false; |
2752 | 2816 |
| 2817 #ifdef DEBUG |
| 2818 debug_heap->Verify(); |
| 2819 #endif |
| 2820 |
2753 // Allocate and fill entries in the snapshot, allocate references. | 2821 // Allocate and fill entries in the snapshot, allocate references. |
2754 snapshot_->AllocateEntries(entries_.entries_count(), | 2822 snapshot_->AllocateEntries(entries_.entries_count(), |
2755 entries_.total_children_count(), | 2823 entries_.total_children_count(), |
2756 entries_.total_retainers_count()); | 2824 entries_.total_retainers_count()); |
2757 entries_.AllocateEntries(); | 2825 entries_.AllocateEntries(); |
2758 | 2826 |
2759 // Pass 2. Fill references. | 2827 // Pass 2. Fill references. |
2760 if (!FillReferences()) return false; | 2828 if (!FillReferences()) return false; |
2761 | 2829 |
2762 if (!SetEntriesDominators()) return false; | 2830 if (!SetEntriesDominators()) return false; |
(...skipping 17 matching lines...) Expand all Loading... |
2780 return | 2848 return |
2781 control_->ReportProgressValue(progress_counter_, progress_total_) == | 2849 control_->ReportProgressValue(progress_counter_, progress_total_) == |
2782 v8::ActivityControl::kContinue; | 2850 v8::ActivityControl::kContinue; |
2783 } | 2851 } |
2784 return true; | 2852 return true; |
2785 } | 2853 } |
2786 | 2854 |
2787 | 2855 |
2788 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { | 2856 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { |
2789 if (control_ == NULL) return; | 2857 if (control_ == NULL) return; |
| 2858 HeapIterator iterator(HeapIterator::kFilterUnreachable); |
2790 progress_total_ = ( | 2859 progress_total_ = ( |
2791 v8_heap_explorer_.EstimateObjectsCount() + | 2860 v8_heap_explorer_.EstimateObjectsCount(&iterator) + |
2792 dom_explorer_.EstimateObjectsCount()) * iterations_count; | 2861 dom_explorer_.EstimateObjectsCount()) * iterations_count; |
2793 progress_counter_ = 0; | 2862 progress_counter_ = 0; |
2794 } | 2863 } |
2795 | 2864 |
2796 | 2865 |
2797 bool HeapSnapshotGenerator::CountEntriesAndReferences() { | 2866 bool HeapSnapshotGenerator::CountEntriesAndReferences() { |
2798 SnapshotCounter counter(&entries_); | 2867 SnapshotCounter counter(&entries_); |
2799 v8_heap_explorer_.AddRootEntries(&counter); | 2868 v8_heap_explorer_.AddRootEntries(&counter); |
2800 dom_explorer_.AddRootEntries(&counter); | 2869 dom_explorer_.AddRootEntries(&counter); |
2801 return | 2870 return |
(...skipping 29 matching lines...) Expand all Loading... |
2831 child->paint_reachable(); | 2900 child->paint_reachable(); |
2832 has_new_edges = true; | 2901 has_new_edges = true; |
2833 } | 2902 } |
2834 } | 2903 } |
2835 if (!has_new_edges) { | 2904 if (!has_new_edges) { |
2836 entry->set_ordered_index(current_entry); | 2905 entry->set_ordered_index(current_entry); |
2837 (*entries)[current_entry++] = entry; | 2906 (*entries)[current_entry++] = entry; |
2838 nodes_to_visit.RemoveLast(); | 2907 nodes_to_visit.RemoveLast(); |
2839 } | 2908 } |
2840 } | 2909 } |
2841 entries->Truncate(current_entry); | 2910 ASSERT_EQ(current_entry, entries->length()); |
2842 } | 2911 } |
2843 | 2912 |
2844 | 2913 |
2845 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { | 2914 static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) { |
2846 int finger1 = i1, finger2 = i2; | 2915 int finger1 = i1, finger2 = i2; |
2847 while (finger1 != finger2) { | 2916 while (finger1 != finger2) { |
2848 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); | 2917 while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index(); |
2849 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); | 2918 while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index(); |
2850 } | 2919 } |
2851 return finger1; | 2920 return finger1; |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3326 | 3395 |
3327 | 3396 |
3328 void HeapSnapshotJSONSerializer::SortHashMap( | 3397 void HeapSnapshotJSONSerializer::SortHashMap( |
3329 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 3398 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
3330 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 3399 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
3331 sorted_entries->Add(p); | 3400 sorted_entries->Add(p); |
3332 sorted_entries->Sort(SortUsingEntryValue); | 3401 sorted_entries->Sort(SortUsingEntryValue); |
3333 } | 3402 } |
3334 | 3403 |
3335 } } // namespace v8::internal | 3404 } } // namespace v8::internal |
OLD | NEW |