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

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

Powered by Google App Engine
This is Rietveld 408576698