OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/compilation-cache.h" | 10 #include "src/compilation-cache.h" |
(...skipping 1452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1463 Heap* heap = map->GetHeap(); | 1463 Heap* heap = map->GetHeap(); |
1464 Map* map_obj = Map::cast(obj); | 1464 Map* map_obj = Map::cast(obj); |
1465 DCHECK(map->instance_type() == MAP_TYPE); | 1465 DCHECK(map->instance_type() == MAP_TYPE); |
1466 DescriptorArray* array = map_obj->instance_descriptors(); | 1466 DescriptorArray* array = map_obj->instance_descriptors(); |
1467 if (map_obj->owns_descriptors() && | 1467 if (map_obj->owns_descriptors() && |
1468 array != heap->empty_descriptor_array()) { | 1468 array != heap->empty_descriptor_array()) { |
1469 int fixed_array_size = array->Size(); | 1469 int fixed_array_size = array->Size(); |
1470 heap->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE, | 1470 heap->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE, |
1471 fixed_array_size); | 1471 fixed_array_size); |
1472 } | 1472 } |
1473 if (TransitionArray::IsFullTransitionArray(map_obj->raw_transitions())) { | 1473 if (map_obj->HasTransitionArray()) { |
1474 int fixed_array_size = | 1474 int fixed_array_size = map_obj->transitions()->Size(); |
1475 TransitionArray::cast(map_obj->raw_transitions())->Size(); | |
1476 heap->RecordFixedArraySubTypeStats(TRANSITION_ARRAY_SUB_TYPE, | 1475 heap->RecordFixedArraySubTypeStats(TRANSITION_ARRAY_SUB_TYPE, |
1477 fixed_array_size); | 1476 fixed_array_size); |
1478 } | 1477 } |
1479 if (map_obj->has_code_cache()) { | 1478 if (map_obj->has_code_cache()) { |
1480 CodeCache* cache = CodeCache::cast(map_obj->code_cache()); | 1479 CodeCache* cache = CodeCache::cast(map_obj->code_cache()); |
1481 heap->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, | 1480 heap->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, |
1482 cache->default_cache()->Size()); | 1481 cache->default_cache()->Size()); |
1483 if (!cache->normal_type_cache()->IsUndefined()) { | 1482 if (!cache->normal_type_cache()->IsUndefined()) { |
1484 heap->RecordFixedArraySubTypeStats( | 1483 heap->RecordFixedArraySubTypeStats( |
1485 MAP_CODE_CACHE_SUB_TYPE, | 1484 MAP_CODE_CACHE_SUB_TYPE, |
(...skipping 854 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2340 isolate(), DependentCode::kWeakCodeGroup); | 2339 isolate(), DependentCode::kWeakCodeGroup); |
2341 table->set(key_index, heap_->the_hole_value()); | 2340 table->set(key_index, heap_->the_hole_value()); |
2342 table->set(value_index, heap_->the_hole_value()); | 2341 table->set(value_index, heap_->the_hole_value()); |
2343 table->ElementRemoved(); | 2342 table->ElementRemoved(); |
2344 } | 2343 } |
2345 } | 2344 } |
2346 } | 2345 } |
2347 | 2346 |
2348 | 2347 |
2349 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { | 2348 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { |
2350 FixedArray* prototype_transitions = | 2349 int number_of_transitions = map->NumberOfProtoTransitions(); |
2351 TransitionArray::GetPrototypeTransitions(map); | 2350 FixedArray* prototype_transitions = map->GetPrototypeTransitions(); |
2352 int number_of_transitions = | |
2353 TransitionArray::NumberOfPrototypeTransitions(prototype_transitions); | |
2354 | 2351 |
2355 const int header = TransitionArray::kProtoTransitionHeaderSize; | 2352 const int header = Map::kProtoTransitionHeaderSize; |
2356 int new_number_of_transitions = 0; | 2353 int new_number_of_transitions = 0; |
2357 for (int i = 0; i < number_of_transitions; i++) { | 2354 for (int i = 0; i < number_of_transitions; i++) { |
2358 Object* cached_map = prototype_transitions->get(header + i); | 2355 Object* cached_map = prototype_transitions->get(header + i); |
2359 if (IsMarked(cached_map)) { | 2356 if (IsMarked(cached_map)) { |
2360 if (new_number_of_transitions != i) { | 2357 if (new_number_of_transitions != i) { |
2361 prototype_transitions->set(header + new_number_of_transitions, | 2358 prototype_transitions->set(header + new_number_of_transitions, |
2362 cached_map, SKIP_WRITE_BARRIER); | 2359 cached_map, SKIP_WRITE_BARRIER); |
2363 } | 2360 } |
2364 new_number_of_transitions++; | 2361 new_number_of_transitions++; |
2365 } | 2362 } |
2366 } | 2363 } |
2367 | 2364 |
2368 if (new_number_of_transitions != number_of_transitions) { | 2365 if (new_number_of_transitions != number_of_transitions) { |
2369 TransitionArray::SetNumberOfPrototypeTransitions(prototype_transitions, | 2366 map->SetNumberOfProtoTransitions(new_number_of_transitions); |
2370 new_number_of_transitions); | |
2371 } | 2367 } |
2372 | 2368 |
2373 // Fill slots that became free with undefined value. | 2369 // Fill slots that became free with undefined value. |
2374 for (int i = new_number_of_transitions; i < number_of_transitions; i++) { | 2370 for (int i = new_number_of_transitions; i < number_of_transitions; i++) { |
2375 prototype_transitions->set_undefined(header + i); | 2371 prototype_transitions->set_undefined(header + i); |
2376 } | 2372 } |
2377 } | 2373 } |
2378 | 2374 |
2379 | 2375 |
2380 void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, | 2376 void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, |
2381 MarkBit map_mark) { | 2377 MarkBit map_mark) { |
2382 Object* potential_parent = map->GetBackPointer(); | 2378 Object* potential_parent = map->GetBackPointer(); |
2383 if (!potential_parent->IsMap()) return; | 2379 if (!potential_parent->IsMap()) return; |
2384 Map* parent = Map::cast(potential_parent); | 2380 Map* parent = Map::cast(potential_parent); |
2385 | 2381 |
2386 // Follow back pointer, check whether we are dealing with a map transition | 2382 // Follow back pointer, check whether we are dealing with a map transition |
2387 // from a live map to a dead path and in case clear transitions of parent. | 2383 // from a live map to a dead path and in case clear transitions of parent. |
2388 bool current_is_alive = map_mark.Get(); | 2384 bool current_is_alive = map_mark.Get(); |
2389 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); | 2385 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); |
2390 if (!current_is_alive && parent_is_alive) { | 2386 if (!current_is_alive && parent_is_alive) { |
2391 ClearMapTransitions(parent, map); | 2387 ClearMapTransitions(parent); |
2392 } | 2388 } |
2393 } | 2389 } |
2394 | 2390 |
2395 | 2391 |
2396 // Clear a possible back pointer in case the transition leads to a dead map. | 2392 // Clear a possible back pointer in case the transition leads to a dead map. |
2397 // Return true in case a back pointer has been cleared and false otherwise. | 2393 // Return true in case a back pointer has been cleared and false otherwise. |
2398 bool MarkCompactCollector::ClearMapBackPointer(Map* target) { | 2394 bool MarkCompactCollector::ClearMapBackPointer(Map* target) { |
2399 if (Marking::MarkBitFrom(target).Get()) return false; | 2395 if (Marking::MarkBitFrom(target).Get()) return false; |
2400 target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER); | 2396 target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER); |
2401 return true; | 2397 return true; |
2402 } | 2398 } |
2403 | 2399 |
2404 | 2400 |
2405 void MarkCompactCollector::ClearMapTransitions(Map* map, Map* dead_transition) { | 2401 void MarkCompactCollector::ClearMapTransitions(Map* map) { |
2406 Object* transitions = map->raw_transitions(); | 2402 // If there are no transitions to be cleared, return. |
2407 int num_transitions = TransitionArray::NumberOfTransitions(transitions); | 2403 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
| 2404 // properly cleared. |
| 2405 if (!map->HasTransitionArray()) return; |
2408 | 2406 |
2409 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 2407 TransitionArray* t = map->transitions(); |
2410 DescriptorArray* descriptors = map->instance_descriptors(); | |
2411 | |
2412 // A previously existing simple transition (stored in a WeakCell) may have | |
2413 // been cleared. Clear the useless cell pointer, and take ownership | |
2414 // of the descriptor array. | |
2415 if (transitions->IsWeakCell() && WeakCell::cast(transitions)->cleared()) { | |
2416 map->set_raw_transitions(Smi::FromInt(0)); | |
2417 } | |
2418 if (num_transitions == 0 && | |
2419 descriptors == dead_transition->instance_descriptors() && | |
2420 number_of_own_descriptors > 0) { | |
2421 TrimDescriptorArray(map, descriptors, number_of_own_descriptors); | |
2422 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); | |
2423 map->set_owns_descriptors(true); | |
2424 return; | |
2425 } | |
2426 | 2408 |
2427 int transition_index = 0; | 2409 int transition_index = 0; |
2428 | 2410 |
| 2411 DescriptorArray* descriptors = map->instance_descriptors(); |
2429 bool descriptors_owner_died = false; | 2412 bool descriptors_owner_died = false; |
2430 | 2413 |
2431 // Compact all live descriptors to the left. | 2414 // Compact all live descriptors to the left. |
2432 for (int i = 0; i < num_transitions; ++i) { | 2415 for (int i = 0; i < t->number_of_transitions(); ++i) { |
2433 Map* target = TransitionArray::GetTarget(transitions, i); | 2416 Map* target = t->GetTarget(i); |
2434 if (ClearMapBackPointer(target)) { | 2417 if (ClearMapBackPointer(target)) { |
2435 if (target->instance_descriptors() == descriptors) { | 2418 if (target->instance_descriptors() == descriptors) { |
2436 descriptors_owner_died = true; | 2419 descriptors_owner_died = true; |
2437 } | 2420 } |
2438 } else { | 2421 } else { |
2439 if (i != transition_index) { | 2422 if (i != transition_index) { |
2440 DCHECK(TransitionArray::IsFullTransitionArray(transitions)); | |
2441 TransitionArray* t = TransitionArray::cast(transitions); | |
2442 Name* key = t->GetKey(i); | 2423 Name* key = t->GetKey(i); |
2443 t->SetKey(transition_index, key); | 2424 t->SetKey(transition_index, key); |
2444 Object** key_slot = t->GetKeySlot(transition_index); | 2425 Object** key_slot = t->GetKeySlot(transition_index); |
2445 RecordSlot(key_slot, key_slot, key); | 2426 RecordSlot(key_slot, key_slot, key); |
2446 // Target slots do not need to be recorded since maps are not compacted. | 2427 // Target slots do not need to be recorded since maps are not compacted. |
2447 t->SetTarget(transition_index, t->GetTarget(i)); | 2428 t->SetTarget(transition_index, t->GetTarget(i)); |
2448 } | 2429 } |
2449 transition_index++; | 2430 transition_index++; |
2450 } | 2431 } |
2451 } | 2432 } |
2452 | 2433 |
2453 // If there are no transitions to be cleared, return. | 2434 // If there are no transitions to be cleared, return. |
2454 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 2435 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
2455 // properly cleared. | 2436 // properly cleared. |
2456 if (transition_index == num_transitions) return; | 2437 if (transition_index == t->number_of_transitions()) return; |
| 2438 |
| 2439 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
2457 | 2440 |
2458 if (descriptors_owner_died) { | 2441 if (descriptors_owner_died) { |
2459 if (number_of_own_descriptors > 0) { | 2442 if (number_of_own_descriptors > 0) { |
2460 TrimDescriptorArray(map, descriptors, number_of_own_descriptors); | 2443 TrimDescriptorArray(map, descriptors, number_of_own_descriptors); |
2461 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); | 2444 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); |
2462 map->set_owns_descriptors(true); | 2445 map->set_owns_descriptors(true); |
2463 } else { | 2446 } else { |
2464 DCHECK(descriptors == heap_->empty_descriptor_array()); | 2447 DCHECK(descriptors == heap_->empty_descriptor_array()); |
2465 } | 2448 } |
2466 } | 2449 } |
2467 | 2450 |
2468 // Note that we never eliminate a transition array, though we might right-trim | 2451 // Note that we never eliminate a transition array, though we might right-trim |
2469 // such that number_of_transitions() == 0. If this assumption changes, | 2452 // such that number_of_transitions() == 0. If this assumption changes, |
2470 // TransitionArray::Insert() will need to deal with the case that a transition | 2453 // TransitionArray::Insert() will need to deal with the case that a transition |
2471 // array disappeared during GC. | 2454 // array disappeared during GC. |
2472 int trim = TransitionArray::Capacity(transitions) - transition_index; | 2455 int trim = t->number_of_transitions_storage() - transition_index; |
2473 if (trim > 0) { | 2456 if (trim > 0) { |
2474 // Non-full-TransitionArray cases can never reach this point. | |
2475 DCHECK(TransitionArray::IsFullTransitionArray(transitions)); | |
2476 TransitionArray* t = TransitionArray::cast(transitions); | |
2477 heap_->RightTrimFixedArray<Heap::FROM_GC>( | 2457 heap_->RightTrimFixedArray<Heap::FROM_GC>( |
2478 t, trim * TransitionArray::kTransitionSize); | 2458 t, t->IsSimpleTransition() ? trim |
| 2459 : trim * TransitionArray::kTransitionSize); |
2479 t->SetNumberOfTransitions(transition_index); | 2460 t->SetNumberOfTransitions(transition_index); |
2480 // The map still has a full transition array. | |
2481 DCHECK(TransitionArray::IsFullTransitionArray(map->raw_transitions())); | |
2482 } | 2461 } |
| 2462 DCHECK(map->HasTransitionArray()); |
2483 } | 2463 } |
2484 | 2464 |
2485 | 2465 |
2486 void MarkCompactCollector::TrimDescriptorArray(Map* map, | 2466 void MarkCompactCollector::TrimDescriptorArray(Map* map, |
2487 DescriptorArray* descriptors, | 2467 DescriptorArray* descriptors, |
2488 int number_of_own_descriptors) { | 2468 int number_of_own_descriptors) { |
2489 int number_of_descriptors = descriptors->number_of_descriptors_storage(); | 2469 int number_of_descriptors = descriptors->number_of_descriptors_storage(); |
2490 int to_trim = number_of_descriptors - number_of_own_descriptors; | 2470 int to_trim = number_of_descriptors - number_of_own_descriptors; |
2491 if (to_trim == 0) return; | 2471 if (to_trim == 0) return; |
2492 | 2472 |
(...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4184 | 4164 |
4185 { | 4165 { |
4186 GCTracer::Scope sweep_scope(heap()->tracer(), | 4166 GCTracer::Scope sweep_scope(heap()->tracer(), |
4187 GCTracer::Scope::MC_SWEEP_CELL); | 4167 GCTracer::Scope::MC_SWEEP_CELL); |
4188 SweepSpace(heap()->cell_space(), SEQUENTIAL_SWEEPING); | 4168 SweepSpace(heap()->cell_space(), SEQUENTIAL_SWEEPING); |
4189 SweepSpace(heap()->property_cell_space(), SEQUENTIAL_SWEEPING); | 4169 SweepSpace(heap()->property_cell_space(), SEQUENTIAL_SWEEPING); |
4190 } | 4170 } |
4191 | 4171 |
4192 EvacuateNewSpaceAndCandidates(); | 4172 EvacuateNewSpaceAndCandidates(); |
4193 | 4173 |
4194 // ClearNonLiveReferences depends on precise sweeping of map space to | 4174 // ClearNonLiveTransitions depends on precise sweeping of map space to |
4195 // detect whether unmarked map became dead in this collection or in one | 4175 // detect whether unmarked map became dead in this collection or in one |
4196 // of the previous ones. | 4176 // of the previous ones. |
4197 { | 4177 { |
4198 GCTracer::Scope sweep_scope(heap()->tracer(), | 4178 GCTracer::Scope sweep_scope(heap()->tracer(), |
4199 GCTracer::Scope::MC_SWEEP_MAP); | 4179 GCTracer::Scope::MC_SWEEP_MAP); |
4200 SweepSpace(heap()->map_space(), SEQUENTIAL_SWEEPING); | 4180 SweepSpace(heap()->map_space(), SEQUENTIAL_SWEEPING); |
4201 } | 4181 } |
4202 | 4182 |
4203 // Deallocate unmarked objects and clear marked bits for marked objects. | 4183 // Deallocate unmarked objects and clear marked bits for marked objects. |
4204 heap_->lo_space()->FreeUnmarkedObjects(); | 4184 heap_->lo_space()->FreeUnmarkedObjects(); |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4436 SlotsBuffer* buffer = *buffer_address; | 4416 SlotsBuffer* buffer = *buffer_address; |
4437 while (buffer != NULL) { | 4417 while (buffer != NULL) { |
4438 SlotsBuffer* next_buffer = buffer->next(); | 4418 SlotsBuffer* next_buffer = buffer->next(); |
4439 DeallocateBuffer(buffer); | 4419 DeallocateBuffer(buffer); |
4440 buffer = next_buffer; | 4420 buffer = next_buffer; |
4441 } | 4421 } |
4442 *buffer_address = NULL; | 4422 *buffer_address = NULL; |
4443 } | 4423 } |
4444 } | 4424 } |
4445 } // namespace v8::internal | 4425 } // namespace v8::internal |
OLD | NEW |