| 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 | 
|---|