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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 abort_incremental_marking_(false), | 66 abort_incremental_marking_(false), |
67 marking_parity_(ODD_MARKING_PARITY), | 67 marking_parity_(ODD_MARKING_PARITY), |
68 compacting_(false), | 68 compacting_(false), |
69 was_marked_incrementally_(false), | 69 was_marked_incrementally_(false), |
70 sweeping_pending_(false), | 70 sweeping_pending_(false), |
71 sequential_sweeping_(false), | 71 sequential_sweeping_(false), |
72 tracer_(NULL), | 72 tracer_(NULL), |
73 migration_slots_buffer_(NULL), | 73 migration_slots_buffer_(NULL), |
74 heap_(NULL), | 74 heap_(NULL), |
75 code_flusher_(NULL), | 75 code_flusher_(NULL), |
76 encountered_weak_collections_(NULL) { } | 76 encountered_weak_collections_(NULL), |
77 | 77 code_to_deoptimize_(NULL) { } |
78 | 78 |
79 #ifdef VERIFY_HEAP | 79 #ifdef VERIFY_HEAP |
80 class VerifyMarkingVisitor: public ObjectVisitor { | 80 class VerifyMarkingVisitor: public ObjectVisitor { |
81 public: | 81 public: |
82 void VisitPointers(Object** start, Object** end) { | 82 void VisitPointers(Object** start, Object** end) { |
83 for (Object** current = start; current < end; current++) { | 83 for (Object** current = start; current < end; current++) { |
84 if ((*current)->IsHeapObject()) { | 84 if ((*current)->IsHeapObject()) { |
85 HeapObject* object = HeapObject::cast(*current); | 85 HeapObject* object = HeapObject::cast(*current); |
86 CHECK(HEAP->mark_compact_collector()->IsMarked(object)); | 86 CHECK(HEAP->mark_compact_collector()->IsMarked(object)); |
87 } | 87 } |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 } | 485 } |
486 | 486 |
487 | 487 |
488 void MarkCompactCollector::VerifyWeakEmbeddedMapsInOptimizedCode() { | 488 void MarkCompactCollector::VerifyWeakEmbeddedMapsInOptimizedCode() { |
489 HeapObjectIterator code_iterator(heap()->code_space()); | 489 HeapObjectIterator code_iterator(heap()->code_space()); |
490 for (HeapObject* obj = code_iterator.Next(); | 490 for (HeapObject* obj = code_iterator.Next(); |
491 obj != NULL; | 491 obj != NULL; |
492 obj = code_iterator.Next()) { | 492 obj = code_iterator.Next()) { |
493 Code* code = Code::cast(obj); | 493 Code* code = Code::cast(obj); |
494 if (code->kind() != Code::OPTIMIZED_FUNCTION) continue; | 494 if (code->kind() != Code::OPTIMIZED_FUNCTION) continue; |
495 if (code->marked_for_deoptimization()) continue; | 495 if (WillBeDeoptimized(code)) continue; |
496 code->VerifyEmbeddedMapsDependency(); | 496 code->VerifyEmbeddedMapsDependency(); |
497 } | 497 } |
498 } | 498 } |
499 | 499 |
500 | 500 |
501 void MarkCompactCollector::VerifyOmittedPrototypeChecks() { | 501 void MarkCompactCollector::VerifyOmittedPrototypeChecks() { |
502 HeapObjectIterator iterator(heap()->map_space()); | 502 HeapObjectIterator iterator(heap()->map_space()); |
503 for (HeapObject* obj = iterator.Next(); | 503 for (HeapObject* obj = iterator.Next(); |
504 obj != NULL; | 504 obj != NULL; |
505 obj = iterator.Next()) { | 505 obj = iterator.Next()) { |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 } | 938 } |
939 | 939 |
940 #ifdef VERIFY_HEAP | 940 #ifdef VERIFY_HEAP |
941 if (!was_marked_incrementally_ && FLAG_verify_heap) { | 941 if (!was_marked_incrementally_ && FLAG_verify_heap) { |
942 VerifyMarkbitsAreClean(); | 942 VerifyMarkbitsAreClean(); |
943 } | 943 } |
944 #endif | 944 #endif |
945 } | 945 } |
946 | 946 |
947 | 947 |
948 class DeoptimizeMarkedCodeFilter : public OptimizedFunctionFilter { | |
949 public: | |
950 virtual bool TakeFunction(JSFunction* function) { | |
951 return function->code()->marked_for_deoptimization(); | |
952 } | |
953 }; | |
954 | |
955 | |
956 void MarkCompactCollector::Finish() { | 948 void MarkCompactCollector::Finish() { |
957 #ifdef DEBUG | 949 #ifdef DEBUG |
958 ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); | 950 ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); |
959 state_ = IDLE; | 951 state_ = IDLE; |
960 #endif | 952 #endif |
961 // The stub cache is not traversed during GC; clear the cache to | 953 // The stub cache is not traversed during GC; clear the cache to |
962 // force lazy re-initialization of it. This must be done after the | 954 // force lazy re-initialization of it. This must be done after the |
963 // GC, because it relies on the new address of certain old space | 955 // GC, because it relies on the new address of certain old space |
964 // objects (empty string, illegal builtin). | 956 // objects (empty string, illegal builtin). |
965 isolate()->stub_cache()->Clear(); | 957 isolate()->stub_cache()->Clear(); |
966 | 958 |
967 DeoptimizeMarkedCodeFilter filter; | 959 if (code_to_deoptimize_ != Smi::FromInt(0)) { |
968 Deoptimizer::DeoptimizeAllFunctionsWith(isolate(), &filter); | 960 // Convert the linked list of Code objects into a ZoneList. |
| 961 Zone zone(isolate()); |
| 962 ZoneList<Code*> codes(4, &zone); |
| 963 |
| 964 Object *list = code_to_deoptimize_; |
| 965 while (list->IsCode()) { |
| 966 Code *code = Code::cast(list); |
| 967 list = code->code_to_deoptimize_link(); |
| 968 codes.Add(code, &zone); |
| 969 // Destroy the link and don't ever try to deoptimize this code again. |
| 970 code->set_code_to_deoptimize_link(Smi::FromInt(0)); |
| 971 } |
| 972 code_to_deoptimize_ = Smi::FromInt(0); |
| 973 |
| 974 Deoptimizer::DeoptimizeCodeList(isolate(), &codes); |
| 975 } |
969 } | 976 } |
970 | 977 |
971 | 978 |
972 // ------------------------------------------------------------------------- | 979 // ------------------------------------------------------------------------- |
973 // Phase 1: tracing and marking live objects. | 980 // Phase 1: tracing and marking live objects. |
974 // before: all objects are in normal state. | 981 // before: all objects are in normal state. |
975 // after: a live object's map pointer is marked as '00'. | 982 // after: a live object's map pointer is marked as '00'. |
976 | 983 |
977 // Marking all live objects in the heap as part of mark-sweep or mark-compact | 984 // Marking all live objects in the heap as part of mark-sweep or mark-compact |
978 // collection. Before marking, all objects are in their normal state. After | 985 // collection. Before marking, all objects are in their normal state. After |
(...skipping 1624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2603 DisallowHeapAllocation no_allocation; | 2610 DisallowHeapAllocation no_allocation; |
2604 DependentCode* entries = map->dependent_code(); | 2611 DependentCode* entries = map->dependent_code(); |
2605 DependentCode::GroupStartIndexes starts(entries); | 2612 DependentCode::GroupStartIndexes starts(entries); |
2606 int number_of_entries = starts.number_of_entries(); | 2613 int number_of_entries = starts.number_of_entries(); |
2607 if (number_of_entries == 0) return; | 2614 if (number_of_entries == 0) return; |
2608 for (int i = 0; i < number_of_entries; i++) { | 2615 for (int i = 0; i < number_of_entries; i++) { |
2609 // If the entry is compilation info then the map must be alive, | 2616 // If the entry is compilation info then the map must be alive, |
2610 // and ClearAndDeoptimizeDependentCode shouldn't be called. | 2617 // and ClearAndDeoptimizeDependentCode shouldn't be called. |
2611 ASSERT(entries->is_code_at(i)); | 2618 ASSERT(entries->is_code_at(i)); |
2612 Code* code = entries->code_at(i); | 2619 Code* code = entries->code_at(i); |
2613 if (IsMarked(code) && !code->marked_for_deoptimization()) { | 2620 |
2614 code->set_marked_for_deoptimization(true); | 2621 if (IsMarked(code) && !WillBeDeoptimized(code)) { |
| 2622 // Insert the code into the code_to_deoptimize linked list. |
| 2623 Object* next = code_to_deoptimize_; |
| 2624 if (next != Smi::FromInt(0)) { |
| 2625 // Record the slot so that it is updated. |
| 2626 Object** slot = code->code_to_deoptimize_link_slot(); |
| 2627 RecordSlot(slot, slot, next); |
| 2628 } |
| 2629 code->set_code_to_deoptimize_link(next); |
| 2630 code_to_deoptimize_ = code; |
2615 } | 2631 } |
2616 entries->clear_at(i); | 2632 entries->clear_at(i); |
2617 } | 2633 } |
2618 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array())); | 2634 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array())); |
2619 } | 2635 } |
2620 | 2636 |
2621 | 2637 |
2622 void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) { | 2638 void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) { |
2623 DisallowHeapAllocation no_allocation; | 2639 DisallowHeapAllocation no_allocation; |
2624 DependentCode::GroupStartIndexes starts(entries); | 2640 DependentCode::GroupStartIndexes starts(entries); |
2625 int number_of_entries = starts.number_of_entries(); | 2641 int number_of_entries = starts.number_of_entries(); |
2626 if (number_of_entries == 0) return; | 2642 if (number_of_entries == 0) return; |
2627 int new_number_of_entries = 0; | 2643 int new_number_of_entries = 0; |
2628 // Go through all groups, remove dead codes and compact. | 2644 // Go through all groups, remove dead codes and compact. |
2629 for (int g = 0; g < DependentCode::kGroupCount; g++) { | 2645 for (int g = 0; g < DependentCode::kGroupCount; g++) { |
2630 int group_number_of_entries = 0; | 2646 int group_number_of_entries = 0; |
2631 for (int i = starts.at(g); i < starts.at(g + 1); i++) { | 2647 for (int i = starts.at(g); i < starts.at(g + 1); i++) { |
2632 Object* obj = entries->object_at(i); | 2648 Object* obj = entries->object_at(i); |
2633 ASSERT(obj->IsCode() || IsMarked(obj)); | 2649 ASSERT(obj->IsCode() || IsMarked(obj)); |
2634 if (IsMarked(obj) && | 2650 if (IsMarked(obj) && |
2635 (!obj->IsCode() || !Code::cast(obj)->marked_for_deoptimization())) { | 2651 (!obj->IsCode() || !WillBeDeoptimized(Code::cast(obj)))) { |
2636 if (new_number_of_entries + group_number_of_entries != i) { | 2652 if (new_number_of_entries + group_number_of_entries != i) { |
2637 entries->set_object_at( | 2653 entries->set_object_at( |
2638 new_number_of_entries + group_number_of_entries, obj); | 2654 new_number_of_entries + group_number_of_entries, obj); |
2639 } | 2655 } |
2640 Object** slot = entries->slot_at(new_number_of_entries + | 2656 Object** slot = entries->slot_at(new_number_of_entries + |
2641 group_number_of_entries); | 2657 group_number_of_entries); |
2642 RecordSlot(slot, slot, obj); | 2658 RecordSlot(slot, slot, obj); |
2643 group_number_of_entries++; | 2659 group_number_of_entries++; |
2644 } | 2660 } |
2645 } | 2661 } |
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3263 | 3279 |
3264 // If the object is white than no slots were recorded on it yet. | 3280 // If the object is white than no slots were recorded on it yet. |
3265 MarkBit mark_bit = Marking::MarkBitFrom(code); | 3281 MarkBit mark_bit = Marking::MarkBitFrom(code); |
3266 if (Marking::IsWhite(mark_bit)) return; | 3282 if (Marking::IsWhite(mark_bit)) return; |
3267 | 3283 |
3268 invalidated_code_.Add(code); | 3284 invalidated_code_.Add(code); |
3269 } | 3285 } |
3270 } | 3286 } |
3271 | 3287 |
3272 | 3288 |
| 3289 // Return true if the given code is deoptimized or will be deoptimized. |
| 3290 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { |
| 3291 // We assume the code_to_deoptimize_link is initialized to undefined. |
| 3292 // If it is 0, or refers to another Code object, then this code |
| 3293 // is already linked, or was already linked into the list. |
| 3294 return code->code_to_deoptimize_link() != heap()->undefined_value() |
| 3295 || code->marked_for_deoptimization(); |
| 3296 } |
| 3297 |
| 3298 |
3273 bool MarkCompactCollector::MarkInvalidatedCode() { | 3299 bool MarkCompactCollector::MarkInvalidatedCode() { |
3274 bool code_marked = false; | 3300 bool code_marked = false; |
3275 | 3301 |
3276 int length = invalidated_code_.length(); | 3302 int length = invalidated_code_.length(); |
3277 for (int i = 0; i < length; i++) { | 3303 for (int i = 0; i < length; i++) { |
3278 Code* code = invalidated_code_[i]; | 3304 Code* code = invalidated_code_[i]; |
3279 | 3305 |
3280 if (SetMarkBitsUnderInvalidatedCode(code, true)) { | 3306 if (SetMarkBitsUnderInvalidatedCode(code, true)) { |
3281 code_marked = true; | 3307 code_marked = true; |
3282 } | 3308 } |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3446 HeapObjectIterator js_global_property_cell_iterator( | 3472 HeapObjectIterator js_global_property_cell_iterator( |
3447 heap_->property_cell_space()); | 3473 heap_->property_cell_space()); |
3448 for (HeapObject* cell = js_global_property_cell_iterator.Next(); | 3474 for (HeapObject* cell = js_global_property_cell_iterator.Next(); |
3449 cell != NULL; | 3475 cell != NULL; |
3450 cell = js_global_property_cell_iterator.Next()) { | 3476 cell = js_global_property_cell_iterator.Next()) { |
3451 if (cell->IsPropertyCell()) { | 3477 if (cell->IsPropertyCell()) { |
3452 PropertyCell::BodyDescriptor::IterateBody(cell, &updating_visitor); | 3478 PropertyCell::BodyDescriptor::IterateBody(cell, &updating_visitor); |
3453 } | 3479 } |
3454 } | 3480 } |
3455 | 3481 |
3456 // Update pointer from the native contexts list. | 3482 // Update the heads of the native contexts list the code to deoptimize list. |
3457 updating_visitor.VisitPointer(heap_->native_contexts_list_address()); | 3483 updating_visitor.VisitPointer(heap_->native_contexts_list_address()); |
| 3484 updating_visitor.VisitPointer(&code_to_deoptimize_); |
3458 | 3485 |
3459 heap_->string_table()->Iterate(&updating_visitor); | 3486 heap_->string_table()->Iterate(&updating_visitor); |
3460 | 3487 |
3461 // Update pointers from external string table. | 3488 // Update pointers from external string table. |
3462 heap_->UpdateReferencesInExternalStringTable( | 3489 heap_->UpdateReferencesInExternalStringTable( |
3463 &UpdateReferenceInExternalStringTableEntry); | 3490 &UpdateReferenceInExternalStringTableEntry); |
3464 | 3491 |
3465 if (!FLAG_watch_ic_patching) { | 3492 if (!FLAG_watch_ic_patching) { |
3466 // Update JSFunction pointers from the runtime profiler. | 3493 // Update JSFunction pointers from the runtime profiler. |
3467 heap()->isolate()->runtime_profiler()->UpdateSamplesAfterCompact( | 3494 heap()->isolate()->runtime_profiler()->UpdateSamplesAfterCompact( |
(...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4311 while (buffer != NULL) { | 4338 while (buffer != NULL) { |
4312 SlotsBuffer* next_buffer = buffer->next(); | 4339 SlotsBuffer* next_buffer = buffer->next(); |
4313 DeallocateBuffer(buffer); | 4340 DeallocateBuffer(buffer); |
4314 buffer = next_buffer; | 4341 buffer = next_buffer; |
4315 } | 4342 } |
4316 *buffer_address = NULL; | 4343 *buffer_address = NULL; |
4317 } | 4344 } |
4318 | 4345 |
4319 | 4346 |
4320 } } // namespace v8::internal | 4347 } } // namespace v8::internal |
OLD | NEW |