Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: src/heap.cc

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/heap.h ('k') | src/heap-profiler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/heap.h ('k') | src/heap-profiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698