| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 | 129 |
| 130 // Will be 4 * reserved_semispace_size_ to ensure that young | 130 // Will be 4 * reserved_semispace_size_ to ensure that young |
| 131 // generation can be aligned to its size. | 131 // generation can be aligned to its size. |
| 132 int Heap::survived_since_last_expansion_ = 0; | 132 int Heap::survived_since_last_expansion_ = 0; |
| 133 intptr_t Heap::external_allocation_limit_ = 0; | 133 intptr_t Heap::external_allocation_limit_ = 0; |
| 134 | 134 |
| 135 Heap::HeapState Heap::gc_state_ = NOT_IN_GC; | 135 Heap::HeapState Heap::gc_state_ = NOT_IN_GC; |
| 136 | 136 |
| 137 int Heap::mc_count_ = 0; | 137 int Heap::mc_count_ = 0; |
| 138 int Heap::ms_count_ = 0; | 138 int Heap::ms_count_ = 0; |
| 139 int Heap::gc_count_ = 0; | 139 unsigned int Heap::gc_count_ = 0; |
| 140 | 140 |
| 141 GCTracer* Heap::tracer_ = NULL; | 141 GCTracer* Heap::tracer_ = NULL; |
| 142 | 142 |
| 143 int Heap::unflattened_strings_length_ = 0; | 143 int Heap::unflattened_strings_length_ = 0; |
| 144 | 144 |
| 145 int Heap::always_allocate_scope_depth_ = 0; | 145 int Heap::always_allocate_scope_depth_ = 0; |
| 146 int Heap::linear_allocation_scope_depth_ = 0; | 146 int Heap::linear_allocation_scope_depth_ = 0; |
| 147 int Heap::contexts_disposed_ = 0; | 147 int Heap::contexts_disposed_ = 0; |
| 148 | 148 |
| 149 int Heap::young_survivors_after_last_gc_ = 0; | 149 int Heap::young_survivors_after_last_gc_ = 0; |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 GarbageCollectionEpilogue(); | 500 GarbageCollectionEpilogue(); |
| 501 } | 501 } |
| 502 | 502 |
| 503 ASSERT(IncrementalMarking::state() == IncrementalMarking::STOPPED); | 503 ASSERT(IncrementalMarking::state() == IncrementalMarking::STOPPED); |
| 504 if (IncrementalMarking::WorthActivating() && NextGCIsLikelyToBeFull()) { | 504 if (IncrementalMarking::WorthActivating() && NextGCIsLikelyToBeFull()) { |
| 505 IncrementalMarking::Start(); | 505 IncrementalMarking::Start(); |
| 506 } | 506 } |
| 507 | 507 |
| 508 #ifdef ENABLE_LOGGING_AND_PROFILING | 508 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 509 if (FLAG_log_gc) HeapProfiler::WriteSample(); | 509 if (FLAG_log_gc) HeapProfiler::WriteSample(); |
| 510 if (CpuProfiler::is_profiling()) CpuProfiler::ProcessMovedFunctions(); | |
| 511 #endif | 510 #endif |
| 512 | 511 |
| 513 return next_gc_likely_to_collect_more; | 512 return next_gc_likely_to_collect_more; |
| 514 } | 513 } |
| 515 | 514 |
| 516 | 515 |
| 517 void Heap::PerformScavenge() { | 516 void Heap::PerformScavenge() { |
| 518 GCTracer tracer; | 517 GCTracer tracer; |
| 519 if (IncrementalMarking::state() == IncrementalMarking::STOPPED) { | 518 if (IncrementalMarking::state() == IncrementalMarking::STOPPED) { |
| 520 PerformGarbageCollection(SCAVENGER, &tracer); | 519 PerformGarbageCollection(SCAVENGER, &tracer); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 } | 808 } |
| 810 | 809 |
| 811 | 810 |
| 812 void Heap::MarkCompactPrologue(bool is_compacting) { | 811 void Heap::MarkCompactPrologue(bool is_compacting) { |
| 813 // At any old GC clear the keyed lookup cache to enable collection of unused | 812 // At any old GC clear the keyed lookup cache to enable collection of unused |
| 814 // maps. | 813 // maps. |
| 815 KeyedLookupCache::Clear(); | 814 KeyedLookupCache::Clear(); |
| 816 ContextSlotCache::Clear(); | 815 ContextSlotCache::Clear(); |
| 817 DescriptorLookupCache::Clear(); | 816 DescriptorLookupCache::Clear(); |
| 818 | 817 |
| 819 RuntimeProfiler::MarkCompactPrologue(is_compacting); | |
| 820 | |
| 821 CompilationCache::MarkCompactPrologue(); | 818 CompilationCache::MarkCompactPrologue(); |
| 822 | 819 |
| 823 CompletelyClearInstanceofCache(); | 820 CompletelyClearInstanceofCache(); |
| 824 | 821 |
| 825 if (is_compacting) FlushNumberStringCache(); | 822 if (is_compacting) FlushNumberStringCache(); |
| 826 | 823 |
| 827 ClearNormalizedMapCaches(); | 824 ClearNormalizedMapCaches(); |
| 828 } | 825 } |
| 829 | 826 |
| 830 | 827 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 Address value_address = | 1010 Address value_address = |
| 1014 reinterpret_cast<Address>(cell) + | 1011 reinterpret_cast<Address>(cell) + |
| 1015 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); | 1012 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); |
| 1016 scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address)); | 1013 scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address)); |
| 1017 } | 1014 } |
| 1018 } | 1015 } |
| 1019 | 1016 |
| 1020 // Scavenge object reachable from the global contexts list directly. | 1017 // Scavenge object reachable from the global contexts list directly. |
| 1021 scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_)); | 1018 scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_)); |
| 1022 | 1019 |
| 1023 // Scavenge objects reachable from the runtime-profiler sampler | |
| 1024 // window directly. | |
| 1025 Object** sampler_window_address = RuntimeProfiler::SamplerWindowAddress(); | |
| 1026 int sampler_window_size = RuntimeProfiler::SamplerWindowSize(); | |
| 1027 scavenge_visitor.VisitPointers( | |
| 1028 sampler_window_address, | |
| 1029 sampler_window_address + sampler_window_size); | |
| 1030 | |
| 1031 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1020 new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
| 1032 | 1021 |
| 1033 UpdateNewSpaceReferencesInExternalStringTable( | 1022 UpdateNewSpaceReferencesInExternalStringTable( |
| 1034 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1023 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
| 1035 | 1024 |
| 1036 LiveObjectList::UpdateReferencesForScavengeGC(); | 1025 LiveObjectList::UpdateReferencesForScavengeGC(); |
| 1026 RuntimeProfiler::UpdateSamplesAfterScavenge(); |
| 1037 | 1027 |
| 1038 ASSERT(new_space_front == new_space_.top()); | 1028 ASSERT(new_space_front == new_space_.top()); |
| 1039 | 1029 |
| 1040 // Set age mark. | 1030 // Set age mark. |
| 1041 new_space_.set_age_mark(new_space_.top()); | 1031 new_space_.set_age_mark(new_space_.top()); |
| 1042 | 1032 |
| 1043 // Update how much has survived scavenge. | 1033 // Update how much has survived scavenge. |
| 1044 IncrementYoungSurvivorsCounter(static_cast<int>( | 1034 IncrementYoungSurvivorsCounter(static_cast<int>( |
| 1045 (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); | 1035 (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); |
| 1046 | 1036 |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1309 // Set the forwarding address. | 1299 // Set the forwarding address. |
| 1310 source->set_map_word(MapWord::FromForwardingAddress(target)); | 1300 source->set_map_word(MapWord::FromForwardingAddress(target)); |
| 1311 | 1301 |
| 1312 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 1302 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 1313 // Update NewSpace stats if necessary. | 1303 // Update NewSpace stats if necessary. |
| 1314 RecordCopiedObject(target); | 1304 RecordCopiedObject(target); |
| 1315 #endif | 1305 #endif |
| 1316 HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address())); | 1306 HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address())); |
| 1317 #if defined(ENABLE_LOGGING_AND_PROFILING) | 1307 #if defined(ENABLE_LOGGING_AND_PROFILING) |
| 1318 if (Logger::is_logging() || CpuProfiler::is_profiling()) { | 1308 if (Logger::is_logging() || CpuProfiler::is_profiling()) { |
| 1319 if (target->IsJSFunction()) { | 1309 if (target->IsSharedFunctionInfo()) { |
| 1320 PROFILE(FunctionMoveEvent(source->address(), target->address())); | 1310 PROFILE(SharedFunctionInfoMoveEvent( |
| 1321 PROFILE(FunctionCreateEventFromMove(JSFunction::cast(target))); | 1311 source->address(), target->address())); |
| 1322 } | 1312 } |
| 1323 } | 1313 } |
| 1324 #endif | 1314 #endif |
| 1325 return target; | 1315 return target; |
| 1326 } | 1316 } |
| 1327 | 1317 |
| 1328 | 1318 |
| 1329 template<ObjectContents object_contents, SizeRestriction size_restriction> | 1319 template<ObjectContents object_contents, SizeRestriction size_restriction> |
| 1330 static inline void EvacuateObject(Map* map, | 1320 static inline void EvacuateObject(Map* map, |
| 1331 HeapObject** slot, | 1321 HeapObject** slot, |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 if (!maybe_obj->ToObject(&obj)) return false; | 1671 if (!maybe_obj->ToObject(&obj)) return false; |
| 1682 } | 1672 } |
| 1683 set_byte_array_map(Map::cast(obj)); | 1673 set_byte_array_map(Map::cast(obj)); |
| 1684 | 1674 |
| 1685 { MaybeObject* maybe_obj = AllocateByteArray(0, TENURED); | 1675 { MaybeObject* maybe_obj = AllocateByteArray(0, TENURED); |
| 1686 if (!maybe_obj->ToObject(&obj)) return false; | 1676 if (!maybe_obj->ToObject(&obj)) return false; |
| 1687 } | 1677 } |
| 1688 set_empty_byte_array(ByteArray::cast(obj)); | 1678 set_empty_byte_array(ByteArray::cast(obj)); |
| 1689 | 1679 |
| 1690 { MaybeObject* maybe_obj = | 1680 { MaybeObject* maybe_obj = |
| 1691 AllocateMap(PIXEL_ARRAY_TYPE, PixelArray::kAlignedSize); | 1681 AllocateMap(EXTERNAL_PIXEL_ARRAY_TYPE, ExternalArray::kAlignedSize); |
| 1692 if (!maybe_obj->ToObject(&obj)) return false; | 1682 if (!maybe_obj->ToObject(&obj)) return false; |
| 1693 } | 1683 } |
| 1694 set_pixel_array_map(Map::cast(obj)); | 1684 set_external_pixel_array_map(Map::cast(obj)); |
| 1695 | 1685 |
| 1696 { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE, | 1686 { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE, |
| 1697 ExternalArray::kAlignedSize); | 1687 ExternalArray::kAlignedSize); |
| 1698 if (!maybe_obj->ToObject(&obj)) return false; | 1688 if (!maybe_obj->ToObject(&obj)) return false; |
| 1699 } | 1689 } |
| 1700 set_external_byte_array_map(Map::cast(obj)); | 1690 set_external_byte_array_map(Map::cast(obj)); |
| 1701 | 1691 |
| 1702 { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE, | 1692 { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE, |
| 1703 ExternalArray::kAlignedSize); | 1693 ExternalArray::kAlignedSize); |
| 1704 if (!maybe_obj->ToObject(&obj)) return false; | 1694 if (!maybe_obj->ToObject(&obj)) return false; |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1880 if (!maybe_elements->ToObject(&elements)) return false; | 1870 if (!maybe_elements->ToObject(&elements)) return false; |
| 1881 } | 1871 } |
| 1882 FixedArray::cast(elements)->set(0, Smi::FromInt(0)); | 1872 FixedArray::cast(elements)->set(0, Smi::FromInt(0)); |
| 1883 JSObject::cast(obj)->set_elements(FixedArray::cast(elements)); | 1873 JSObject::cast(obj)->set_elements(FixedArray::cast(elements)); |
| 1884 set_message_listeners(JSObject::cast(obj)); | 1874 set_message_listeners(JSObject::cast(obj)); |
| 1885 | 1875 |
| 1886 return true; | 1876 return true; |
| 1887 } | 1877 } |
| 1888 | 1878 |
| 1889 | 1879 |
| 1890 void Heap::CreateCEntryStub() { | |
| 1891 CEntryStub stub(1); | |
| 1892 set_c_entry_code(*stub.GetCode()); | |
| 1893 } | |
| 1894 | |
| 1895 | |
| 1896 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP | |
| 1897 void Heap::CreateRegExpCEntryStub() { | |
| 1898 RegExpCEntryStub stub; | |
| 1899 set_re_c_entry_code(*stub.GetCode()); | |
| 1900 } | |
| 1901 #endif | |
| 1902 | |
| 1903 | |
| 1904 void Heap::CreateJSEntryStub() { | 1880 void Heap::CreateJSEntryStub() { |
| 1905 JSEntryStub stub; | 1881 JSEntryStub stub; |
| 1906 set_js_entry_code(*stub.GetCode()); | 1882 set_js_entry_code(*stub.GetCode()); |
| 1907 } | 1883 } |
| 1908 | 1884 |
| 1909 | 1885 |
| 1910 void Heap::CreateJSConstructEntryStub() { | 1886 void Heap::CreateJSConstructEntryStub() { |
| 1911 JSConstructEntryStub stub; | 1887 JSConstructEntryStub stub; |
| 1912 set_js_construct_entry_code(*stub.GetCode()); | 1888 set_js_construct_entry_code(*stub.GetCode()); |
| 1913 } | 1889 } |
| 1914 | 1890 |
| 1915 | 1891 |
| 1916 #if V8_TARGET_ARCH_ARM | |
| 1917 void Heap::CreateDirectCEntryStub() { | |
| 1918 DirectCEntryStub stub; | |
| 1919 set_direct_c_entry_code(*stub.GetCode()); | |
| 1920 } | |
| 1921 #endif | |
| 1922 | |
| 1923 | |
| 1924 void Heap::CreateFixedStubs() { | 1892 void Heap::CreateFixedStubs() { |
| 1925 // Here we create roots for fixed stubs. They are needed at GC | 1893 // Here we create roots for fixed stubs. They are needed at GC |
| 1926 // for cooking and uncooking (check out frames.cc). | 1894 // for cooking and uncooking (check out frames.cc). |
| 1927 // The eliminates the need for doing dictionary lookup in the | 1895 // The eliminates the need for doing dictionary lookup in the |
| 1928 // stub cache for these stubs. | 1896 // stub cache for these stubs. |
| 1929 HandleScope scope; | 1897 HandleScope scope; |
| 1930 // gcc-4.4 has problem generating correct code of following snippet: | 1898 // gcc-4.4 has problem generating correct code of following snippet: |
| 1931 // { CEntryStub stub; | 1899 // { JSEntryStub stub; |
| 1932 // c_entry_code_ = *stub.GetCode(); | 1900 // js_entry_code_ = *stub.GetCode(); |
| 1933 // } | 1901 // } |
| 1934 // { DebuggerStatementStub stub; | 1902 // { JSConstructEntryStub stub; |
| 1935 // debugger_statement_code_ = *stub.GetCode(); | 1903 // js_construct_entry_code_ = *stub.GetCode(); |
| 1936 // } | 1904 // } |
| 1937 // To workaround the problem, make separate functions without inlining. | 1905 // To workaround the problem, make separate functions without inlining. |
| 1938 Heap::CreateCEntryStub(); | |
| 1939 Heap::CreateJSEntryStub(); | 1906 Heap::CreateJSEntryStub(); |
| 1940 Heap::CreateJSConstructEntryStub(); | 1907 Heap::CreateJSConstructEntryStub(); |
| 1941 #if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP | |
| 1942 Heap::CreateRegExpCEntryStub(); | |
| 1943 #endif | |
| 1944 #if V8_TARGET_ARCH_ARM | |
| 1945 Heap::CreateDirectCEntryStub(); | |
| 1946 #endif | |
| 1947 } | 1908 } |
| 1948 | 1909 |
| 1949 | 1910 |
| 1950 bool Heap::CreateInitialObjects() { | 1911 bool Heap::CreateInitialObjects() { |
| 1951 Object* obj; | 1912 Object* obj; |
| 1952 | 1913 |
| 1953 // The -0 value must be set before NumberFromDouble works. | 1914 // The -0 value must be set before NumberFromDouble works. |
| 1954 { MaybeObject* maybe_obj = AllocateHeapNumber(-0.0, TENURED); | 1915 { MaybeObject* maybe_obj = AllocateHeapNumber(-0.0, TENURED); |
| 1955 if (!maybe_obj->ToObject(&obj)) return false; | 1916 if (!maybe_obj->ToObject(&obj)) return false; |
| 1956 } | 1917 } |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2231 case kExternalShortArray: | 2192 case kExternalShortArray: |
| 2232 return kExternalShortArrayMapRootIndex; | 2193 return kExternalShortArrayMapRootIndex; |
| 2233 case kExternalUnsignedShortArray: | 2194 case kExternalUnsignedShortArray: |
| 2234 return kExternalUnsignedShortArrayMapRootIndex; | 2195 return kExternalUnsignedShortArrayMapRootIndex; |
| 2235 case kExternalIntArray: | 2196 case kExternalIntArray: |
| 2236 return kExternalIntArrayMapRootIndex; | 2197 return kExternalIntArrayMapRootIndex; |
| 2237 case kExternalUnsignedIntArray: | 2198 case kExternalUnsignedIntArray: |
| 2238 return kExternalUnsignedIntArrayMapRootIndex; | 2199 return kExternalUnsignedIntArrayMapRootIndex; |
| 2239 case kExternalFloatArray: | 2200 case kExternalFloatArray: |
| 2240 return kExternalFloatArrayMapRootIndex; | 2201 return kExternalFloatArrayMapRootIndex; |
| 2202 case kExternalPixelArray: |
| 2203 return kExternalPixelArrayMapRootIndex; |
| 2241 default: | 2204 default: |
| 2242 UNREACHABLE(); | 2205 UNREACHABLE(); |
| 2243 return kUndefinedValueRootIndex; | 2206 return kUndefinedValueRootIndex; |
| 2244 } | 2207 } |
| 2245 } | 2208 } |
| 2246 | 2209 |
| 2247 | 2210 |
| 2248 MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) { | 2211 MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) { |
| 2249 // We need to distinguish the minus zero value and this cannot be | 2212 // We need to distinguish the minus zero value and this cannot be |
| 2250 // done after conversion to int. Doing this by comparing bit | 2213 // done after conversion to int. Doing this by comparing bit |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2665 filler->set_map(one_pointer_filler_map()); | 2628 filler->set_map(one_pointer_filler_map()); |
| 2666 } else if (size == 2 * kPointerSize) { | 2629 } else if (size == 2 * kPointerSize) { |
| 2667 filler->set_map(two_pointer_filler_map()); | 2630 filler->set_map(two_pointer_filler_map()); |
| 2668 } else { | 2631 } else { |
| 2669 filler->set_map(byte_array_map()); | 2632 filler->set_map(byte_array_map()); |
| 2670 ByteArray::cast(filler)->set_length(ByteArray::LengthFor(size)); | 2633 ByteArray::cast(filler)->set_length(ByteArray::LengthFor(size)); |
| 2671 } | 2634 } |
| 2672 } | 2635 } |
| 2673 | 2636 |
| 2674 | 2637 |
| 2675 MaybeObject* Heap::AllocatePixelArray(int length, | |
| 2676 uint8_t* external_pointer, | |
| 2677 PretenureFlag pretenure) { | |
| 2678 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | |
| 2679 Object* result; | |
| 2680 { MaybeObject* maybe_result = | |
| 2681 AllocateRaw(PixelArray::kAlignedSize, space, OLD_DATA_SPACE); | |
| 2682 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 2683 } | |
| 2684 | |
| 2685 reinterpret_cast<PixelArray*>(result)->set_map(pixel_array_map()); | |
| 2686 reinterpret_cast<PixelArray*>(result)->set_length(length); | |
| 2687 reinterpret_cast<PixelArray*>(result)->set_external_pointer(external_pointer); | |
| 2688 | |
| 2689 return result; | |
| 2690 } | |
| 2691 | |
| 2692 | |
| 2693 MaybeObject* Heap::AllocateExternalArray(int length, | 2638 MaybeObject* Heap::AllocateExternalArray(int length, |
| 2694 ExternalArrayType array_type, | 2639 ExternalArrayType array_type, |
| 2695 void* external_pointer, | 2640 void* external_pointer, |
| 2696 PretenureFlag pretenure) { | 2641 PretenureFlag pretenure) { |
| 2697 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | 2642 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
| 2698 Object* result; | 2643 Object* result; |
| 2699 { MaybeObject* maybe_result = AllocateRaw(ExternalArray::kAlignedSize, | 2644 { MaybeObject* maybe_result = AllocateRaw(ExternalArray::kAlignedSize, |
| 2700 space, | 2645 space, |
| 2701 OLD_DATA_SPACE); | 2646 OLD_DATA_SPACE); |
| 2702 if (!maybe_result->ToObject(&result)) return maybe_result; | 2647 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2703 } | 2648 } |
| 2704 | 2649 |
| 2705 reinterpret_cast<ExternalArray*>(result)->set_map( | 2650 reinterpret_cast<ExternalArray*>(result)->set_map( |
| 2706 MapForExternalArrayType(array_type)); | 2651 MapForExternalArrayType(array_type)); |
| 2707 reinterpret_cast<ExternalArray*>(result)->set_length(length); | 2652 reinterpret_cast<ExternalArray*>(result)->set_length(length); |
| 2708 reinterpret_cast<ExternalArray*>(result)->set_external_pointer( | 2653 reinterpret_cast<ExternalArray*>(result)->set_external_pointer( |
| 2709 external_pointer); | 2654 external_pointer); |
| 2710 | 2655 |
| 2711 return result; | 2656 return result; |
| 2712 } | 2657 } |
| 2713 | 2658 |
| 2714 | 2659 |
| 2715 MaybeObject* Heap::CreateCode(const CodeDesc& desc, | 2660 MaybeObject* Heap::CreateCode(const CodeDesc& desc, |
| 2716 Code::Flags flags, | 2661 Code::Flags flags, |
| 2717 Handle<Object> self_reference) { | 2662 Handle<Object> self_reference, |
| 2663 bool immovable) { |
| 2718 // Allocate ByteArray before the Code object, so that we do not risk | 2664 // Allocate ByteArray before the Code object, so that we do not risk |
| 2719 // leaving uninitialized Code object (and breaking the heap). | 2665 // leaving uninitialized Code object (and breaking the heap). |
| 2720 Object* reloc_info; | 2666 Object* reloc_info; |
| 2721 { MaybeObject* maybe_reloc_info = AllocateByteArray(desc.reloc_size, TENURED); | 2667 { MaybeObject* maybe_reloc_info = AllocateByteArray(desc.reloc_size, TENURED); |
| 2722 if (!maybe_reloc_info->ToObject(&reloc_info)) return maybe_reloc_info; | 2668 if (!maybe_reloc_info->ToObject(&reloc_info)) return maybe_reloc_info; |
| 2723 } | 2669 } |
| 2724 | 2670 |
| 2725 // Compute size | 2671 // Compute size. |
| 2726 int body_size = RoundUp(desc.instr_size, kObjectAlignment); | 2672 int body_size = RoundUp(desc.instr_size, kObjectAlignment); |
| 2727 int obj_size = Code::SizeFor(body_size); | 2673 int obj_size = Code::SizeFor(body_size); |
| 2728 ASSERT(IsAligned(static_cast<intptr_t>(obj_size), kCodeAlignment)); | 2674 ASSERT(IsAligned(static_cast<intptr_t>(obj_size), kCodeAlignment)); |
| 2729 MaybeObject* maybe_result; | 2675 MaybeObject* maybe_result; |
| 2730 if (obj_size > MaxObjectSizeInPagedSpace()) { | 2676 // Large code objects and code objects which should stay at a fixed address |
| 2677 // are allocated in large object space. |
| 2678 if (obj_size > MaxObjectSizeInPagedSpace() || immovable) { |
| 2731 maybe_result = lo_space_->AllocateRawCode(obj_size); | 2679 maybe_result = lo_space_->AllocateRawCode(obj_size); |
| 2732 } else { | 2680 } else { |
| 2733 maybe_result = code_space_->AllocateRaw(obj_size); | 2681 maybe_result = code_space_->AllocateRaw(obj_size); |
| 2734 } | 2682 } |
| 2735 | 2683 |
| 2736 Object* result; | 2684 Object* result; |
| 2737 if (!maybe_result->ToObject(&result)) return maybe_result; | 2685 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2738 | 2686 |
| 2739 // Initialize the object | 2687 // Initialize the object |
| 2740 HeapObject::cast(result)->set_map(code_map()); | 2688 HeapObject::cast(result)->set_map(code_map()); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2887 JSFunction* object_function = | 2835 JSFunction* object_function = |
| 2888 function->context()->global_context()->object_function(); | 2836 function->context()->global_context()->object_function(); |
| 2889 Object* prototype; | 2837 Object* prototype; |
| 2890 { MaybeObject* maybe_prototype = AllocateJSObject(object_function); | 2838 { MaybeObject* maybe_prototype = AllocateJSObject(object_function); |
| 2891 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; | 2839 if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; |
| 2892 } | 2840 } |
| 2893 // When creating the prototype for the function we must set its | 2841 // When creating the prototype for the function we must set its |
| 2894 // constructor to the function. | 2842 // constructor to the function. |
| 2895 Object* result; | 2843 Object* result; |
| 2896 { MaybeObject* maybe_result = | 2844 { MaybeObject* maybe_result = |
| 2897 JSObject::cast(prototype)->SetProperty(constructor_symbol(), | 2845 JSObject::cast(prototype)->SetLocalPropertyIgnoreAttributes( |
| 2898 function, | 2846 constructor_symbol(), function, DONT_ENUM); |
| 2899 DONT_ENUM); | |
| 2900 if (!maybe_result->ToObject(&result)) return maybe_result; | 2847 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2901 } | 2848 } |
| 2902 return prototype; | 2849 return prototype; |
| 2903 } | 2850 } |
| 2904 | 2851 |
| 2905 | 2852 |
| 2906 MaybeObject* Heap::AllocateFunction(Map* function_map, | 2853 MaybeObject* Heap::AllocateFunction(Map* function_map, |
| 2907 SharedFunctionInfo* shared, | 2854 SharedFunctionInfo* shared, |
| 2908 Object* prototype, | 2855 Object* prototype, |
| 2909 PretenureFlag pretenure) { | 2856 PretenureFlag pretenure) { |
| (...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3760 Struct::cast(result)->InitializeBody(size); | 3707 Struct::cast(result)->InitializeBody(size); |
| 3761 return result; | 3708 return result; |
| 3762 } | 3709 } |
| 3763 | 3710 |
| 3764 | 3711 |
| 3765 bool Heap::IdleNotification() { | 3712 bool Heap::IdleNotification() { |
| 3766 static const int kIdlesBeforeScavenge = 4; | 3713 static const int kIdlesBeforeScavenge = 4; |
| 3767 static const int kIdlesBeforeMarkSweep = 7; | 3714 static const int kIdlesBeforeMarkSweep = 7; |
| 3768 static const int kIdlesBeforeMarkCompact = 8; | 3715 static const int kIdlesBeforeMarkCompact = 8; |
| 3769 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; | 3716 static const int kMaxIdleCount = kIdlesBeforeMarkCompact + 1; |
| 3770 static const int kGCsBetweenCleanup = 4; | 3717 static const unsigned int kGCsBetweenCleanup = 4; |
| 3771 static int number_idle_notifications = 0; | 3718 static int number_idle_notifications = 0; |
| 3772 static int last_gc_count = gc_count_; | 3719 static unsigned int last_gc_count = gc_count_; |
| 3773 | 3720 |
| 3774 bool uncommit = true; | 3721 bool uncommit = true; |
| 3775 bool finished = false; | 3722 bool finished = false; |
| 3776 | 3723 |
| 3777 // Reset the number of idle notifications received when a number of | 3724 // Reset the number of idle notifications received when a number of |
| 3778 // GCs have taken place. This allows another round of cleanup based | 3725 // GCs have taken place. This allows another round of cleanup based |
| 3779 // on idle notifications if enough work has been carried out to | 3726 // on idle notifications if enough work has been carried out to |
| 3780 // provoke a number of garbage collections. | 3727 // provoke a number of garbage collections. |
| 3781 if (gc_count_ < last_gc_count + kGCsBetweenCleanup) { | 3728 if (gc_count_ - last_gc_count < kGCsBetweenCleanup) { |
| 3782 number_idle_notifications = | 3729 number_idle_notifications = |
| 3783 Min(number_idle_notifications + 1, kMaxIdleCount); | 3730 Min(number_idle_notifications + 1, kMaxIdleCount); |
| 3784 } else { | 3731 } else { |
| 3785 number_idle_notifications = 0; | 3732 number_idle_notifications = 0; |
| 3786 last_gc_count = gc_count_; | 3733 last_gc_count = gc_count_; |
| 3787 } | 3734 } |
| 3788 | 3735 |
| 3789 if (number_idle_notifications == kIdlesBeforeScavenge) { | 3736 if (number_idle_notifications == kIdlesBeforeScavenge) { |
| 3790 if (contexts_disposed_ > 0) { | 3737 if (contexts_disposed_ > 0) { |
| 3791 HistogramTimerScope scope(&Counters::gc_context); | 3738 HistogramTimerScope scope(&Counters::gc_context); |
| (...skipping 1380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5172 } | 5119 } |
| 5173 | 5120 |
| 5174 | 5121 |
| 5175 void HeapIterator::reset() { | 5122 void HeapIterator::reset() { |
| 5176 // Restart the iterator. | 5123 // Restart the iterator. |
| 5177 Shutdown(); | 5124 Shutdown(); |
| 5178 Init(); | 5125 Init(); |
| 5179 } | 5126 } |
| 5180 | 5127 |
| 5181 | 5128 |
| 5182 #ifdef DEBUG | 5129 #if defined(DEBUG) || defined(LIVE_OBJECT_LIST) |
| 5183 | 5130 |
| 5184 static bool search_for_any_global; | 5131 Object* const PathTracer::kAnyGlobalObject = reinterpret_cast<Object*>(NULL); |
| 5185 static Object* search_target; | 5132 |
| 5186 static bool found_target; | 5133 class PathTracer::MarkVisitor: public ObjectVisitor { |
| 5187 static List<Object*> object_stack(20); | 5134 public: |
| 5135 explicit MarkVisitor(PathTracer* tracer) : tracer_(tracer) {} |
| 5136 void VisitPointers(Object** start, Object** end) { |
| 5137 // Scan all HeapObject pointers in [start, end) |
| 5138 for (Object** p = start; !tracer_->found() && (p < end); p++) { |
| 5139 if ((*p)->IsHeapObject()) |
| 5140 tracer_->MarkRecursively(p, this); |
| 5141 } |
| 5142 } |
| 5143 |
| 5144 private: |
| 5145 PathTracer* tracer_; |
| 5146 }; |
| 5188 | 5147 |
| 5189 | 5148 |
| 5190 // Tags 0, 1, and 3 are used. Use 2 for marking visited HeapObject. | 5149 class PathTracer::UnmarkVisitor: public ObjectVisitor { |
| 5191 static const int kMarkTag = 2; | |
| 5192 | |
| 5193 static void MarkObjectRecursively(Object** p); | |
| 5194 class MarkObjectVisitor : public ObjectVisitor { | |
| 5195 public: | 5150 public: |
| 5151 explicit UnmarkVisitor(PathTracer* tracer) : tracer_(tracer) {} |
| 5196 void VisitPointers(Object** start, Object** end) { | 5152 void VisitPointers(Object** start, Object** end) { |
| 5197 // Copy all HeapObject pointers in [start, end) | 5153 // Scan all HeapObject pointers in [start, end) |
| 5198 for (Object** p = start; p < end; p++) { | 5154 for (Object** p = start; p < end; p++) { |
| 5199 if ((*p)->IsHeapObject()) | 5155 if ((*p)->IsHeapObject()) |
| 5200 MarkObjectRecursively(p); | 5156 tracer_->UnmarkRecursively(p, this); |
| 5201 } | 5157 } |
| 5202 } | 5158 } |
| 5159 |
| 5160 private: |
| 5161 PathTracer* tracer_; |
| 5203 }; | 5162 }; |
| 5204 | 5163 |
| 5205 static MarkObjectVisitor mark_visitor; | |
| 5206 | 5164 |
| 5207 static void MarkObjectRecursively(Object** p) { | 5165 void PathTracer::VisitPointers(Object** start, Object** end) { |
| 5166 bool done = ((what_to_find_ == FIND_FIRST) && found_target_); |
| 5167 // Visit all HeapObject pointers in [start, end) |
| 5168 for (Object** p = start; !done && (p < end); p++) { |
| 5169 if ((*p)->IsHeapObject()) { |
| 5170 TracePathFrom(p); |
| 5171 done = ((what_to_find_ == FIND_FIRST) && found_target_); |
| 5172 } |
| 5173 } |
| 5174 } |
| 5175 |
| 5176 |
| 5177 void PathTracer::Reset() { |
| 5178 found_target_ = false; |
| 5179 object_stack_.Clear(); |
| 5180 } |
| 5181 |
| 5182 |
| 5183 void PathTracer::TracePathFrom(Object** root) { |
| 5184 ASSERT((search_target_ == kAnyGlobalObject) || |
| 5185 search_target_->IsHeapObject()); |
| 5186 found_target_in_trace_ = false; |
| 5187 object_stack_.Clear(); |
| 5188 |
| 5189 MarkVisitor mark_visitor(this); |
| 5190 MarkRecursively(root, &mark_visitor); |
| 5191 |
| 5192 UnmarkVisitor unmark_visitor(this); |
| 5193 UnmarkRecursively(root, &unmark_visitor); |
| 5194 |
| 5195 ProcessResults(); |
| 5196 } |
| 5197 |
| 5198 |
| 5199 void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) { |
| 5208 if (!(*p)->IsHeapObject()) return; | 5200 if (!(*p)->IsHeapObject()) return; |
| 5209 | 5201 |
| 5210 HeapObject* obj = HeapObject::cast(*p); | 5202 HeapObject* obj = HeapObject::cast(*p); |
| 5211 | 5203 |
| 5212 Object* map = obj->map(); | 5204 Object* map = obj->map(); |
| 5213 | 5205 |
| 5214 if (!map->IsHeapObject()) return; // visited before | 5206 if (!map->IsHeapObject()) return; // visited before |
| 5215 | 5207 |
| 5216 if (found_target) return; // stop if target found | 5208 if (found_target_in_trace_) return; // stop if target found |
| 5217 object_stack.Add(obj); | 5209 object_stack_.Add(obj); |
| 5218 if ((search_for_any_global && obj->IsJSGlobalObject()) || | 5210 if (((search_target_ == kAnyGlobalObject) && obj->IsJSGlobalObject()) || |
| 5219 (!search_for_any_global && (obj == search_target))) { | 5211 (obj == search_target_)) { |
| 5220 found_target = true; | 5212 found_target_in_trace_ = true; |
| 5213 found_target_ = true; |
| 5221 return; | 5214 return; |
| 5222 } | 5215 } |
| 5223 | 5216 |
| 5217 bool is_global_context = obj->IsGlobalContext(); |
| 5218 |
| 5224 // not visited yet | 5219 // not visited yet |
| 5225 Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map)); | 5220 Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map)); |
| 5226 | 5221 |
| 5227 Address map_addr = map_p->address(); | 5222 Address map_addr = map_p->address(); |
| 5228 | 5223 |
| 5229 obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag)); | 5224 obj->set_map(reinterpret_cast<Map*>(map_addr + kMarkTag)); |
| 5230 | 5225 |
| 5231 MarkObjectRecursively(&map); | 5226 // Scan the object body. |
| 5227 if (is_global_context && (visit_mode_ == VISIT_ONLY_STRONG)) { |
| 5228 // This is specialized to scan Context's properly. |
| 5229 Object** start = reinterpret_cast<Object**>(obj->address() + |
| 5230 Context::kHeaderSize); |
| 5231 Object** end = reinterpret_cast<Object**>(obj->address() + |
| 5232 Context::kHeaderSize + Context::FIRST_WEAK_SLOT * kPointerSize); |
| 5233 mark_visitor->VisitPointers(start, end); |
| 5234 } else { |
| 5235 obj->IterateBody(map_p->instance_type(), |
| 5236 obj->SizeFromMap(map_p), |
| 5237 mark_visitor); |
| 5238 } |
| 5232 | 5239 |
| 5233 obj->IterateBody(map_p->instance_type(), obj->SizeFromMap(map_p), | 5240 // Scan the map after the body because the body is a lot more interesting |
| 5234 &mark_visitor); | 5241 // when doing leak detection. |
| 5242 MarkRecursively(&map, mark_visitor); |
| 5235 | 5243 |
| 5236 if (!found_target) // don't pop if found the target | 5244 if (!found_target_in_trace_) // don't pop if found the target |
| 5237 object_stack.RemoveLast(); | 5245 object_stack_.RemoveLast(); |
| 5238 } | 5246 } |
| 5239 | 5247 |
| 5240 | 5248 |
| 5241 static void UnmarkObjectRecursively(Object** p); | 5249 void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) { |
| 5242 class UnmarkObjectVisitor : public ObjectVisitor { | |
| 5243 public: | |
| 5244 void VisitPointers(Object** start, Object** end) { | |
| 5245 // Copy all HeapObject pointers in [start, end) | |
| 5246 for (Object** p = start; p < end; p++) { | |
| 5247 if ((*p)->IsHeapObject()) | |
| 5248 UnmarkObjectRecursively(p); | |
| 5249 } | |
| 5250 } | |
| 5251 }; | |
| 5252 | |
| 5253 static UnmarkObjectVisitor unmark_visitor; | |
| 5254 | |
| 5255 static void UnmarkObjectRecursively(Object** p) { | |
| 5256 if (!(*p)->IsHeapObject()) return; | 5250 if (!(*p)->IsHeapObject()) return; |
| 5257 | 5251 |
| 5258 HeapObject* obj = HeapObject::cast(*p); | 5252 HeapObject* obj = HeapObject::cast(*p); |
| 5259 | 5253 |
| 5260 Object* map = obj->map(); | 5254 Object* map = obj->map(); |
| 5261 | 5255 |
| 5262 if (map->IsHeapObject()) return; // unmarked already | 5256 if (map->IsHeapObject()) return; // unmarked already |
| 5263 | 5257 |
| 5264 Address map_addr = reinterpret_cast<Address>(map); | 5258 Address map_addr = reinterpret_cast<Address>(map); |
| 5265 | 5259 |
| 5266 map_addr -= kMarkTag; | 5260 map_addr -= kMarkTag; |
| 5267 | 5261 |
| 5268 ASSERT_TAG_ALIGNED(map_addr); | 5262 ASSERT_TAG_ALIGNED(map_addr); |
| 5269 | 5263 |
| 5270 HeapObject* map_p = HeapObject::FromAddress(map_addr); | 5264 HeapObject* map_p = HeapObject::FromAddress(map_addr); |
| 5271 | 5265 |
| 5272 obj->set_map(reinterpret_cast<Map*>(map_p)); | 5266 obj->set_map(reinterpret_cast<Map*>(map_p)); |
| 5273 | 5267 |
| 5274 UnmarkObjectRecursively(reinterpret_cast<Object**>(&map_p)); | 5268 UnmarkRecursively(reinterpret_cast<Object**>(&map_p), unmark_visitor); |
| 5275 | 5269 |
| 5276 obj->IterateBody(Map::cast(map_p)->instance_type(), | 5270 obj->IterateBody(Map::cast(map_p)->instance_type(), |
| 5277 obj->SizeFromMap(Map::cast(map_p)), | 5271 obj->SizeFromMap(Map::cast(map_p)), |
| 5278 &unmark_visitor); | 5272 unmark_visitor); |
| 5279 } | 5273 } |
| 5280 | 5274 |
| 5281 | 5275 |
| 5282 static void MarkRootObjectRecursively(Object** root) { | 5276 void PathTracer::ProcessResults() { |
| 5283 if (search_for_any_global) { | 5277 if (found_target_) { |
| 5284 ASSERT(search_target == NULL); | |
| 5285 } else { | |
| 5286 ASSERT(search_target->IsHeapObject()); | |
| 5287 } | |
| 5288 found_target = false; | |
| 5289 object_stack.Clear(); | |
| 5290 | |
| 5291 MarkObjectRecursively(root); | |
| 5292 UnmarkObjectRecursively(root); | |
| 5293 | |
| 5294 if (found_target) { | |
| 5295 PrintF("=====================================\n"); | 5278 PrintF("=====================================\n"); |
| 5296 PrintF("==== Path to object ====\n"); | 5279 PrintF("==== Path to object ====\n"); |
| 5297 PrintF("=====================================\n\n"); | 5280 PrintF("=====================================\n\n"); |
| 5298 | 5281 |
| 5299 ASSERT(!object_stack.is_empty()); | 5282 ASSERT(!object_stack_.is_empty()); |
| 5300 for (int i = 0; i < object_stack.length(); i++) { | 5283 for (int i = 0; i < object_stack_.length(); i++) { |
| 5301 if (i > 0) PrintF("\n |\n |\n V\n\n"); | 5284 if (i > 0) PrintF("\n |\n |\n V\n\n"); |
| 5302 Object* obj = object_stack[i]; | 5285 Object* obj = object_stack_[i]; |
| 5286 #ifdef OBJECT_PRINT |
| 5303 obj->Print(); | 5287 obj->Print(); |
| 5288 #else |
| 5289 obj->ShortPrint(); |
| 5290 #endif |
| 5304 } | 5291 } |
| 5305 PrintF("=====================================\n"); | 5292 PrintF("=====================================\n"); |
| 5306 } | 5293 } |
| 5307 } | 5294 } |
| 5295 #endif // DEBUG || LIVE_OBJECT_LIST |
| 5308 | 5296 |
| 5309 | 5297 |
| 5310 // Helper class for visiting HeapObjects recursively. | 5298 #ifdef DEBUG |
| 5311 class MarkRootVisitor: public ObjectVisitor { | |
| 5312 public: | |
| 5313 void VisitPointers(Object** start, Object** end) { | |
| 5314 // Visit all HeapObject pointers in [start, end) | |
| 5315 for (Object** p = start; p < end; p++) { | |
| 5316 if ((*p)->IsHeapObject()) | |
| 5317 MarkRootObjectRecursively(p); | |
| 5318 } | |
| 5319 } | |
| 5320 }; | |
| 5321 | |
| 5322 | |
| 5323 // Triggers a depth-first traversal of reachable objects from roots | 5299 // Triggers a depth-first traversal of reachable objects from roots |
| 5324 // and finds a path to a specific heap object and prints it. | 5300 // and finds a path to a specific heap object and prints it. |
| 5325 void Heap::TracePathToObject(Object* target) { | 5301 void Heap::TracePathToObject(Object* target) { |
| 5326 search_target = target; | 5302 PathTracer tracer(target, PathTracer::FIND_ALL, VISIT_ALL); |
| 5327 search_for_any_global = false; | 5303 IterateRoots(&tracer, VISIT_ONLY_STRONG); |
| 5328 | |
| 5329 MarkRootVisitor root_visitor; | |
| 5330 IterateRoots(&root_visitor, VISIT_ONLY_STRONG); | |
| 5331 } | 5304 } |
| 5332 | 5305 |
| 5333 | 5306 |
| 5334 // Triggers a depth-first traversal of reachable objects from roots | 5307 // Triggers a depth-first traversal of reachable objects from roots |
| 5335 // and finds a path to any global object and prints it. Useful for | 5308 // and finds a path to any global object and prints it. Useful for |
| 5336 // determining the source for leaks of global objects. | 5309 // determining the source for leaks of global objects. |
| 5337 void Heap::TracePathToGlobal() { | 5310 void Heap::TracePathToGlobal() { |
| 5338 search_target = NULL; | 5311 PathTracer tracer(PathTracer::kAnyGlobalObject, |
| 5339 search_for_any_global = true; | 5312 PathTracer::FIND_ALL, |
| 5340 | 5313 VISIT_ALL); |
| 5341 MarkRootVisitor root_visitor; | 5314 IterateRoots(&tracer, VISIT_ONLY_STRONG); |
| 5342 IterateRoots(&root_visitor, VISIT_ONLY_STRONG); | |
| 5343 } | 5315 } |
| 5344 #endif | 5316 #endif |
| 5345 | 5317 |
| 5346 | 5318 |
| 5347 static intptr_t CountTotalHolesSize() { | 5319 static intptr_t CountTotalHolesSize() { |
| 5348 intptr_t holes_size = 0; | 5320 intptr_t holes_size = 0; |
| 5349 OldSpaces spaces; | 5321 OldSpaces spaces; |
| 5350 for (OldSpace* space = spaces.next(); | 5322 for (OldSpace* space = spaces.next(); |
| 5351 space != NULL; | 5323 space != NULL; |
| 5352 space = spaces.next()) { | 5324 space = spaces.next()) { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5584 void ExternalStringTable::TearDown() { | 5556 void ExternalStringTable::TearDown() { |
| 5585 new_space_strings_.Free(); | 5557 new_space_strings_.Free(); |
| 5586 old_space_strings_.Free(); | 5558 old_space_strings_.Free(); |
| 5587 } | 5559 } |
| 5588 | 5560 |
| 5589 | 5561 |
| 5590 List<Object*> ExternalStringTable::new_space_strings_; | 5562 List<Object*> ExternalStringTable::new_space_strings_; |
| 5591 List<Object*> ExternalStringTable::old_space_strings_; | 5563 List<Object*> ExternalStringTable::old_space_strings_; |
| 5592 | 5564 |
| 5593 } } // namespace v8::internal | 5565 } } // namespace v8::internal |
| OLD | NEW |