| 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 (map_obj->HasTransitionArray()) { | 1473 if (TransitionArray::IsFullTransitionArray(map_obj->raw_transitions())) { |
| 1474 int fixed_array_size = map_obj->transitions()->Size(); | 1474 int fixed_array_size = |
| 1475 TransitionArray::cast(map_obj->raw_transitions())->Size(); |
| 1475 heap->RecordFixedArraySubTypeStats(TRANSITION_ARRAY_SUB_TYPE, | 1476 heap->RecordFixedArraySubTypeStats(TRANSITION_ARRAY_SUB_TYPE, |
| 1476 fixed_array_size); | 1477 fixed_array_size); |
| 1477 } | 1478 } |
| 1478 if (map_obj->has_code_cache()) { | 1479 if (map_obj->has_code_cache()) { |
| 1479 CodeCache* cache = CodeCache::cast(map_obj->code_cache()); | 1480 CodeCache* cache = CodeCache::cast(map_obj->code_cache()); |
| 1480 heap->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, | 1481 heap->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, |
| 1481 cache->default_cache()->Size()); | 1482 cache->default_cache()->Size()); |
| 1482 if (!cache->normal_type_cache()->IsUndefined()) { | 1483 if (!cache->normal_type_cache()->IsUndefined()) { |
| 1483 heap->RecordFixedArraySubTypeStats( | 1484 heap->RecordFixedArraySubTypeStats( |
| 1484 MAP_CODE_CACHE_SUB_TYPE, | 1485 MAP_CODE_CACHE_SUB_TYPE, |
| (...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2399 isolate(), DependentCode::kWeakCodeGroup); | 2400 isolate(), DependentCode::kWeakCodeGroup); |
| 2400 table->set(key_index, heap_->the_hole_value()); | 2401 table->set(key_index, heap_->the_hole_value()); |
| 2401 table->set(value_index, heap_->the_hole_value()); | 2402 table->set(value_index, heap_->the_hole_value()); |
| 2402 table->ElementRemoved(); | 2403 table->ElementRemoved(); |
| 2403 } | 2404 } |
| 2404 } | 2405 } |
| 2405 } | 2406 } |
| 2406 | 2407 |
| 2407 | 2408 |
| 2408 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { | 2409 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { |
| 2409 int number_of_transitions = map->NumberOfProtoTransitions(); | 2410 FixedArray* prototype_transitions = |
| 2410 FixedArray* prototype_transitions = map->GetPrototypeTransitions(); | 2411 TransitionArray::GetPrototypeTransitions(map); |
| 2412 int number_of_transitions = |
| 2413 TransitionArray::NumberOfPrototypeTransitions(prototype_transitions); |
| 2411 | 2414 |
| 2412 const int header = Map::kProtoTransitionHeaderSize; | 2415 const int header = TransitionArray::kProtoTransitionHeaderSize; |
| 2413 int new_number_of_transitions = 0; | 2416 int new_number_of_transitions = 0; |
| 2414 for (int i = 0; i < number_of_transitions; i++) { | 2417 for (int i = 0; i < number_of_transitions; i++) { |
| 2415 Object* cached_map = prototype_transitions->get(header + i); | 2418 Object* cached_map = prototype_transitions->get(header + i); |
| 2416 if (IsMarked(cached_map)) { | 2419 if (IsMarked(cached_map)) { |
| 2417 if (new_number_of_transitions != i) { | 2420 if (new_number_of_transitions != i) { |
| 2418 prototype_transitions->set(header + new_number_of_transitions, | 2421 prototype_transitions->set(header + new_number_of_transitions, |
| 2419 cached_map, SKIP_WRITE_BARRIER); | 2422 cached_map, SKIP_WRITE_BARRIER); |
| 2420 } | 2423 } |
| 2421 new_number_of_transitions++; | 2424 new_number_of_transitions++; |
| 2422 } | 2425 } |
| 2423 } | 2426 } |
| 2424 | 2427 |
| 2425 if (new_number_of_transitions != number_of_transitions) { | 2428 if (new_number_of_transitions != number_of_transitions) { |
| 2426 map->SetNumberOfProtoTransitions(new_number_of_transitions); | 2429 TransitionArray::SetNumberOfPrototypeTransitions(prototype_transitions, |
| 2430 new_number_of_transitions); |
| 2427 } | 2431 } |
| 2428 | 2432 |
| 2429 // Fill slots that became free with undefined value. | 2433 // Fill slots that became free with undefined value. |
| 2430 for (int i = new_number_of_transitions; i < number_of_transitions; i++) { | 2434 for (int i = new_number_of_transitions; i < number_of_transitions; i++) { |
| 2431 prototype_transitions->set_undefined(header + i); | 2435 prototype_transitions->set_undefined(header + i); |
| 2432 } | 2436 } |
| 2433 } | 2437 } |
| 2434 | 2438 |
| 2435 | 2439 |
| 2436 void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, | 2440 void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, |
| 2437 MarkBit map_mark) { | 2441 MarkBit map_mark) { |
| 2438 Object* potential_parent = map->GetBackPointer(); | 2442 Object* potential_parent = map->GetBackPointer(); |
| 2439 if (!potential_parent->IsMap()) return; | 2443 if (!potential_parent->IsMap()) return; |
| 2440 Map* parent = Map::cast(potential_parent); | 2444 Map* parent = Map::cast(potential_parent); |
| 2441 | 2445 |
| 2442 // Follow back pointer, check whether we are dealing with a map transition | 2446 // Follow back pointer, check whether we are dealing with a map transition |
| 2443 // from a live map to a dead path and in case clear transitions of parent. | 2447 // from a live map to a dead path and in case clear transitions of parent. |
| 2444 bool current_is_alive = map_mark.Get(); | 2448 bool current_is_alive = map_mark.Get(); |
| 2445 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); | 2449 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); |
| 2446 if (!current_is_alive && parent_is_alive) { | 2450 if (!current_is_alive && parent_is_alive) { |
| 2447 ClearMapTransitions(parent); | 2451 ClearMapTransitions(parent, map); |
| 2448 } | 2452 } |
| 2449 } | 2453 } |
| 2450 | 2454 |
| 2451 | 2455 |
| 2452 // Clear a possible back pointer in case the transition leads to a dead map. | 2456 // Clear a possible back pointer in case the transition leads to a dead map. |
| 2453 // Return true in case a back pointer has been cleared and false otherwise. | 2457 // Return true in case a back pointer has been cleared and false otherwise. |
| 2454 bool MarkCompactCollector::ClearMapBackPointer(Map* target) { | 2458 bool MarkCompactCollector::ClearMapBackPointer(Map* target) { |
| 2455 if (Marking::MarkBitFrom(target).Get()) return false; | 2459 if (Marking::MarkBitFrom(target).Get()) return false; |
| 2456 target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER); | 2460 target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER); |
| 2457 return true; | 2461 return true; |
| 2458 } | 2462 } |
| 2459 | 2463 |
| 2460 | 2464 |
| 2461 void MarkCompactCollector::ClearMapTransitions(Map* map) { | 2465 void MarkCompactCollector::ClearMapTransitions(Map* map, Map* dead_transition) { |
| 2462 // If there are no transitions to be cleared, return. | 2466 Object* transitions = map->raw_transitions(); |
| 2463 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 2467 int num_transitions = TransitionArray::NumberOfTransitions(transitions); |
| 2464 // properly cleared. | |
| 2465 if (!map->HasTransitionArray()) return; | |
| 2466 | 2468 |
| 2467 TransitionArray* t = map->transitions(); | 2469 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| 2470 DescriptorArray* descriptors = map->instance_descriptors(); |
| 2471 |
| 2472 // A previously existing simple transition (stored in a WeakCell) may have |
| 2473 // been cleared. Clear the useless cell pointer, and take ownership |
| 2474 // of the descriptor array. |
| 2475 if (transitions->IsWeakCell() && WeakCell::cast(transitions)->cleared()) { |
| 2476 map->set_raw_transitions(Smi::FromInt(0)); |
| 2477 } |
| 2478 if (num_transitions == 0 && |
| 2479 descriptors == dead_transition->instance_descriptors() && |
| 2480 number_of_own_descriptors > 0) { |
| 2481 TrimDescriptorArray(map, descriptors, number_of_own_descriptors); |
| 2482 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); |
| 2483 map->set_owns_descriptors(true); |
| 2484 return; |
| 2485 } |
| 2468 | 2486 |
| 2469 int transition_index = 0; | 2487 int transition_index = 0; |
| 2470 | 2488 |
| 2471 DescriptorArray* descriptors = map->instance_descriptors(); | |
| 2472 bool descriptors_owner_died = false; | 2489 bool descriptors_owner_died = false; |
| 2473 | 2490 |
| 2474 // Compact all live descriptors to the left. | 2491 // Compact all live descriptors to the left. |
| 2475 for (int i = 0; i < t->number_of_transitions(); ++i) { | 2492 for (int i = 0; i < num_transitions; ++i) { |
| 2476 Map* target = t->GetTarget(i); | 2493 Map* target = TransitionArray::GetTarget(transitions, i); |
| 2477 if (ClearMapBackPointer(target)) { | 2494 if (ClearMapBackPointer(target)) { |
| 2478 if (target->instance_descriptors() == descriptors) { | 2495 if (target->instance_descriptors() == descriptors) { |
| 2479 descriptors_owner_died = true; | 2496 descriptors_owner_died = true; |
| 2480 } | 2497 } |
| 2481 } else { | 2498 } else { |
| 2482 if (i != transition_index) { | 2499 if (i != transition_index) { |
| 2500 DCHECK(TransitionArray::IsFullTransitionArray(transitions)); |
| 2501 TransitionArray* t = TransitionArray::cast(transitions); |
| 2483 Name* key = t->GetKey(i); | 2502 Name* key = t->GetKey(i); |
| 2484 t->SetKey(transition_index, key); | 2503 t->SetKey(transition_index, key); |
| 2485 Object** key_slot = t->GetKeySlot(transition_index); | 2504 Object** key_slot = t->GetKeySlot(transition_index); |
| 2486 RecordSlot(key_slot, key_slot, key); | 2505 RecordSlot(key_slot, key_slot, key); |
| 2487 // Target slots do not need to be recorded since maps are not compacted. | 2506 // Target slots do not need to be recorded since maps are not compacted. |
| 2488 t->SetTarget(transition_index, t->GetTarget(i)); | 2507 t->SetTarget(transition_index, t->GetTarget(i)); |
| 2489 } | 2508 } |
| 2490 transition_index++; | 2509 transition_index++; |
| 2491 } | 2510 } |
| 2492 } | 2511 } |
| 2493 | 2512 |
| 2494 // If there are no transitions to be cleared, return. | 2513 // If there are no transitions to be cleared, return. |
| 2495 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 2514 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
| 2496 // properly cleared. | 2515 // properly cleared. |
| 2497 if (transition_index == t->number_of_transitions()) return; | 2516 if (transition_index == num_transitions) return; |
| 2498 | |
| 2499 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | |
| 2500 | 2517 |
| 2501 if (descriptors_owner_died) { | 2518 if (descriptors_owner_died) { |
| 2502 if (number_of_own_descriptors > 0) { | 2519 if (number_of_own_descriptors > 0) { |
| 2503 TrimDescriptorArray(map, descriptors, number_of_own_descriptors); | 2520 TrimDescriptorArray(map, descriptors, number_of_own_descriptors); |
| 2504 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); | 2521 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); |
| 2505 map->set_owns_descriptors(true); | 2522 map->set_owns_descriptors(true); |
| 2506 } else { | 2523 } else { |
| 2507 DCHECK(descriptors == heap_->empty_descriptor_array()); | 2524 DCHECK(descriptors == heap_->empty_descriptor_array()); |
| 2508 } | 2525 } |
| 2509 } | 2526 } |
| 2510 | 2527 |
| 2511 // Note that we never eliminate a transition array, though we might right-trim | 2528 // Note that we never eliminate a transition array, though we might right-trim |
| 2512 // such that number_of_transitions() == 0. If this assumption changes, | 2529 // such that number_of_transitions() == 0. If this assumption changes, |
| 2513 // TransitionArray::Insert() will need to deal with the case that a transition | 2530 // TransitionArray::Insert() will need to deal with the case that a transition |
| 2514 // array disappeared during GC. | 2531 // array disappeared during GC. |
| 2515 int trim = t->number_of_transitions_storage() - transition_index; | 2532 int trim = TransitionArray::Capacity(transitions) - transition_index; |
| 2516 if (trim > 0) { | 2533 if (trim > 0) { |
| 2534 // Non-full-TransitionArray cases can never reach this point. |
| 2535 DCHECK(TransitionArray::IsFullTransitionArray(transitions)); |
| 2536 TransitionArray* t = TransitionArray::cast(transitions); |
| 2517 heap_->RightTrimFixedArray<Heap::FROM_GC>( | 2537 heap_->RightTrimFixedArray<Heap::FROM_GC>( |
| 2518 t, t->IsSimpleTransition() ? trim | 2538 t, trim * TransitionArray::kTransitionSize); |
| 2519 : trim * TransitionArray::kTransitionSize); | |
| 2520 t->SetNumberOfTransitions(transition_index); | 2539 t->SetNumberOfTransitions(transition_index); |
| 2540 // The map still has a full transition array. |
| 2541 DCHECK(TransitionArray::IsFullTransitionArray(map->raw_transitions())); |
| 2521 } | 2542 } |
| 2522 DCHECK(map->HasTransitionArray()); | |
| 2523 } | 2543 } |
| 2524 | 2544 |
| 2525 | 2545 |
| 2526 void MarkCompactCollector::TrimDescriptorArray(Map* map, | 2546 void MarkCompactCollector::TrimDescriptorArray(Map* map, |
| 2527 DescriptorArray* descriptors, | 2547 DescriptorArray* descriptors, |
| 2528 int number_of_own_descriptors) { | 2548 int number_of_own_descriptors) { |
| 2529 int number_of_descriptors = descriptors->number_of_descriptors_storage(); | 2549 int number_of_descriptors = descriptors->number_of_descriptors_storage(); |
| 2530 int to_trim = number_of_descriptors - number_of_own_descriptors; | 2550 int to_trim = number_of_descriptors - number_of_own_descriptors; |
| 2531 if (to_trim == 0) return; | 2551 if (to_trim == 0) return; |
| 2532 | 2552 |
| (...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4224 | 4244 |
| 4225 { | 4245 { |
| 4226 GCTracer::Scope sweep_scope(heap()->tracer(), | 4246 GCTracer::Scope sweep_scope(heap()->tracer(), |
| 4227 GCTracer::Scope::MC_SWEEP_CELL); | 4247 GCTracer::Scope::MC_SWEEP_CELL); |
| 4228 SweepSpace(heap()->cell_space(), SEQUENTIAL_SWEEPING); | 4248 SweepSpace(heap()->cell_space(), SEQUENTIAL_SWEEPING); |
| 4229 SweepSpace(heap()->property_cell_space(), SEQUENTIAL_SWEEPING); | 4249 SweepSpace(heap()->property_cell_space(), SEQUENTIAL_SWEEPING); |
| 4230 } | 4250 } |
| 4231 | 4251 |
| 4232 EvacuateNewSpaceAndCandidates(); | 4252 EvacuateNewSpaceAndCandidates(); |
| 4233 | 4253 |
| 4234 // ClearNonLiveTransitions depends on precise sweeping of map space to | 4254 // ClearNonLiveReferences depends on precise sweeping of map space to |
| 4235 // detect whether unmarked map became dead in this collection or in one | 4255 // detect whether unmarked map became dead in this collection or in one |
| 4236 // of the previous ones. | 4256 // of the previous ones. |
| 4237 { | 4257 { |
| 4238 GCTracer::Scope sweep_scope(heap()->tracer(), | 4258 GCTracer::Scope sweep_scope(heap()->tracer(), |
| 4239 GCTracer::Scope::MC_SWEEP_MAP); | 4259 GCTracer::Scope::MC_SWEEP_MAP); |
| 4240 SweepSpace(heap()->map_space(), SEQUENTIAL_SWEEPING); | 4260 SweepSpace(heap()->map_space(), SEQUENTIAL_SWEEPING); |
| 4241 } | 4261 } |
| 4242 | 4262 |
| 4243 // Deallocate unmarked objects and clear marked bits for marked objects. | 4263 // Deallocate unmarked objects and clear marked bits for marked objects. |
| 4244 heap_->lo_space()->FreeUnmarkedObjects(); | 4264 heap_->lo_space()->FreeUnmarkedObjects(); |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4476 SlotsBuffer* buffer = *buffer_address; | 4496 SlotsBuffer* buffer = *buffer_address; |
| 4477 while (buffer != NULL) { | 4497 while (buffer != NULL) { |
| 4478 SlotsBuffer* next_buffer = buffer->next(); | 4498 SlotsBuffer* next_buffer = buffer->next(); |
| 4479 DeallocateBuffer(buffer); | 4499 DeallocateBuffer(buffer); |
| 4480 buffer = next_buffer; | 4500 buffer = next_buffer; |
| 4481 } | 4501 } |
| 4482 *buffer_address = NULL; | 4502 *buffer_address = NULL; |
| 4483 } | 4503 } |
| 4484 } | 4504 } |
| 4485 } // namespace v8::internal | 4505 } // namespace v8::internal |
| OLD | NEW |