Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: src/heap/mark-compact.cc

Issue 980573002: Simplify and compact transitions storage (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 853 matching lines...) Expand 10 before | Expand all | Expand 10 after
2338 isolate(), DependentCode::kWeakCodeGroup); 2339 isolate(), DependentCode::kWeakCodeGroup);
2339 table->set(key_index, heap_->the_hole_value()); 2340 table->set(key_index, heap_->the_hole_value());
2340 table->set(value_index, heap_->the_hole_value()); 2341 table->set(value_index, heap_->the_hole_value());
2341 table->ElementRemoved(); 2342 table->ElementRemoved();
2342 } 2343 }
2343 } 2344 }
2344 } 2345 }
2345 2346
2346 2347
2347 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { 2348 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) {
2348 int number_of_transitions = map->NumberOfProtoTransitions(); 2349 FixedArray* prototype_transitions =
2349 FixedArray* prototype_transitions = map->GetPrototypeTransitions(); 2350 TransitionArray::GetPrototypeTransitions(map);
2351 int number_of_transitions =
2352 TransitionArray::NumberOfPrototypeTransitions(prototype_transitions);
2350 2353
2351 const int header = Map::kProtoTransitionHeaderSize; 2354 const int header = TransitionArray::kProtoTransitionHeaderSize;
2352 int new_number_of_transitions = 0; 2355 int new_number_of_transitions = 0;
2353 for (int i = 0; i < number_of_transitions; i++) { 2356 for (int i = 0; i < number_of_transitions; i++) {
2354 Object* cached_map = prototype_transitions->get(header + i); 2357 Object* cached_map = prototype_transitions->get(header + i);
2355 if (IsMarked(cached_map)) { 2358 if (IsMarked(cached_map)) {
2356 if (new_number_of_transitions != i) { 2359 if (new_number_of_transitions != i) {
2357 prototype_transitions->set(header + new_number_of_transitions, 2360 prototype_transitions->set(header + new_number_of_transitions,
2358 cached_map, SKIP_WRITE_BARRIER); 2361 cached_map, SKIP_WRITE_BARRIER);
2359 } 2362 }
2360 new_number_of_transitions++; 2363 new_number_of_transitions++;
2361 } 2364 }
2362 } 2365 }
2363 2366
2364 if (new_number_of_transitions != number_of_transitions) { 2367 if (new_number_of_transitions != number_of_transitions) {
2365 map->SetNumberOfProtoTransitions(new_number_of_transitions); 2368 TransitionArray::SetNumberOfPrototypeTransitions(prototype_transitions,
2369 new_number_of_transitions);
2366 } 2370 }
2367 2371
2368 // Fill slots that became free with undefined value. 2372 // Fill slots that became free with undefined value.
2369 for (int i = new_number_of_transitions; i < number_of_transitions; i++) { 2373 for (int i = new_number_of_transitions; i < number_of_transitions; i++) {
2370 prototype_transitions->set_undefined(header + i); 2374 prototype_transitions->set_undefined(header + i);
2371 } 2375 }
2372 } 2376 }
2373 2377
2374 2378
2375 void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, 2379 void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map,
2376 MarkBit map_mark) { 2380 MarkBit map_mark) {
2377 Object* potential_parent = map->GetBackPointer(); 2381 Object* potential_parent = map->GetBackPointer();
2378 if (!potential_parent->IsMap()) return; 2382 if (!potential_parent->IsMap()) return;
2379 Map* parent = Map::cast(potential_parent); 2383 Map* parent = Map::cast(potential_parent);
2380 2384
2381 // Follow back pointer, check whether we are dealing with a map transition 2385 // Follow back pointer, check whether we are dealing with a map transition
2382 // from a live map to a dead path and in case clear transitions of parent. 2386 // from a live map to a dead path and in case clear transitions of parent.
2383 bool current_is_alive = map_mark.Get(); 2387 bool current_is_alive = map_mark.Get();
2384 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); 2388 bool parent_is_alive = Marking::MarkBitFrom(parent).Get();
2385 if (!current_is_alive && parent_is_alive) { 2389 if (!current_is_alive && parent_is_alive) {
2386 ClearMapTransitions(parent); 2390 ClearMapTransitions(parent, map);
2387 } 2391 }
2388 } 2392 }
2389 2393
2390 2394
2391 // Clear a possible back pointer in case the transition leads to a dead map. 2395 // Clear a possible back pointer in case the transition leads to a dead map.
2392 // Return true in case a back pointer has been cleared and false otherwise. 2396 // Return true in case a back pointer has been cleared and false otherwise.
2393 bool MarkCompactCollector::ClearMapBackPointer(Map* target) { 2397 bool MarkCompactCollector::ClearMapBackPointer(Map* target) {
2394 if (Marking::MarkBitFrom(target).Get()) return false; 2398 if (Marking::MarkBitFrom(target).Get()) return false;
2395 target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER); 2399 target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER);
2396 return true; 2400 return true;
2397 } 2401 }
2398 2402
2399 2403
2400 void MarkCompactCollector::ClearMapTransitions(Map* map) { 2404 void MarkCompactCollector::ClearMapTransitions(Map* map, Map* dead_transition) {
2401 // If there are no transitions to be cleared, return. 2405 Object* transitions = map->raw_transitions();
2402 // TODO(verwaest) Should be an assert, otherwise back pointers are not 2406 int num_transitions = TransitionArray::NumberOfTransitions(transitions);
2403 // properly cleared.
2404 if (!map->HasTransitionArray()) return;
2405 2407
2406 TransitionArray* t = map->transitions(); 2408 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2409 DescriptorArray* descriptors = map->instance_descriptors();
2410
2411 // A previously existing simple transition (stored in a WeakCell) may have
2412 // been cleared. Take ownership of the descriptor array.
2413 if (num_transitions == 0 &&
2414 descriptors == dead_transition->instance_descriptors() &&
2415 number_of_own_descriptors > 0) {
2416 TrimDescriptorArray(map, descriptors, number_of_own_descriptors);
2417 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
2418 map->set_owns_descriptors(true);
2419 return;
2420 }
2407 2421
2408 int transition_index = 0; 2422 int transition_index = 0;
2409 2423
2410 DescriptorArray* descriptors = map->instance_descriptors();
2411 bool descriptors_owner_died = false; 2424 bool descriptors_owner_died = false;
2412 2425
2413 // Compact all live descriptors to the left. 2426 // Compact all live descriptors to the left.
2414 for (int i = 0; i < t->number_of_transitions(); ++i) { 2427 for (int i = 0; i < num_transitions; ++i) {
2415 Map* target = t->GetTarget(i); 2428 Map* target = TransitionArray::GetTarget(transitions, i);
2416 if (ClearMapBackPointer(target)) { 2429 if (ClearMapBackPointer(target)) {
2417 if (target->instance_descriptors() == descriptors) { 2430 if (target->instance_descriptors() == descriptors) {
2418 descriptors_owner_died = true; 2431 descriptors_owner_died = true;
2419 } 2432 }
2420 } else { 2433 } else {
2421 if (i != transition_index) { 2434 if (i != transition_index) {
2435 DCHECK(TransitionArray::IsFullTransitionArray(transitions));
2436 TransitionArray* t = TransitionArray::cast(transitions);
2422 Name* key = t->GetKey(i); 2437 Name* key = t->GetKey(i);
2423 t->SetKey(transition_index, key); 2438 t->SetKey(transition_index, key);
2424 Object** key_slot = t->GetKeySlot(transition_index); 2439 Object** key_slot = t->GetKeySlot(transition_index);
2425 RecordSlot(key_slot, key_slot, key); 2440 RecordSlot(key_slot, key_slot, key);
2426 // Target slots do not need to be recorded since maps are not compacted. 2441 // Target slots do not need to be recorded since maps are not compacted.
2427 t->SetTarget(transition_index, t->GetTarget(i)); 2442 t->SetTarget(transition_index, t->GetTarget(i));
2428 } 2443 }
2429 transition_index++; 2444 transition_index++;
2430 } 2445 }
2431 } 2446 }
2432 2447
2433 // If there are no transitions to be cleared, return. 2448 // If there are no transitions to be cleared, return.
2434 // TODO(verwaest) Should be an assert, otherwise back pointers are not 2449 // TODO(verwaest) Should be an assert, otherwise back pointers are not
2435 // properly cleared. 2450 // properly cleared.
2436 if (transition_index == t->number_of_transitions()) return; 2451 if (transition_index == num_transitions) return;
2437
2438 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2439 2452
2440 if (descriptors_owner_died) { 2453 if (descriptors_owner_died) {
2441 if (number_of_own_descriptors > 0) { 2454 if (number_of_own_descriptors > 0) {
2442 TrimDescriptorArray(map, descriptors, number_of_own_descriptors); 2455 TrimDescriptorArray(map, descriptors, number_of_own_descriptors);
2443 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); 2456 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors);
2444 map->set_owns_descriptors(true); 2457 map->set_owns_descriptors(true);
2445 } else { 2458 } else {
2446 DCHECK(descriptors == heap_->empty_descriptor_array()); 2459 DCHECK(descriptors == heap_->empty_descriptor_array());
2447 } 2460 }
2448 } 2461 }
2449 2462
2450 // Note that we never eliminate a transition array, though we might right-trim 2463 // Note that we never eliminate a transition array, though we might right-trim
2451 // such that number_of_transitions() == 0. If this assumption changes, 2464 // such that number_of_transitions() == 0. If this assumption changes,
2452 // TransitionArray::Insert() will need to deal with the case that a transition 2465 // TransitionArray::Insert() will need to deal with the case that a transition
2453 // array disappeared during GC. 2466 // array disappeared during GC.
2454 int trim = t->number_of_transitions_storage() - transition_index; 2467 int trim = TransitionArray::Capacity(transitions) - transition_index;
2455 if (trim > 0) { 2468 if (trim > 0) {
2456 heap_->RightTrimFixedArray<Heap::FROM_GC>( 2469 if (TransitionArray::IsFullTransitionArray(transitions)) {
2457 t, t->IsSimpleTransition() ? trim 2470 TransitionArray* t = TransitionArray::cast(transitions);
2458 : trim * TransitionArray::kTransitionSize); 2471 heap_->RightTrimFixedArray<Heap::FROM_GC>(
2459 t->SetNumberOfTransitions(transition_index); 2472 t, trim * TransitionArray::kTransitionSize);
2473 t->SetNumberOfTransitions(transition_index);
2474 // The map still has a full transition array.
2475 DCHECK(TransitionArray::IsFullTransitionArray(map->raw_transitions()));
2476 } else {
2477 map->set_raw_transitions(Smi::FromInt(0));
2478 }
2460 } 2479 }
2461 DCHECK(map->HasTransitionArray());
2462 } 2480 }
2463 2481
2464 2482
2465 void MarkCompactCollector::TrimDescriptorArray(Map* map, 2483 void MarkCompactCollector::TrimDescriptorArray(Map* map,
2466 DescriptorArray* descriptors, 2484 DescriptorArray* descriptors,
2467 int number_of_own_descriptors) { 2485 int number_of_own_descriptors) {
2468 int number_of_descriptors = descriptors->number_of_descriptors_storage(); 2486 int number_of_descriptors = descriptors->number_of_descriptors_storage();
2469 int to_trim = number_of_descriptors - number_of_own_descriptors; 2487 int to_trim = number_of_descriptors - number_of_own_descriptors;
2470 if (to_trim == 0) return; 2488 if (to_trim == 0) return;
2471 2489
(...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after
4163 4181
4164 { 4182 {
4165 GCTracer::Scope sweep_scope(heap()->tracer(), 4183 GCTracer::Scope sweep_scope(heap()->tracer(),
4166 GCTracer::Scope::MC_SWEEP_CELL); 4184 GCTracer::Scope::MC_SWEEP_CELL);
4167 SweepSpace(heap()->cell_space(), SEQUENTIAL_SWEEPING); 4185 SweepSpace(heap()->cell_space(), SEQUENTIAL_SWEEPING);
4168 SweepSpace(heap()->property_cell_space(), SEQUENTIAL_SWEEPING); 4186 SweepSpace(heap()->property_cell_space(), SEQUENTIAL_SWEEPING);
4169 } 4187 }
4170 4188
4171 EvacuateNewSpaceAndCandidates(); 4189 EvacuateNewSpaceAndCandidates();
4172 4190
4173 // ClearNonLiveTransitions depends on precise sweeping of map space to 4191 // ClearNonLiveReferences depends on precise sweeping of map space to
4174 // detect whether unmarked map became dead in this collection or in one 4192 // detect whether unmarked map became dead in this collection or in one
4175 // of the previous ones. 4193 // of the previous ones.
4176 { 4194 {
4177 GCTracer::Scope sweep_scope(heap()->tracer(), 4195 GCTracer::Scope sweep_scope(heap()->tracer(),
4178 GCTracer::Scope::MC_SWEEP_MAP); 4196 GCTracer::Scope::MC_SWEEP_MAP);
4179 SweepSpace(heap()->map_space(), SEQUENTIAL_SWEEPING); 4197 SweepSpace(heap()->map_space(), SEQUENTIAL_SWEEPING);
4180 } 4198 }
4181 4199
4182 // Deallocate unmarked objects and clear marked bits for marked objects. 4200 // Deallocate unmarked objects and clear marked bits for marked objects.
4183 heap_->lo_space()->FreeUnmarkedObjects(); 4201 heap_->lo_space()->FreeUnmarkedObjects();
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
4415 SlotsBuffer* buffer = *buffer_address; 4433 SlotsBuffer* buffer = *buffer_address;
4416 while (buffer != NULL) { 4434 while (buffer != NULL) {
4417 SlotsBuffer* next_buffer = buffer->next(); 4435 SlotsBuffer* next_buffer = buffer->next();
4418 DeallocateBuffer(buffer); 4436 DeallocateBuffer(buffer);
4419 buffer = next_buffer; 4437 buffer = next_buffer;
4420 } 4438 }
4421 *buffer_address = NULL; 4439 *buffer_address = NULL;
4422 } 4440 }
4423 } 4441 }
4424 } // namespace v8::internal 4442 } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698