| 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 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 if (!FLAG_collect_maps) ReattachInitialMaps(); | 442 if (!FLAG_collect_maps) ReattachInitialMaps(); |
| 443 | 443 |
| 444 #ifdef DEBUG | 444 #ifdef DEBUG |
| 445 if (FLAG_verify_native_context_separation) { | 445 if (FLAG_verify_native_context_separation) { |
| 446 VerifyNativeContextSeparation(heap_); | 446 VerifyNativeContextSeparation(heap_); |
| 447 } | 447 } |
| 448 #endif | 448 #endif |
| 449 | 449 |
| 450 #ifdef VERIFY_HEAP | 450 #ifdef VERIFY_HEAP |
| 451 if (heap()->weak_embedded_objects_verification_enabled()) { | 451 if (heap()->weak_embedded_objects_verification_enabled()) { |
| 452 VerifyWeakEmbeddedObjectsInOptimizedCode(); | 452 VerifyWeakEmbeddedObjectsInCode(); |
| 453 } | 453 } |
| 454 if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) { | 454 if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) { |
| 455 VerifyOmittedMapChecks(); | 455 VerifyOmittedMapChecks(); |
| 456 } | 456 } |
| 457 #endif | 457 #endif |
| 458 | 458 |
| 459 Finish(); | 459 Finish(); |
| 460 | 460 |
| 461 if (marking_parity_ == EVEN_MARKING_PARITY) { | 461 if (marking_parity_ == EVEN_MARKING_PARITY) { |
| 462 marking_parity_ = ODD_MARKING_PARITY; | 462 marking_parity_ = ODD_MARKING_PARITY; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 | 503 |
| 504 LargeObjectIterator it(heap_->lo_space()); | 504 LargeObjectIterator it(heap_->lo_space()); |
| 505 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 505 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
| 506 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 506 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 507 CHECK(Marking::IsWhite(mark_bit)); | 507 CHECK(Marking::IsWhite(mark_bit)); |
| 508 CHECK_EQ(0, Page::FromAddress(obj->address())->LiveBytes()); | 508 CHECK_EQ(0, Page::FromAddress(obj->address())->LiveBytes()); |
| 509 } | 509 } |
| 510 } | 510 } |
| 511 | 511 |
| 512 | 512 |
| 513 void MarkCompactCollector::VerifyWeakEmbeddedObjectsInOptimizedCode() { | 513 void MarkCompactCollector::VerifyWeakEmbeddedObjectsInCode() { |
| 514 HeapObjectIterator code_iterator(heap()->code_space()); | 514 HeapObjectIterator code_iterator(heap()->code_space()); |
| 515 for (HeapObject* obj = code_iterator.Next(); | 515 for (HeapObject* obj = code_iterator.Next(); |
| 516 obj != NULL; | 516 obj != NULL; |
| 517 obj = code_iterator.Next()) { | 517 obj = code_iterator.Next()) { |
| 518 Code* code = Code::cast(obj); | 518 Code* code = Code::cast(obj); |
| 519 if (code->kind() != Code::OPTIMIZED_FUNCTION) continue; | 519 if (!code->is_optimized_code() && !code->is_weak_stub()) continue; |
| 520 if (WillBeDeoptimized(code)) continue; | 520 if (WillBeDeoptimized(code)) continue; |
| 521 code->VerifyEmbeddedObjectsDependency(); | 521 code->VerifyEmbeddedObjectsDependency(); |
| 522 } | 522 } |
| 523 } | 523 } |
| 524 | 524 |
| 525 | 525 |
| 526 void MarkCompactCollector::VerifyOmittedMapChecks() { | 526 void MarkCompactCollector::VerifyOmittedMapChecks() { |
| 527 HeapObjectIterator iterator(heap()->map_space()); | 527 HeapObjectIterator iterator(heap()->map_space()); |
| 528 for (HeapObject* obj = iterator.Next(); | 528 for (HeapObject* obj = iterator.Next(); |
| 529 obj != NULL; | 529 obj != NULL; |
| (...skipping 2046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2576 // Since it survived the GC, reattach it now. | 2576 // Since it survived the GC, reattach it now. |
| 2577 JSFunction::cast(map->constructor())->shared()->AttachInitialMap(map); | 2577 JSFunction::cast(map->constructor())->shared()->AttachInitialMap(map); |
| 2578 } | 2578 } |
| 2579 | 2579 |
| 2580 ClearNonLivePrototypeTransitions(map); | 2580 ClearNonLivePrototypeTransitions(map); |
| 2581 ClearNonLiveMapTransitions(map, map_mark); | 2581 ClearNonLiveMapTransitions(map, map_mark); |
| 2582 | 2582 |
| 2583 if (map_mark.Get()) { | 2583 if (map_mark.Get()) { |
| 2584 ClearNonLiveDependentCode(map->dependent_code()); | 2584 ClearNonLiveDependentCode(map->dependent_code()); |
| 2585 } else { | 2585 } else { |
| 2586 ClearAndDeoptimizeDependentCode(map->dependent_code()); | 2586 ClearDependentCode(map->dependent_code()); |
| 2587 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array())); | 2587 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array())); |
| 2588 } | 2588 } |
| 2589 } | 2589 } |
| 2590 | 2590 |
| 2591 // Iterate over property cell space, removing dependent code that is not | 2591 // Iterate over property cell space, removing dependent code that is not |
| 2592 // otherwise kept alive by strong references. | 2592 // otherwise kept alive by strong references. |
| 2593 HeapObjectIterator cell_iterator(heap_->property_cell_space()); | 2593 HeapObjectIterator cell_iterator(heap_->property_cell_space()); |
| 2594 for (HeapObject* cell = cell_iterator.Next(); | 2594 for (HeapObject* cell = cell_iterator.Next(); |
| 2595 cell != NULL; | 2595 cell != NULL; |
| 2596 cell = cell_iterator.Next()) { | 2596 cell = cell_iterator.Next()) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2631 } | 2631 } |
| 2632 } | 2632 } |
| 2633 if (IsMarked(key)) { | 2633 if (IsMarked(key)) { |
| 2634 if (!IsMarked(value)) { | 2634 if (!IsMarked(value)) { |
| 2635 HeapObject* obj = HeapObject::cast(value); | 2635 HeapObject* obj = HeapObject::cast(value); |
| 2636 MarkBit mark = Marking::MarkBitFrom(obj); | 2636 MarkBit mark = Marking::MarkBitFrom(obj); |
| 2637 SetMark(obj, mark); | 2637 SetMark(obj, mark); |
| 2638 } | 2638 } |
| 2639 ClearNonLiveDependentCode(DependentCode::cast(value)); | 2639 ClearNonLiveDependentCode(DependentCode::cast(value)); |
| 2640 } else { | 2640 } else { |
| 2641 ClearAndDeoptimizeDependentCode(DependentCode::cast(value)); | 2641 ClearDependentCode(DependentCode::cast(value)); |
| 2642 table->set(key_index, heap_->the_hole_value()); | 2642 table->set(key_index, heap_->the_hole_value()); |
| 2643 table->set(value_index, heap_->the_hole_value()); | 2643 table->set(value_index, heap_->the_hole_value()); |
| 2644 } | 2644 } |
| 2645 } | 2645 } |
| 2646 } | 2646 } |
| 2647 } | 2647 } |
| 2648 | 2648 |
| 2649 | 2649 |
| 2650 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { | 2650 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { |
| 2651 int number_of_transitions = map->NumberOfProtoTransitions(); | 2651 int number_of_transitions = map->NumberOfProtoTransitions(); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2701 // Follow back pointer, check whether we are dealing with a map transition | 2701 // Follow back pointer, check whether we are dealing with a map transition |
| 2702 // from a live map to a dead path and in case clear transitions of parent. | 2702 // from a live map to a dead path and in case clear transitions of parent. |
| 2703 bool current_is_alive = map_mark.Get(); | 2703 bool current_is_alive = map_mark.Get(); |
| 2704 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); | 2704 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); |
| 2705 if (!current_is_alive && parent_is_alive) { | 2705 if (!current_is_alive && parent_is_alive) { |
| 2706 parent->ClearNonLiveTransitions(heap()); | 2706 parent->ClearNonLiveTransitions(heap()); |
| 2707 } | 2707 } |
| 2708 } | 2708 } |
| 2709 | 2709 |
| 2710 | 2710 |
| 2711 void MarkCompactCollector::ClearAndDeoptimizeDependentCode( | 2711 void MarkCompactCollector::ClearDependentICList(Object* head) { |
| 2712 Object* current = head; |
| 2713 Object* undefined = heap()->undefined_value(); |
| 2714 while (current != undefined) { |
| 2715 Code* code = Code::cast(current); |
| 2716 if (IsMarked(code)) { |
| 2717 ASSERT(code->is_weak_stub()); |
| 2718 IC::InvalidateMaps(code); |
| 2719 } |
| 2720 current = code->next_code_link(); |
| 2721 code->set_next_code_link(undefined); |
| 2722 } |
| 2723 } |
| 2724 |
| 2725 |
| 2726 void MarkCompactCollector::ClearDependentCode( |
| 2712 DependentCode* entries) { | 2727 DependentCode* entries) { |
| 2713 DisallowHeapAllocation no_allocation; | 2728 DisallowHeapAllocation no_allocation; |
| 2714 DependentCode::GroupStartIndexes starts(entries); | 2729 DependentCode::GroupStartIndexes starts(entries); |
| 2715 int number_of_entries = starts.number_of_entries(); | 2730 int number_of_entries = starts.number_of_entries(); |
| 2716 if (number_of_entries == 0) return; | 2731 if (number_of_entries == 0) return; |
| 2717 for (int i = 0; i < number_of_entries; i++) { | 2732 int g = DependentCode::kWeakICGroup; |
| 2733 if (starts.at(g) != starts.at(g + 1)) { |
| 2734 int i = starts.at(g); |
| 2735 ASSERT(i + 1 == starts.at(g + 1)); |
| 2736 Object* head = entries->object_at(i); |
| 2737 ClearDependentICList(head); |
| 2738 } |
| 2739 g = DependentCode::kWeakCodeGroup; |
| 2740 for (int i = starts.at(g); i < starts.at(g + 1); i++) { |
| 2718 // If the entry is compilation info then the map must be alive, | 2741 // If the entry is compilation info then the map must be alive, |
| 2719 // and ClearAndDeoptimizeDependentCode shouldn't be called. | 2742 // and ClearDependentCode shouldn't be called. |
| 2720 ASSERT(entries->is_code_at(i)); | 2743 ASSERT(entries->is_code_at(i)); |
| 2721 Code* code = entries->code_at(i); | 2744 Code* code = entries->code_at(i); |
| 2722 | |
| 2723 if (IsMarked(code) && !code->marked_for_deoptimization()) { | 2745 if (IsMarked(code) && !code->marked_for_deoptimization()) { |
| 2724 code->set_marked_for_deoptimization(true); | 2746 code->set_marked_for_deoptimization(true); |
| 2725 code->InvalidateEmbeddedObjects(); | 2747 code->InvalidateEmbeddedObjects(); |
| 2726 have_code_to_deoptimize_ = true; | 2748 have_code_to_deoptimize_ = true; |
| 2727 } | 2749 } |
| 2750 } |
| 2751 for (int i = 0; i < number_of_entries; i++) { |
| 2728 entries->clear_at(i); | 2752 entries->clear_at(i); |
| 2729 } | 2753 } |
| 2730 } | 2754 } |
| 2731 | 2755 |
| 2732 | 2756 |
| 2757 int MarkCompactCollector::ClearNonLiveDependentCodeInGroup( |
| 2758 DependentCode* entries, int group, int start, int end, int new_start) { |
| 2759 int survived = 0; |
| 2760 if (group == DependentCode::kWeakICGroup) { |
| 2761 // Dependent weak IC stubs form a linked list and only the head is stored |
| 2762 // in the dependent code array. |
| 2763 if (start != end) { |
| 2764 ASSERT(start + 1 == end); |
| 2765 Object* old_head = entries->object_at(start); |
| 2766 MarkCompactWeakObjectRetainer retainer; |
| 2767 Object* head = VisitWeakList<Code>(heap(), old_head, &retainer, true); |
| 2768 entries->set_object_at(new_start, head); |
| 2769 Object** slot = entries->slot_at(new_start); |
| 2770 RecordSlot(slot, slot, head); |
| 2771 // We do not compact this group even if the head is undefined, |
| 2772 // more dependent ICs are likely to be added later. |
| 2773 survived = 1; |
| 2774 } |
| 2775 } else { |
| 2776 for (int i = start; i < end; i++) { |
| 2777 Object* obj = entries->object_at(i); |
| 2778 ASSERT(obj->IsCode() || IsMarked(obj)); |
| 2779 if (IsMarked(obj) && |
| 2780 (!obj->IsCode() || !WillBeDeoptimized(Code::cast(obj)))) { |
| 2781 if (new_start + survived != i) { |
| 2782 entries->set_object_at(new_start + survived, obj); |
| 2783 } |
| 2784 Object** slot = entries->slot_at(new_start + survived); |
| 2785 RecordSlot(slot, slot, obj); |
| 2786 survived++; |
| 2787 } |
| 2788 } |
| 2789 } |
| 2790 entries->set_number_of_entries( |
| 2791 static_cast<DependentCode::DependencyGroup>(group), survived); |
| 2792 return survived; |
| 2793 } |
| 2794 |
| 2795 |
| 2733 void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) { | 2796 void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) { |
| 2734 DisallowHeapAllocation no_allocation; | 2797 DisallowHeapAllocation no_allocation; |
| 2735 DependentCode::GroupStartIndexes starts(entries); | 2798 DependentCode::GroupStartIndexes starts(entries); |
| 2736 int number_of_entries = starts.number_of_entries(); | 2799 int number_of_entries = starts.number_of_entries(); |
| 2737 if (number_of_entries == 0) return; | 2800 if (number_of_entries == 0) return; |
| 2738 int new_number_of_entries = 0; | 2801 int new_number_of_entries = 0; |
| 2739 // Go through all groups, remove dead codes and compact. | 2802 // Go through all groups, remove dead codes and compact. |
| 2740 for (int g = 0; g < DependentCode::kGroupCount; g++) { | 2803 for (int g = 0; g < DependentCode::kGroupCount; g++) { |
| 2741 int group_number_of_entries = 0; | 2804 int survived = ClearNonLiveDependentCodeInGroup( |
| 2742 for (int i = starts.at(g); i < starts.at(g + 1); i++) { | 2805 entries, g, starts.at(g), starts.at(g + 1), new_number_of_entries); |
| 2743 Object* obj = entries->object_at(i); | 2806 new_number_of_entries += survived; |
| 2744 ASSERT(obj->IsCode() || IsMarked(obj)); | |
| 2745 if (IsMarked(obj) && | |
| 2746 (!obj->IsCode() || !WillBeDeoptimized(Code::cast(obj)))) { | |
| 2747 if (new_number_of_entries + group_number_of_entries != i) { | |
| 2748 entries->set_object_at( | |
| 2749 new_number_of_entries + group_number_of_entries, obj); | |
| 2750 } | |
| 2751 Object** slot = entries->slot_at(new_number_of_entries + | |
| 2752 group_number_of_entries); | |
| 2753 RecordSlot(slot, slot, obj); | |
| 2754 group_number_of_entries++; | |
| 2755 } | |
| 2756 } | |
| 2757 entries->set_number_of_entries( | |
| 2758 static_cast<DependentCode::DependencyGroup>(g), | |
| 2759 group_number_of_entries); | |
| 2760 new_number_of_entries += group_number_of_entries; | |
| 2761 } | 2807 } |
| 2762 for (int i = new_number_of_entries; i < number_of_entries; i++) { | 2808 for (int i = new_number_of_entries; i < number_of_entries; i++) { |
| 2763 entries->clear_at(i); | 2809 entries->clear_at(i); |
| 2764 } | 2810 } |
| 2765 } | 2811 } |
| 2766 | 2812 |
| 2767 | 2813 |
| 2768 void MarkCompactCollector::ProcessWeakCollections() { | 2814 void MarkCompactCollector::ProcessWeakCollections() { |
| 2769 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_WEAKCOLLECTION_PROCESS); | 2815 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_WEAKCOLLECTION_PROCESS); |
| 2770 Object* weak_collection_obj = encountered_weak_collections(); | 2816 Object* weak_collection_obj = encountered_weak_collections(); |
| (...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3407 MarkBit mark_bit = Marking::MarkBitFrom(code); | 3453 MarkBit mark_bit = Marking::MarkBitFrom(code); |
| 3408 if (Marking::IsWhite(mark_bit)) return; | 3454 if (Marking::IsWhite(mark_bit)) return; |
| 3409 | 3455 |
| 3410 invalidated_code_.Add(code); | 3456 invalidated_code_.Add(code); |
| 3411 } | 3457 } |
| 3412 } | 3458 } |
| 3413 | 3459 |
| 3414 | 3460 |
| 3415 // Return true if the given code is deoptimized or will be deoptimized. | 3461 // Return true if the given code is deoptimized or will be deoptimized. |
| 3416 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { | 3462 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { |
| 3417 return code->marked_for_deoptimization(); | 3463 return code->is_optimized_code() && code->marked_for_deoptimization(); |
| 3418 } | 3464 } |
| 3419 | 3465 |
| 3420 | 3466 |
| 3421 bool MarkCompactCollector::MarkInvalidatedCode() { | 3467 bool MarkCompactCollector::MarkInvalidatedCode() { |
| 3422 bool code_marked = false; | 3468 bool code_marked = false; |
| 3423 | 3469 |
| 3424 int length = invalidated_code_.length(); | 3470 int length = invalidated_code_.length(); |
| 3425 for (int i = 0; i < length; i++) { | 3471 for (int i = 0; i < length; i++) { |
| 3426 Code* code = invalidated_code_[i]; | 3472 Code* code = invalidated_code_[i]; |
| 3427 | 3473 |
| (...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4529 while (buffer != NULL) { | 4575 while (buffer != NULL) { |
| 4530 SlotsBuffer* next_buffer = buffer->next(); | 4576 SlotsBuffer* next_buffer = buffer->next(); |
| 4531 DeallocateBuffer(buffer); | 4577 DeallocateBuffer(buffer); |
| 4532 buffer = next_buffer; | 4578 buffer = next_buffer; |
| 4533 } | 4579 } |
| 4534 *buffer_address = NULL; | 4580 *buffer_address = NULL; |
| 4535 } | 4581 } |
| 4536 | 4582 |
| 4537 | 4583 |
| 4538 } } // namespace v8::internal | 4584 } } // namespace v8::internal |
| OLD | NEW |