| 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 1921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1932 | 1932 |
| 1933 | 1933 |
| 1934 static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque, | 1934 static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque, |
| 1935 MemoryChunk* p) { | 1935 MemoryChunk* p) { |
| 1936 ASSERT(!marking_deque->IsFull()); | 1936 ASSERT(!marking_deque->IsFull()); |
| 1937 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 1937 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
| 1938 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 1938 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| 1939 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); | 1939 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); |
| 1940 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 1940 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 1941 | 1941 |
| 1942 MarkBit::CellType* cells = p->markbits()->cells(); | 1942 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
| 1943 Address cell_base = it.CurrentCellBase(); |
| 1944 MarkBit::CellType* cell = it.CurrentCell(); |
| 1943 | 1945 |
| 1944 int last_cell_index = | 1946 const MarkBit::CellType current_cell = *cell; |
| 1945 Bitmap::IndexToCell( | |
| 1946 Bitmap::CellAlignIndex( | |
| 1947 p->AddressToMarkbitIndex(p->area_end()))); | |
| 1948 | |
| 1949 Address cell_base = p->area_start(); | |
| 1950 int cell_index = Bitmap::IndexToCell( | |
| 1951 Bitmap::CellAlignIndex( | |
| 1952 p->AddressToMarkbitIndex(cell_base))); | |
| 1953 | |
| 1954 | |
| 1955 for (; | |
| 1956 cell_index < last_cell_index; | |
| 1957 cell_index++, cell_base += 32 * kPointerSize) { | |
| 1958 ASSERT(static_cast<unsigned>(cell_index) == | |
| 1959 Bitmap::IndexToCell( | |
| 1960 Bitmap::CellAlignIndex( | |
| 1961 p->AddressToMarkbitIndex(cell_base)))); | |
| 1962 | |
| 1963 const MarkBit::CellType current_cell = cells[cell_index]; | |
| 1964 if (current_cell == 0) continue; | 1947 if (current_cell == 0) continue; |
| 1965 | 1948 |
| 1966 const MarkBit::CellType next_cell = cells[cell_index + 1]; | 1949 MarkBit::CellType grey_objects; |
| 1967 MarkBit::CellType grey_objects = current_cell & | 1950 if (it.HasNext()) { |
| 1968 ((current_cell >> 1) | (next_cell << (Bitmap::kBitsPerCell - 1))); | 1951 const MarkBit::CellType next_cell = *(cell+1); |
| 1952 grey_objects = current_cell & |
| 1953 ((current_cell >> 1) | (next_cell << (Bitmap::kBitsPerCell - 1))); |
| 1954 } else { |
| 1955 grey_objects = current_cell & (current_cell >> 1); |
| 1956 } |
| 1969 | 1957 |
| 1970 int offset = 0; | 1958 int offset = 0; |
| 1971 while (grey_objects != 0) { | 1959 while (grey_objects != 0) { |
| 1972 int trailing_zeros = CompilerIntrinsics::CountTrailingZeros(grey_objects); | 1960 int trailing_zeros = CompilerIntrinsics::CountTrailingZeros(grey_objects); |
| 1973 grey_objects >>= trailing_zeros; | 1961 grey_objects >>= trailing_zeros; |
| 1974 offset += trailing_zeros; | 1962 offset += trailing_zeros; |
| 1975 MarkBit markbit(&cells[cell_index], 1 << offset, false); | 1963 MarkBit markbit(cell, 1 << offset, false); |
| 1976 ASSERT(Marking::IsGrey(markbit)); | 1964 ASSERT(Marking::IsGrey(markbit)); |
| 1977 Marking::GreyToBlack(markbit); | 1965 Marking::GreyToBlack(markbit); |
| 1978 Address addr = cell_base + offset * kPointerSize; | 1966 Address addr = cell_base + offset * kPointerSize; |
| 1979 HeapObject* object = HeapObject::FromAddress(addr); | 1967 HeapObject* object = HeapObject::FromAddress(addr); |
| 1980 MemoryChunk::IncrementLiveBytesFromGC(object->address(), object->Size()); | 1968 MemoryChunk::IncrementLiveBytesFromGC(object->address(), object->Size()); |
| 1981 marking_deque->PushBlack(object); | 1969 marking_deque->PushBlack(object); |
| 1982 if (marking_deque->IsFull()) return; | 1970 if (marking_deque->IsFull()) return; |
| 1983 offset += 2; | 1971 offset += 2; |
| 1984 grey_objects >>= 2; | 1972 grey_objects >>= 2; |
| 1985 } | 1973 } |
| 1986 | 1974 |
| 1987 grey_objects >>= (Bitmap::kBitsPerCell - 1); | 1975 grey_objects >>= (Bitmap::kBitsPerCell - 1); |
| 1988 } | 1976 } |
| 1989 } | 1977 } |
| 1990 | 1978 |
| 1991 | 1979 |
| 1980 int MarkCompactCollector::DiscoverAndPromoteBlackObjectsOnPage( |
| 1981 NewSpace* new_space, |
| 1982 NewSpacePage* p) { |
| 1983 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
| 1984 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| 1985 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); |
| 1986 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 1987 |
| 1988 MarkBit::CellType* cells = p->markbits()->cells(); |
| 1989 int survivors_size = 0; |
| 1990 |
| 1991 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
| 1992 Address cell_base = it.CurrentCellBase(); |
| 1993 MarkBit::CellType* cell = it.CurrentCell(); |
| 1994 |
| 1995 MarkBit::CellType current_cell = *cell; |
| 1996 if (current_cell == 0) continue; |
| 1997 |
| 1998 int offset = 0; |
| 1999 while (current_cell != 0) { |
| 2000 int trailing_zeros = CompilerIntrinsics::CountTrailingZeros(current_cell); |
| 2001 current_cell >>= trailing_zeros; |
| 2002 offset += trailing_zeros; |
| 2003 Address address = cell_base + offset * kPointerSize; |
| 2004 HeapObject* object = HeapObject::FromAddress(address); |
| 2005 |
| 2006 int size = object->Size(); |
| 2007 survivors_size += size; |
| 2008 |
| 2009 offset++; |
| 2010 current_cell >>= 1; |
| 2011 // Aggressively promote young survivors to the old space. |
| 2012 if (TryPromoteObject(object, size)) { |
| 2013 continue; |
| 2014 } |
| 2015 |
| 2016 // Promotion failed. Just migrate object to another semispace. |
| 2017 MaybeObject* allocation = new_space->AllocateRaw(size); |
| 2018 if (allocation->IsFailure()) { |
| 2019 if (!new_space->AddFreshPage()) { |
| 2020 // Shouldn't happen. We are sweeping linearly, and to-space |
| 2021 // has the same number of pages as from-space, so there is |
| 2022 // always room. |
| 2023 UNREACHABLE(); |
| 2024 } |
| 2025 allocation = new_space->AllocateRaw(size); |
| 2026 ASSERT(!allocation->IsFailure()); |
| 2027 } |
| 2028 Object* target = allocation->ToObjectUnchecked(); |
| 2029 |
| 2030 MigrateObject(HeapObject::cast(target)->address(), |
| 2031 object->address(), |
| 2032 size, |
| 2033 NEW_SPACE); |
| 2034 } |
| 2035 *cells = 0; |
| 2036 } |
| 2037 return survivors_size; |
| 2038 } |
| 2039 |
| 2040 |
| 1992 static void DiscoverGreyObjectsInSpace(Heap* heap, | 2041 static void DiscoverGreyObjectsInSpace(Heap* heap, |
| 1993 MarkingDeque* marking_deque, | 2042 MarkingDeque* marking_deque, |
| 1994 PagedSpace* space) { | 2043 PagedSpace* space) { |
| 1995 if (!space->was_swept_conservatively()) { | 2044 if (!space->was_swept_conservatively()) { |
| 1996 HeapObjectIterator it(space); | 2045 HeapObjectIterator it(space); |
| 1997 DiscoverGreyObjectsWithIterator(heap, marking_deque, &it); | 2046 DiscoverGreyObjectsWithIterator(heap, marking_deque, &it); |
| 1998 } else { | 2047 } else { |
| 1999 PageIterator it(space); | 2048 PageIterator it(space); |
| 2000 while (it.has_next()) { | 2049 while (it.has_next()) { |
| 2001 Page* p = it.next(); | 2050 Page* p = it.next(); |
| (...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2888 // live objects. | 2937 // live objects. |
| 2889 new_space->Flip(); | 2938 new_space->Flip(); |
| 2890 new_space->ResetAllocationInfo(); | 2939 new_space->ResetAllocationInfo(); |
| 2891 | 2940 |
| 2892 int survivors_size = 0; | 2941 int survivors_size = 0; |
| 2893 | 2942 |
| 2894 // First pass: traverse all objects in inactive semispace, remove marks, | 2943 // First pass: traverse all objects in inactive semispace, remove marks, |
| 2895 // migrate live objects and write forwarding addresses. This stage puts | 2944 // migrate live objects and write forwarding addresses. This stage puts |
| 2896 // new entries in the store buffer and may cause some pages to be marked | 2945 // new entries in the store buffer and may cause some pages to be marked |
| 2897 // scan-on-scavenge. | 2946 // scan-on-scavenge. |
| 2898 SemiSpaceIterator from_it(from_bottom, from_top); | 2947 NewSpacePageIterator it(from_bottom, from_top); |
| 2899 for (HeapObject* object = from_it.Next(); | 2948 while (it.has_next()) { |
| 2900 object != NULL; | 2949 NewSpacePage* p = it.next(); |
| 2901 object = from_it.Next()) { | 2950 survivors_size += DiscoverAndPromoteBlackObjectsOnPage(new_space, p); |
| 2902 MarkBit mark_bit = Marking::MarkBitFrom(object); | |
| 2903 if (mark_bit.Get()) { | |
| 2904 mark_bit.Clear(); | |
| 2905 // Don't bother decrementing live bytes count. We'll discard the | |
| 2906 // entire page at the end. | |
| 2907 int size = object->Size(); | |
| 2908 survivors_size += size; | |
| 2909 | |
| 2910 // Aggressively promote young survivors to the old space. | |
| 2911 if (TryPromoteObject(object, size)) { | |
| 2912 continue; | |
| 2913 } | |
| 2914 | |
| 2915 // Promotion failed. Just migrate object to another semispace. | |
| 2916 MaybeObject* allocation = new_space->AllocateRaw(size); | |
| 2917 if (allocation->IsFailure()) { | |
| 2918 if (!new_space->AddFreshPage()) { | |
| 2919 // Shouldn't happen. We are sweeping linearly, and to-space | |
| 2920 // has the same number of pages as from-space, so there is | |
| 2921 // always room. | |
| 2922 UNREACHABLE(); | |
| 2923 } | |
| 2924 allocation = new_space->AllocateRaw(size); | |
| 2925 ASSERT(!allocation->IsFailure()); | |
| 2926 } | |
| 2927 Object* target = allocation->ToObjectUnchecked(); | |
| 2928 | |
| 2929 MigrateObject(HeapObject::cast(target)->address(), | |
| 2930 object->address(), | |
| 2931 size, | |
| 2932 NEW_SPACE); | |
| 2933 } else { | |
| 2934 // Mark dead objects in the new space with null in their map field. | |
| 2935 Memory::Address_at(object->address()) = NULL; | |
| 2936 } | |
| 2937 } | 2951 } |
| 2938 | 2952 |
| 2939 heap_->IncrementYoungSurvivorsCounter(survivors_size); | 2953 heap_->IncrementYoungSurvivorsCounter(survivors_size); |
| 2940 new_space->set_age_mark(new_space->top()); | 2954 new_space->set_age_mark(new_space->top()); |
| 2941 } | 2955 } |
| 2942 | 2956 |
| 2943 | 2957 |
| 2944 void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { | 2958 void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { |
| 2945 AlwaysAllocateScope always_allocate; | 2959 AlwaysAllocateScope always_allocate; |
| 2946 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 2960 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 2947 ASSERT(p->IsEvacuationCandidate() && !p->WasSwept()); | 2961 ASSERT(p->IsEvacuationCandidate() && !p->WasSwept()); |
| 2948 MarkBit::CellType* cells = p->markbits()->cells(); | |
| 2949 p->MarkSweptPrecisely(); | 2962 p->MarkSweptPrecisely(); |
| 2950 | 2963 |
| 2951 int last_cell_index = | |
| 2952 Bitmap::IndexToCell( | |
| 2953 Bitmap::CellAlignIndex( | |
| 2954 p->AddressToMarkbitIndex(p->area_end()))); | |
| 2955 | |
| 2956 Address cell_base = p->area_start(); | |
| 2957 int cell_index = Bitmap::IndexToCell( | |
| 2958 Bitmap::CellAlignIndex( | |
| 2959 p->AddressToMarkbitIndex(cell_base))); | |
| 2960 | |
| 2961 int offsets[16]; | 2964 int offsets[16]; |
| 2962 | 2965 |
| 2963 for (; | 2966 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
| 2964 cell_index < last_cell_index; | 2967 Address cell_base = it.CurrentCellBase(); |
| 2965 cell_index++, cell_base += 32 * kPointerSize) { | 2968 MarkBit::CellType* cell = it.CurrentCell(); |
| 2966 ASSERT(static_cast<unsigned>(cell_index) == | |
| 2967 Bitmap::IndexToCell( | |
| 2968 Bitmap::CellAlignIndex( | |
| 2969 p->AddressToMarkbitIndex(cell_base)))); | |
| 2970 if (cells[cell_index] == 0) continue; | |
| 2971 | 2969 |
| 2972 int live_objects = MarkWordToObjectStarts(cells[cell_index], offsets); | 2970 if (*cell == 0) continue; |
| 2971 |
| 2972 int live_objects = MarkWordToObjectStarts(*cell, offsets); |
| 2973 for (int i = 0; i < live_objects; i++) { | 2973 for (int i = 0; i < live_objects; i++) { |
| 2974 Address object_addr = cell_base + offsets[i] * kPointerSize; | 2974 Address object_addr = cell_base + offsets[i] * kPointerSize; |
| 2975 HeapObject* object = HeapObject::FromAddress(object_addr); | 2975 HeapObject* object = HeapObject::FromAddress(object_addr); |
| 2976 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); | 2976 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 2977 | 2977 |
| 2978 int size = object->Size(); | 2978 int size = object->Size(); |
| 2979 | 2979 |
| 2980 MaybeObject* target = space->AllocateRaw(size); | 2980 MaybeObject* target = space->AllocateRaw(size); |
| 2981 if (target->IsFailure()) { | 2981 if (target->IsFailure()) { |
| 2982 // OS refused to give us memory. | 2982 // OS refused to give us memory. |
| 2983 V8::FatalProcessOutOfMemory("Evacuation"); | 2983 V8::FatalProcessOutOfMemory("Evacuation"); |
| 2984 return; | 2984 return; |
| 2985 } | 2985 } |
| 2986 | 2986 |
| 2987 Object* target_object = target->ToObjectUnchecked(); | 2987 Object* target_object = target->ToObjectUnchecked(); |
| 2988 | 2988 |
| 2989 MigrateObject(HeapObject::cast(target_object)->address(), | 2989 MigrateObject(HeapObject::cast(target_object)->address(), |
| 2990 object_addr, | 2990 object_addr, |
| 2991 size, | 2991 size, |
| 2992 space->identity()); | 2992 space->identity()); |
| 2993 ASSERT(object->map_word().IsForwardingAddress()); | 2993 ASSERT(object->map_word().IsForwardingAddress()); |
| 2994 } | 2994 } |
| 2995 | 2995 |
| 2996 // Clear marking bits for current cell. | 2996 // Clear marking bits for current cell. |
| 2997 cells[cell_index] = 0; | 2997 *cell = 0; |
| 2998 } | 2998 } |
| 2999 p->ResetLiveBytes(); | 2999 p->ResetLiveBytes(); |
| 3000 } | 3000 } |
| 3001 | 3001 |
| 3002 | 3002 |
| 3003 void MarkCompactCollector::EvacuatePages() { | 3003 void MarkCompactCollector::EvacuatePages() { |
| 3004 int npages = evacuation_candidates_.length(); | 3004 int npages = evacuation_candidates_.length(); |
| 3005 for (int i = 0; i < npages; i++) { | 3005 for (int i = 0; i < npages; i++) { |
| 3006 Page* p = evacuation_candidates_[i]; | 3006 Page* p = evacuation_candidates_[i]; |
| 3007 ASSERT(p->IsEvacuationCandidate() || | 3007 ASSERT(p->IsEvacuationCandidate() || |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3108 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); | 3108 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); |
| 3109 ASSERT_EQ(skip_list_mode == REBUILD_SKIP_LIST, | 3109 ASSERT_EQ(skip_list_mode == REBUILD_SKIP_LIST, |
| 3110 space->identity() == CODE_SPACE); | 3110 space->identity() == CODE_SPACE); |
| 3111 ASSERT((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); | 3111 ASSERT((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); |
| 3112 | 3112 |
| 3113 double start_time = 0.0; | 3113 double start_time = 0.0; |
| 3114 if (FLAG_print_cumulative_gc_stat) { | 3114 if (FLAG_print_cumulative_gc_stat) { |
| 3115 start_time = OS::TimeCurrentMillis(); | 3115 start_time = OS::TimeCurrentMillis(); |
| 3116 } | 3116 } |
| 3117 | 3117 |
| 3118 MarkBit::CellType* cells = p->markbits()->cells(); | |
| 3119 p->MarkSweptPrecisely(); | 3118 p->MarkSweptPrecisely(); |
| 3120 | 3119 |
| 3121 int last_cell_index = | |
| 3122 Bitmap::IndexToCell( | |
| 3123 Bitmap::CellAlignIndex( | |
| 3124 p->AddressToMarkbitIndex(p->area_end()))); | |
| 3125 | |
| 3126 Address free_start = p->area_start(); | 3120 Address free_start = p->area_start(); |
| 3127 int cell_index = | |
| 3128 Bitmap::IndexToCell( | |
| 3129 Bitmap::CellAlignIndex( | |
| 3130 p->AddressToMarkbitIndex(free_start))); | |
| 3131 | |
| 3132 ASSERT(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3121 ASSERT(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
| 3133 Address object_address = free_start; | |
| 3134 int offsets[16]; | 3122 int offsets[16]; |
| 3135 | 3123 |
| 3136 SkipList* skip_list = p->skip_list(); | 3124 SkipList* skip_list = p->skip_list(); |
| 3137 int curr_region = -1; | 3125 int curr_region = -1; |
| 3138 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) { | 3126 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) { |
| 3139 skip_list->Clear(); | 3127 skip_list->Clear(); |
| 3140 } | 3128 } |
| 3141 | 3129 |
| 3142 for (; | 3130 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
| 3143 cell_index < last_cell_index; | 3131 Address cell_base = it.CurrentCellBase(); |
| 3144 cell_index++, object_address += 32 * kPointerSize) { | 3132 MarkBit::CellType* cell = it.CurrentCell(); |
| 3145 ASSERT(static_cast<unsigned>(cell_index) == | 3133 int live_objects = MarkWordToObjectStarts(*cell, offsets); |
| 3146 Bitmap::IndexToCell( | |
| 3147 Bitmap::CellAlignIndex( | |
| 3148 p->AddressToMarkbitIndex(object_address)))); | |
| 3149 int live_objects = MarkWordToObjectStarts(cells[cell_index], offsets); | |
| 3150 int live_index = 0; | 3134 int live_index = 0; |
| 3151 for ( ; live_objects != 0; live_objects--) { | 3135 for ( ; live_objects != 0; live_objects--) { |
| 3152 Address free_end = object_address + offsets[live_index++] * kPointerSize; | 3136 Address free_end = cell_base + offsets[live_index++] * kPointerSize; |
| 3153 if (free_end != free_start) { | 3137 if (free_end != free_start) { |
| 3154 space->Free(free_start, static_cast<int>(free_end - free_start)); | 3138 space->Free(free_start, static_cast<int>(free_end - free_start)); |
| 3155 #ifdef ENABLE_GDB_JIT_INTERFACE | 3139 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 3156 if (FLAG_gdbjit && space->identity() == CODE_SPACE) { | 3140 if (FLAG_gdbjit && space->identity() == CODE_SPACE) { |
| 3157 GDBJITInterface::RemoveCodeRange(free_start, free_end); | 3141 GDBJITInterface::RemoveCodeRange(free_start, free_end); |
| 3158 } | 3142 } |
| 3159 #endif | 3143 #endif |
| 3160 } | 3144 } |
| 3161 HeapObject* live_object = HeapObject::FromAddress(free_end); | 3145 HeapObject* live_object = HeapObject::FromAddress(free_end); |
| 3162 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(live_object))); | 3146 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(live_object))); |
| 3163 Map* map = live_object->map(); | 3147 Map* map = live_object->map(); |
| 3164 int size = live_object->SizeFromMap(map); | 3148 int size = live_object->SizeFromMap(map); |
| 3165 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { | 3149 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { |
| 3166 live_object->IterateBody(map->instance_type(), size, v); | 3150 live_object->IterateBody(map->instance_type(), size, v); |
| 3167 } | 3151 } |
| 3168 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { | 3152 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { |
| 3169 int new_region_start = | 3153 int new_region_start = |
| 3170 SkipList::RegionNumber(free_end); | 3154 SkipList::RegionNumber(free_end); |
| 3171 int new_region_end = | 3155 int new_region_end = |
| 3172 SkipList::RegionNumber(free_end + size - kPointerSize); | 3156 SkipList::RegionNumber(free_end + size - kPointerSize); |
| 3173 if (new_region_start != curr_region || | 3157 if (new_region_start != curr_region || |
| 3174 new_region_end != curr_region) { | 3158 new_region_end != curr_region) { |
| 3175 skip_list->AddObject(free_end, size); | 3159 skip_list->AddObject(free_end, size); |
| 3176 curr_region = new_region_end; | 3160 curr_region = new_region_end; |
| 3177 } | 3161 } |
| 3178 } | 3162 } |
| 3179 free_start = free_end + size; | 3163 free_start = free_end + size; |
| 3180 } | 3164 } |
| 3181 // Clear marking bits for current cell. | 3165 // Clear marking bits for current cell. |
| 3182 cells[cell_index] = 0; | 3166 *cell = 0; |
| 3183 } | 3167 } |
| 3184 if (free_start != p->area_end()) { | 3168 if (free_start != p->area_end()) { |
| 3185 space->Free(free_start, static_cast<int>(p->area_end() - free_start)); | 3169 space->Free(free_start, static_cast<int>(p->area_end() - free_start)); |
| 3186 #ifdef ENABLE_GDB_JIT_INTERFACE | 3170 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 3187 if (FLAG_gdbjit && space->identity() == CODE_SPACE) { | 3171 if (FLAG_gdbjit && space->identity() == CODE_SPACE) { |
| 3188 GDBJITInterface::RemoveCodeRange(free_start, p->area_end()); | 3172 GDBJITInterface::RemoveCodeRange(free_start, p->area_end()); |
| 3189 } | 3173 } |
| 3190 #endif | 3174 #endif |
| 3191 } | 3175 } |
| 3192 p->ResetLiveBytes(); | 3176 p->ResetLiveBytes(); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3347 GCTracer::Scope::MC_UPDATE_ROOT_TO_NEW_POINTERS); | 3331 GCTracer::Scope::MC_UPDATE_ROOT_TO_NEW_POINTERS); |
| 3348 // Update roots. | 3332 // Update roots. |
| 3349 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 3333 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 3350 } | 3334 } |
| 3351 | 3335 |
| 3352 { GCTracer::Scope gc_scope(tracer_, | 3336 { GCTracer::Scope gc_scope(tracer_, |
| 3353 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS); | 3337 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS); |
| 3354 StoreBufferRebuildScope scope(heap_, | 3338 StoreBufferRebuildScope scope(heap_, |
| 3355 heap_->store_buffer(), | 3339 heap_->store_buffer(), |
| 3356 &Heap::ScavengeStoreBufferCallback); | 3340 &Heap::ScavengeStoreBufferCallback); |
| 3357 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); | 3341 heap_->store_buffer()->IteratePointersToNewSpaceAndClearMaps( |
| 3342 &UpdatePointer); |
| 3358 } | 3343 } |
| 3359 | 3344 |
| 3360 { GCTracer::Scope gc_scope(tracer_, | 3345 { GCTracer::Scope gc_scope(tracer_, |
| 3361 GCTracer::Scope::MC_UPDATE_POINTERS_TO_EVACUATED); | 3346 GCTracer::Scope::MC_UPDATE_POINTERS_TO_EVACUATED); |
| 3362 SlotsBuffer::UpdateSlotsRecordedIn(heap_, | 3347 SlotsBuffer::UpdateSlotsRecordedIn(heap_, |
| 3363 migration_slots_buffer_, | 3348 migration_slots_buffer_, |
| 3364 code_slots_filtering_required); | 3349 code_slots_filtering_required); |
| 3365 if (FLAG_trace_fragmentation) { | 3350 if (FLAG_trace_fragmentation) { |
| 3366 PrintF(" migration slots buffer: %d\n", | 3351 PrintF(" migration slots buffer: %d\n", |
| 3367 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); | 3352 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3838 template<MarkCompactCollector::SweepingParallelism mode> | 3823 template<MarkCompactCollector::SweepingParallelism mode> |
| 3839 intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space, | 3824 intptr_t MarkCompactCollector::SweepConservatively(PagedSpace* space, |
| 3840 FreeList* free_list, | 3825 FreeList* free_list, |
| 3841 Page* p) { | 3826 Page* p) { |
| 3842 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); | 3827 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); |
| 3843 ASSERT((mode == MarkCompactCollector::SWEEP_IN_PARALLEL && | 3828 ASSERT((mode == MarkCompactCollector::SWEEP_IN_PARALLEL && |
| 3844 free_list != NULL) || | 3829 free_list != NULL) || |
| 3845 (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY && | 3830 (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY && |
| 3846 free_list == NULL)); | 3831 free_list == NULL)); |
| 3847 | 3832 |
| 3848 MarkBit::CellType* cells = p->markbits()->cells(); | |
| 3849 p->MarkSweptConservatively(); | 3833 p->MarkSweptConservatively(); |
| 3850 | 3834 |
| 3851 int last_cell_index = | |
| 3852 Bitmap::IndexToCell( | |
| 3853 Bitmap::CellAlignIndex( | |
| 3854 p->AddressToMarkbitIndex(p->area_end()))); | |
| 3855 | |
| 3856 int cell_index = | |
| 3857 Bitmap::IndexToCell( | |
| 3858 Bitmap::CellAlignIndex( | |
| 3859 p->AddressToMarkbitIndex(p->area_start()))); | |
| 3860 | |
| 3861 intptr_t freed_bytes = 0; | 3835 intptr_t freed_bytes = 0; |
| 3862 | 3836 size_t size = 0; |
| 3863 // This is the start of the 32 word block that we are currently looking at. | |
| 3864 Address block_address = p->area_start(); | |
| 3865 | 3837 |
| 3866 // Skip over all the dead objects at the start of the page and mark them free. | 3838 // Skip over all the dead objects at the start of the page and mark them free. |
| 3867 for (; | 3839 Address cell_base = 0; |
| 3868 cell_index < last_cell_index; | 3840 MarkBit::CellType* cell = NULL; |
| 3869 cell_index++, block_address += 32 * kPointerSize) { | 3841 MarkBitCellIterator it(p); |
| 3870 if (cells[cell_index] != 0) break; | 3842 for (; !it.Done(); it.Advance()) { |
| 3843 cell_base = it.CurrentCellBase(); |
| 3844 cell = it.CurrentCell(); |
| 3845 if (*cell != 0) break; |
| 3871 } | 3846 } |
| 3872 size_t size = block_address - p->area_start(); | 3847 |
| 3873 if (cell_index == last_cell_index) { | 3848 if (it.Done()) { |
| 3849 size = p->area_end() - p->area_start(); |
| 3874 freed_bytes += Free<mode>(space, free_list, p->area_start(), | 3850 freed_bytes += Free<mode>(space, free_list, p->area_start(), |
| 3875 static_cast<int>(size)); | 3851 static_cast<int>(size)); |
| 3876 ASSERT_EQ(0, p->LiveBytes()); | 3852 ASSERT_EQ(0, p->LiveBytes()); |
| 3877 return freed_bytes; | 3853 return freed_bytes; |
| 3878 } | 3854 } |
| 3855 |
| 3879 // Grow the size of the start-of-page free space a little to get up to the | 3856 // Grow the size of the start-of-page free space a little to get up to the |
| 3880 // first live object. | 3857 // first live object. |
| 3881 Address free_end = StartOfLiveObject(block_address, cells[cell_index]); | 3858 Address free_end = StartOfLiveObject(cell_base, *cell); |
| 3882 // Free the first free space. | 3859 // Free the first free space. |
| 3883 size = free_end - p->area_start(); | 3860 size = free_end - p->area_start(); |
| 3884 freed_bytes += Free<mode>(space, free_list, p->area_start(), | 3861 freed_bytes += Free<mode>(space, free_list, p->area_start(), |
| 3885 static_cast<int>(size)); | 3862 static_cast<int>(size)); |
| 3886 | 3863 |
| 3887 // The start of the current free area is represented in undigested form by | 3864 // The start of the current free area is represented in undigested form by |
| 3888 // the address of the last 32-word section that contained a live object and | 3865 // the address of the last 32-word section that contained a live object and |
| 3889 // the marking bitmap for that cell, which describes where the live object | 3866 // the marking bitmap for that cell, which describes where the live object |
| 3890 // started. Unless we find a large free space in the bitmap we will not | 3867 // started. Unless we find a large free space in the bitmap we will not |
| 3891 // digest this pair into a real address. We start the iteration here at the | 3868 // digest this pair into a real address. We start the iteration here at the |
| 3892 // first word in the marking bit map that indicates a live object. | 3869 // first word in the marking bit map that indicates a live object. |
| 3893 Address free_start = block_address; | 3870 Address free_start = cell_base; |
| 3894 uint32_t free_start_cell = cells[cell_index]; | 3871 MarkBit::CellType free_start_cell = *cell; |
| 3895 | 3872 |
| 3896 for ( ; | 3873 for (; !it.Done(); it.Advance()) { |
| 3897 cell_index < last_cell_index; | 3874 cell_base = it.CurrentCellBase(); |
| 3898 cell_index++, block_address += 32 * kPointerSize) { | 3875 cell = it.CurrentCell(); |
| 3899 ASSERT((unsigned)cell_index == | 3876 if (*cell != 0) { |
| 3900 Bitmap::IndexToCell( | |
| 3901 Bitmap::CellAlignIndex( | |
| 3902 p->AddressToMarkbitIndex(block_address)))); | |
| 3903 uint32_t cell = cells[cell_index]; | |
| 3904 if (cell != 0) { | |
| 3905 // We have a live object. Check approximately whether it is more than 32 | 3877 // We have a live object. Check approximately whether it is more than 32 |
| 3906 // words since the last live object. | 3878 // words since the last live object. |
| 3907 if (block_address - free_start > 32 * kPointerSize) { | 3879 if (cell_base - free_start > 32 * kPointerSize) { |
| 3908 free_start = DigestFreeStart(free_start, free_start_cell); | 3880 free_start = DigestFreeStart(free_start, free_start_cell); |
| 3909 if (block_address - free_start > 32 * kPointerSize) { | 3881 if (cell_base - free_start > 32 * kPointerSize) { |
| 3910 // Now that we know the exact start of the free space it still looks | 3882 // Now that we know the exact start of the free space it still looks |
| 3911 // like we have a large enough free space to be worth bothering with. | 3883 // like we have a large enough free space to be worth bothering with. |
| 3912 // so now we need to find the start of the first live object at the | 3884 // so now we need to find the start of the first live object at the |
| 3913 // end of the free space. | 3885 // end of the free space. |
| 3914 free_end = StartOfLiveObject(block_address, cell); | 3886 free_end = StartOfLiveObject(cell_base, *cell); |
| 3915 freed_bytes += Free<mode>(space, free_list, free_start, | 3887 freed_bytes += Free<mode>(space, free_list, free_start, |
| 3916 static_cast<int>(free_end - free_start)); | 3888 static_cast<int>(free_end - free_start)); |
| 3917 } | 3889 } |
| 3918 } | 3890 } |
| 3919 // Update our undigested record of where the current free area started. | 3891 // Update our undigested record of where the current free area started. |
| 3920 free_start = block_address; | 3892 free_start = cell_base; |
| 3921 free_start_cell = cell; | 3893 free_start_cell = *cell; |
| 3922 // Clear marking bits for current cell. | 3894 // Clear marking bits for current cell. |
| 3923 cells[cell_index] = 0; | 3895 *cell = 0; |
| 3924 } | 3896 } |
| 3925 } | 3897 } |
| 3926 | 3898 |
| 3927 // Handle the free space at the end of the page. | 3899 // Handle the free space at the end of the page. |
| 3928 if (block_address - free_start > 32 * kPointerSize) { | 3900 if (cell_base - free_start > 32 * kPointerSize) { |
| 3929 free_start = DigestFreeStart(free_start, free_start_cell); | 3901 free_start = DigestFreeStart(free_start, free_start_cell); |
| 3930 freed_bytes += Free<mode>(space, free_list, free_start, | 3902 freed_bytes += Free<mode>(space, free_list, free_start, |
| 3931 static_cast<int>(block_address - free_start)); | 3903 static_cast<int>(p->area_end() - free_start)); |
| 3932 } | 3904 } |
| 3933 | 3905 |
| 3934 p->ResetLiveBytes(); | 3906 p->ResetLiveBytes(); |
| 3935 return freed_bytes; | 3907 return freed_bytes; |
| 3936 } | 3908 } |
| 3937 | 3909 |
| 3938 | 3910 |
| 3939 void MarkCompactCollector::SweepInParallel(PagedSpace* space, | 3911 void MarkCompactCollector::SweepInParallel(PagedSpace* space, |
| 3940 FreeList* private_free_list, | 3912 FreeList* private_free_list, |
| 3941 FreeList* free_list) { | 3913 FreeList* free_list) { |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4331 while (buffer != NULL) { | 4303 while (buffer != NULL) { |
| 4332 SlotsBuffer* next_buffer = buffer->next(); | 4304 SlotsBuffer* next_buffer = buffer->next(); |
| 4333 DeallocateBuffer(buffer); | 4305 DeallocateBuffer(buffer); |
| 4334 buffer = next_buffer; | 4306 buffer = next_buffer; |
| 4335 } | 4307 } |
| 4336 *buffer_address = NULL; | 4308 *buffer_address = NULL; |
| 4337 } | 4309 } |
| 4338 | 4310 |
| 4339 | 4311 |
| 4340 } } // namespace v8::internal | 4312 } } // namespace v8::internal |
| OLD | NEW |