OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 class VerifyMarkingVisitor: public ObjectVisitor { | 75 class VerifyMarkingVisitor: public ObjectVisitor { |
76 public: | 76 public: |
77 void VisitPointers(Object** start, Object** end) { | 77 void VisitPointers(Object** start, Object** end) { |
78 for (Object** current = start; current < end; current++) { | 78 for (Object** current = start; current < end; current++) { |
79 if ((*current)->IsHeapObject()) { | 79 if ((*current)->IsHeapObject()) { |
80 HeapObject* object = HeapObject::cast(*current); | 80 HeapObject* object = HeapObject::cast(*current); |
81 CHECK(HEAP->mark_compact_collector()->IsMarked(object)); | 81 CHECK(HEAP->mark_compact_collector()->IsMarked(object)); |
82 } | 82 } |
83 } | 83 } |
84 } | 84 } |
85 | |
Michael Starzinger
2013/01/21 10:31:48
Drop one of the empty newlines.
| |
86 | |
87 void VisitEmbeddedPointer(RelocInfo* rinfo) { | |
88 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | |
89 if (rinfo->host()->kind() != Code::OPTIMIZED_FUNCTION || | |
90 !rinfo->target_object()->IsMap() || | |
91 !Map::cast(rinfo->target_object())->CanTransition()) { | |
92 VisitPointer(rinfo->target_object_address()); | |
93 } | |
94 } | |
85 }; | 95 }; |
86 | 96 |
87 | 97 |
88 static void VerifyMarking(Address bottom, Address top) { | 98 static void VerifyMarking(Address bottom, Address top) { |
89 VerifyMarkingVisitor visitor; | 99 VerifyMarkingVisitor visitor; |
90 HeapObject* object; | 100 HeapObject* object; |
91 Address next_object_must_be_here_or_later = bottom; | 101 Address next_object_must_be_here_or_later = bottom; |
92 | 102 |
93 for (Address current = bottom; | 103 for (Address current = bottom; |
94 current < top; | 104 current < top; |
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
816 space->PrepareForMarkCompact(); | 826 space->PrepareForMarkCompact(); |
817 } | 827 } |
818 | 828 |
819 #ifdef VERIFY_HEAP | 829 #ifdef VERIFY_HEAP |
820 if (!was_marked_incrementally_ && FLAG_verify_heap) { | 830 if (!was_marked_incrementally_ && FLAG_verify_heap) { |
821 VerifyMarkbitsAreClean(); | 831 VerifyMarkbitsAreClean(); |
822 } | 832 } |
823 #endif | 833 #endif |
824 } | 834 } |
825 | 835 |
836 class DeoptimizeMarkedCodeFilter : public OptimizedFunctionFilter { | |
837 public: | |
838 virtual bool TakeFunction(JSFunction* function) { | |
839 return function->code()->marked_for_deoptimization(); | |
840 } | |
841 }; | |
842 | |
826 | 843 |
827 void MarkCompactCollector::Finish() { | 844 void MarkCompactCollector::Finish() { |
828 #ifdef DEBUG | 845 #ifdef DEBUG |
829 ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); | 846 ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); |
830 state_ = IDLE; | 847 state_ = IDLE; |
831 #endif | 848 #endif |
832 // The stub cache is not traversed during GC; clear the cache to | 849 // The stub cache is not traversed during GC; clear the cache to |
833 // force lazy re-initialization of it. This must be done after the | 850 // force lazy re-initialization of it. This must be done after the |
834 // GC, because it relies on the new address of certain old space | 851 // GC, because it relies on the new address of certain old space |
835 // objects (empty string, illegal builtin). | 852 // objects (empty string, illegal builtin). |
836 heap()->isolate()->stub_cache()->Clear(); | 853 heap()->isolate()->stub_cache()->Clear(); |
854 | |
855 DeoptimizeMarkedCodeFilter filter; | |
856 Deoptimizer::DeoptimizeAllFunctionsWith(&filter); | |
837 } | 857 } |
838 | 858 |
839 | 859 |
840 // ------------------------------------------------------------------------- | 860 // ------------------------------------------------------------------------- |
841 // Phase 1: tracing and marking live objects. | 861 // Phase 1: tracing and marking live objects. |
842 // before: all objects are in normal state. | 862 // before: all objects are in normal state. |
843 // after: a live object's map pointer is marked as '00'. | 863 // after: a live object's map pointer is marked as '00'. |
844 | 864 |
845 // Marking all live objects in the heap as part of mark-sweep or mark-compact | 865 // Marking all live objects in the heap as part of mark-sweep or mark-compact |
846 // collection. Before marking, all objects are in their normal state. After | 866 // collection. Before marking, all objects are in their normal state. After |
(...skipping 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2159 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | 2179 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); |
2160 if (map->instance_type() < FIRST_JS_RECEIVER_TYPE) continue; | 2180 if (map->instance_type() < FIRST_JS_RECEIVER_TYPE) continue; |
2161 | 2181 |
2162 if (map->attached_to_shared_function_info()) { | 2182 if (map->attached_to_shared_function_info()) { |
2163 JSFunction::cast(map->constructor())->shared()->AttachInitialMap(map); | 2183 JSFunction::cast(map->constructor())->shared()->AttachInitialMap(map); |
2164 } | 2184 } |
2165 } | 2185 } |
2166 } | 2186 } |
2167 | 2187 |
2168 | 2188 |
2169 void MarkCompactCollector::ClearNonLiveTransitions() { | 2189 void MarkCompactCollector::ClearNonLiveTransitions() { |
Michael Starzinger
2013/01/21 10:31:48
This function should be renamed to "ClearNonLiveRe
ulan
2013/01/21 13:11:57
Done.
| |
2170 HeapObjectIterator map_iterator(heap()->map_space()); | 2190 HeapObjectIterator map_iterator(heap()->map_space()); |
2171 // Iterate over the map space, setting map transitions that go from | 2191 // Iterate over the map space, setting map transitions that go from |
2172 // a marked map to an unmarked map to null transitions. This action | 2192 // a marked map to an unmarked map to null transitions. This action |
2173 // is carried out only on maps of JSObjects and related subtypes. | 2193 // is carried out only on maps of JSObjects and related subtypes. |
2174 for (HeapObject* obj = map_iterator.Next(); | 2194 for (HeapObject* obj = map_iterator.Next(); |
2175 obj != NULL; obj = map_iterator.Next()) { | 2195 obj != NULL; obj = map_iterator.Next()) { |
2176 Map* map = reinterpret_cast<Map*>(obj); | 2196 Map* map = reinterpret_cast<Map*>(obj); |
2177 MarkBit map_mark = Marking::MarkBitFrom(map); | 2197 MarkBit map_mark = Marking::MarkBitFrom(map); |
2178 if (map->IsFreeSpace()) continue; | 2198 if (map->IsFreeSpace()) continue; |
2179 | 2199 |
2180 ASSERT(map->IsMap()); | 2200 ASSERT(map->IsMap()); |
2181 // Only JSObject and subtypes have map transitions and back pointers. | 2201 if (!map->CanTransition()) continue; |
2182 STATIC_ASSERT(LAST_TYPE == LAST_JS_OBJECT_TYPE); | |
2183 if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; | |
2184 | 2202 |
2185 if (map_mark.Get() && | 2203 if (map_mark.Get() && |
2186 map->attached_to_shared_function_info()) { | 2204 map->attached_to_shared_function_info()) { |
2187 // This map is used for inobject slack tracking and has been detached | 2205 // This map is used for inobject slack tracking and has been detached |
2188 // from SharedFunctionInfo during the mark phase. | 2206 // from SharedFunctionInfo during the mark phase. |
2189 // Since it survived the GC, reattach it now. | 2207 // Since it survived the GC, reattach it now. |
2190 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); | 2208 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); |
2191 } | 2209 } |
2192 | 2210 |
2193 ClearNonLivePrototypeTransitions(map); | 2211 ClearNonLivePrototypeTransitions(map); |
2194 ClearNonLiveMapTransitions(map, map_mark); | 2212 ClearNonLiveMapTransitions(map, map_mark); |
2213 | |
2214 if (map_mark.Get()) { | |
2215 ClearNonLiveDependentCodes(map); | |
2216 } else { | |
2217 DeoptimizeLiveDependentCodes(map); | |
Michael Starzinger
2013/01/21 10:31:48
How about naming this ClearAndDeoptimizeDependentC
ulan
2013/01/21 13:11:57
Done.
| |
2218 } | |
2195 } | 2219 } |
2196 } | 2220 } |
2197 | 2221 |
2198 | 2222 |
2199 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { | 2223 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { |
2200 int number_of_transitions = map->NumberOfProtoTransitions(); | 2224 int number_of_transitions = map->NumberOfProtoTransitions(); |
2201 FixedArray* prototype_transitions = map->GetPrototypeTransitions(); | 2225 FixedArray* prototype_transitions = map->GetPrototypeTransitions(); |
2202 | 2226 |
2203 int new_number_of_transitions = 0; | 2227 int new_number_of_transitions = 0; |
2204 const int header = Map::kProtoTransitionHeaderSize; | 2228 const int header = Map::kProtoTransitionHeaderSize; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2253 // Follow back pointer, check whether we are dealing with a map transition | 2277 // Follow back pointer, check whether we are dealing with a map transition |
2254 // from a live map to a dead path and in case clear transitions of parent. | 2278 // from a live map to a dead path and in case clear transitions of parent. |
2255 bool current_is_alive = map_mark.Get(); | 2279 bool current_is_alive = map_mark.Get(); |
2256 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); | 2280 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); |
2257 if (!current_is_alive && parent_is_alive) { | 2281 if (!current_is_alive && parent_is_alive) { |
2258 parent->ClearNonLiveTransitions(heap()); | 2282 parent->ClearNonLiveTransitions(heap()); |
2259 } | 2283 } |
2260 } | 2284 } |
2261 | 2285 |
2262 | 2286 |
2287 void MarkCompactCollector::DeoptimizeLiveDependentCodes(Map* map) { | |
2288 AssertNoAllocation no_allocation_scope; | |
2289 DependentCodes* codes = map->dependent_codes(); | |
2290 int number_of_codes = codes->number_of_codes(); | |
2291 if (number_of_codes == 0) return; | |
2292 for (int i = 0; i < number_of_codes; i++) { | |
2293 Code* code = codes->code_at(i); | |
2294 if (IsMarked(code) && !code->marked_for_deoptimization()) { | |
2295 code->set_marked_for_deoptimization(true); | |
2296 } | |
2297 codes->clear_code_at(i); | |
2298 } | |
2299 map->set_dependent_codes(DependentCodes::cast(heap()->empty_fixed_array())); | |
2300 } | |
2301 | |
2302 | |
2303 void MarkCompactCollector::ClearNonLiveDependentCodes(Map* map) { | |
2304 AssertNoAllocation no_allocation_scope; | |
2305 DependentCodes* codes = map->dependent_codes(); | |
2306 int number_of_codes = codes->number_of_codes(); | |
2307 if (number_of_codes == 0) return; | |
2308 int new_number_of_codes = 0; | |
2309 for (int i = 0; i < number_of_codes; i++) { | |
2310 Code* code = codes->code_at(i); | |
2311 if (IsMarked(code) && !code->marked_for_deoptimization()) { | |
2312 if (new_number_of_codes != i) { | |
2313 codes->set_code_at(new_number_of_codes, code); | |
2314 Object** slot = codes->code_slot_at(new_number_of_codes); | |
2315 RecordSlot(slot, slot, code); | |
2316 new_number_of_codes++; | |
2317 } | |
2318 } | |
2319 } | |
2320 for (int i = new_number_of_codes; i < number_of_codes; i++) { | |
2321 codes->clear_code_at(i); | |
2322 } | |
2323 codes->set_number_of_codes(new_number_of_codes); | |
2324 } | |
2325 | |
2326 | |
2263 void MarkCompactCollector::ProcessWeakMaps() { | 2327 void MarkCompactCollector::ProcessWeakMaps() { |
2264 Object* weak_map_obj = encountered_weak_maps(); | 2328 Object* weak_map_obj = encountered_weak_maps(); |
2265 while (weak_map_obj != Smi::FromInt(0)) { | 2329 while (weak_map_obj != Smi::FromInt(0)) { |
2266 ASSERT(MarkCompactCollector::IsMarked(HeapObject::cast(weak_map_obj))); | 2330 ASSERT(MarkCompactCollector::IsMarked(HeapObject::cast(weak_map_obj))); |
2267 JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj); | 2331 JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj); |
2268 ObjectHashTable* table = ObjectHashTable::cast(weak_map->table()); | 2332 ObjectHashTable* table = ObjectHashTable::cast(weak_map->table()); |
2269 Object** anchor = reinterpret_cast<Object**>(table->address()); | 2333 Object** anchor = reinterpret_cast<Object**>(table->address()); |
2270 for (int i = 0; i < table->Capacity(); i++) { | 2334 for (int i = 0; i < table->Capacity(); i++) { |
2271 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { | 2335 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { |
2272 Object** key_slot = | 2336 Object** key_slot = |
(...skipping 1575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3848 while (buffer != NULL) { | 3912 while (buffer != NULL) { |
3849 SlotsBuffer* next_buffer = buffer->next(); | 3913 SlotsBuffer* next_buffer = buffer->next(); |
3850 DeallocateBuffer(buffer); | 3914 DeallocateBuffer(buffer); |
3851 buffer = next_buffer; | 3915 buffer = next_buffer; |
3852 } | 3916 } |
3853 *buffer_address = NULL; | 3917 *buffer_address = NULL; |
3854 } | 3918 } |
3855 | 3919 |
3856 | 3920 |
3857 } } // namespace v8::internal | 3921 } } // namespace v8::internal |
OLD | NEW |