Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 | 52 |
| 53 // ------------------------------------------------------------------------- | 53 // ------------------------------------------------------------------------- |
| 54 // MarkCompactCollector | 54 // MarkCompactCollector |
| 55 | 55 |
| 56 MarkCompactCollector::MarkCompactCollector() : // NOLINT | 56 MarkCompactCollector::MarkCompactCollector() : // NOLINT |
| 57 #ifdef DEBUG | 57 #ifdef DEBUG |
| 58 state_(IDLE), | 58 state_(IDLE), |
| 59 #endif | 59 #endif |
| 60 sweep_precisely_(false), | 60 sweep_precisely_(false), |
| 61 compacting_(false), | 61 compacting_(false), |
| 62 collect_maps_(FLAG_collect_maps), | |
| 62 tracer_(NULL), | 63 tracer_(NULL), |
| 63 migration_slots_buffer_(NULL), | 64 migration_slots_buffer_(NULL), |
| 64 #ifdef DEBUG | 65 #ifdef DEBUG |
| 65 live_young_objects_size_(0), | 66 live_young_objects_size_(0), |
| 66 live_old_pointer_objects_size_(0), | 67 live_old_pointer_objects_size_(0), |
| 67 live_old_data_objects_size_(0), | 68 live_old_data_objects_size_(0), |
| 68 live_code_objects_size_(0), | 69 live_code_objects_size_(0), |
| 69 live_map_objects_size_(0), | 70 live_map_objects_size_(0), |
| 70 live_cell_objects_size_(0), | 71 live_cell_objects_size_(0), |
| 71 live_lo_objects_size_(0), | 72 live_lo_objects_size_(0), |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 | 248 |
| 248 | 249 |
| 249 void MarkCompactCollector::CollectGarbage() { | 250 void MarkCompactCollector::CollectGarbage() { |
| 250 // Make sure that Prepare() has been called. The individual steps below will | 251 // Make sure that Prepare() has been called. The individual steps below will |
| 251 // update the state as they proceed. | 252 // update the state as they proceed. |
| 252 ASSERT(state_ == PREPARE_GC); | 253 ASSERT(state_ == PREPARE_GC); |
| 253 | 254 |
| 254 MarkLiveObjects(); | 255 MarkLiveObjects(); |
| 255 ASSERT(heap_->incremental_marking()->IsStopped()); | 256 ASSERT(heap_->incremental_marking()->IsStopped()); |
| 256 | 257 |
| 257 if (FLAG_collect_maps) ClearNonLiveTransitions(); | 258 if (collect_maps_) ClearNonLiveTransitions(); |
| 258 | 259 |
| 259 #ifdef DEBUG | 260 #ifdef DEBUG |
| 260 if (FLAG_verify_heap) { | 261 if (FLAG_verify_heap) { |
| 261 VerifyMarking(heap_); | 262 VerifyMarking(heap_); |
| 262 } | 263 } |
| 263 #endif | 264 #endif |
| 264 | 265 |
| 265 SweepSpaces(); | 266 SweepSpaces(); |
| 266 | 267 |
| 268 if (!collect_maps_) ReattachInitialMaps(); | |
| 269 | |
| 267 heap_->isolate()->pc_to_code_cache()->Flush(); | 270 heap_->isolate()->pc_to_code_cache()->Flush(); |
| 268 | 271 |
| 269 Finish(); | 272 Finish(); |
| 270 | 273 |
| 271 tracer_ = NULL; | 274 tracer_ = NULL; |
| 272 } | 275 } |
| 273 | 276 |
| 274 | 277 |
| 275 #ifdef DEBUG | 278 #ifdef DEBUG |
| 276 static void VerifyMarkbitsAreClean(PagedSpace* space) { | 279 static void VerifyMarkbitsAreClean(PagedSpace* space) { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 | 398 |
| 396 | 399 |
| 397 void MarkCompactCollector::Prepare(GCTracer* tracer) { | 400 void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| 398 // TODO(gc) re-enable code flushing. | 401 // TODO(gc) re-enable code flushing. |
| 399 FLAG_flush_code = false; | 402 FLAG_flush_code = false; |
| 400 FLAG_always_compact = false; | 403 FLAG_always_compact = false; |
| 401 | 404 |
| 402 // Disable collection of maps if incremental marking is enabled. | 405 // Disable collection of maps if incremental marking is enabled. |
| 403 // TODO(gc) improve maps collection algorithm to work with incremental | 406 // TODO(gc) improve maps collection algorithm to work with incremental |
| 404 // marking. | 407 // marking. |
| 405 if (FLAG_incremental_marking) FLAG_collect_maps = false; | 408 // TODO(gc) consider oscillating collect_maps_ on and off when possible. |
| 409 // This will allow map transition tree to die from both root and leaves. | |
|
Lasse Reichstein
2011/07/15 07:00:14
"a map transition tree" or "map transition trees"?
| |
| 410 collect_maps_ = FLAG_collect_maps && | |
| 411 !heap()->incremental_marking()->IsMarking(); | |
| 406 | 412 |
| 407 // Rather than passing the tracer around we stash it in a static member | 413 // Rather than passing the tracer around we stash it in a static member |
| 408 // variable. | 414 // variable. |
| 409 tracer_ = tracer; | 415 tracer_ = tracer; |
| 410 | 416 |
| 411 #ifdef DEBUG | 417 #ifdef DEBUG |
| 412 ASSERT(state_ == IDLE); | 418 ASSERT(state_ == IDLE); |
| 413 state_ = PREPARE_GC; | 419 state_ = PREPARE_GC; |
| 414 #endif | 420 #endif |
| 415 ASSERT(!FLAG_always_compact || !FLAG_never_compact); | 421 ASSERT(!FLAG_always_compact || !FLAG_never_compact); |
| 416 | 422 |
| 417 if (FLAG_collect_maps) CreateBackPointers(); | 423 if (collect_maps_) CreateBackPointers(); |
| 418 #ifdef ENABLE_GDB_JIT_INTERFACE | 424 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 419 if (FLAG_gdbjit) { | 425 if (FLAG_gdbjit) { |
| 420 // If GDBJIT interface is active disable compaction. | 426 // If GDBJIT interface is active disable compaction. |
| 421 compacting_collection_ = false; | 427 compacting_collection_ = false; |
| 422 } | 428 } |
| 423 #endif | 429 #endif |
| 424 | 430 |
| 425 if (heap()->incremental_marking()->IsMarking() && PreciseSweepingRequired()) { | 431 if (heap()->incremental_marking()->IsMarking() && PreciseSweepingRequired()) { |
| 426 heap()->incremental_marking()->Abort(); | 432 heap()->incremental_marking()->Abort(); |
| 427 } | 433 } |
| (...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1428 if (object->IsMap()) { | 1434 if (object->IsMap()) { |
| 1429 Map* map = Map::cast(object); | 1435 Map* map = Map::cast(object); |
| 1430 if (FLAG_cleanup_code_caches_at_gc) { | 1436 if (FLAG_cleanup_code_caches_at_gc) { |
| 1431 map->ClearCodeCache(heap()); | 1437 map->ClearCodeCache(heap()); |
| 1432 } | 1438 } |
| 1433 | 1439 |
| 1434 // When map collection is enabled we have to mark through map's transitions | 1440 // When map collection is enabled we have to mark through map's transitions |
| 1435 // in a special way to make transition links weak. | 1441 // in a special way to make transition links weak. |
| 1436 // Only maps for subclasses of JSReceiver can have transitions. | 1442 // Only maps for subclasses of JSReceiver can have transitions. |
| 1437 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | 1443 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); |
| 1438 if (FLAG_collect_maps && map->instance_type() >= FIRST_JS_RECEIVER_TYPE) { | 1444 if (collect_maps_ && map->instance_type() >= FIRST_JS_RECEIVER_TYPE) { |
| 1439 MarkMapContents(map); | 1445 MarkMapContents(map); |
| 1440 } else { | 1446 } else { |
| 1441 marking_deque_.PushBlack(map); | 1447 marking_deque_.PushBlack(map); |
| 1442 } | 1448 } |
| 1443 } else { | 1449 } else { |
| 1444 marking_deque_.PushBlack(object); | 1450 marking_deque_.PushBlack(object); |
| 1445 } | 1451 } |
| 1446 } | 1452 } |
| 1447 | 1453 |
| 1448 | 1454 |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2030 live_code_objects_size_ += obj->Size(); | 2036 live_code_objects_size_ += obj->Size(); |
| 2031 } else if (heap()->lo_space()->Contains(obj)) { | 2037 } else if (heap()->lo_space()->Contains(obj)) { |
| 2032 live_lo_objects_size_ += obj->Size(); | 2038 live_lo_objects_size_ += obj->Size(); |
| 2033 } else { | 2039 } else { |
| 2034 UNREACHABLE(); | 2040 UNREACHABLE(); |
| 2035 } | 2041 } |
| 2036 } | 2042 } |
| 2037 #endif // DEBUG | 2043 #endif // DEBUG |
| 2038 | 2044 |
| 2039 | 2045 |
| 2046 void MarkCompactCollector::ReattachInitialMaps() { | |
| 2047 HeapObjectIterator map_iterator(heap()->map_space()); | |
| 2048 for (HeapObject* obj = map_iterator.Next(); | |
| 2049 obj != NULL; | |
| 2050 obj = map_iterator.Next()) { | |
| 2051 if (obj->IsFreeSpace()) continue; | |
| 2052 Map* map = Map::cast(obj); | |
| 2053 | |
| 2054 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE); | |
| 2055 if (map->instance_type() < FIRST_JS_RECEIVER_TYPE) continue; | |
| 2056 | |
| 2057 if (map->attached_to_shared_function_info()) { | |
| 2058 JSFunction::cast(map->constructor())->shared()->AttachInitialMap(map); | |
| 2059 } | |
| 2060 } | |
| 2061 } | |
| 2062 | |
| 2063 | |
| 2040 void MarkCompactCollector::ClearNonLiveTransitions() { | 2064 void MarkCompactCollector::ClearNonLiveTransitions() { |
| 2041 HeapObjectIterator map_iterator(heap()->map_space()); | 2065 HeapObjectIterator map_iterator(heap()->map_space()); |
| 2042 // Iterate over the map space, setting map transitions that go from | 2066 // Iterate over the map space, setting map transitions that go from |
| 2043 // a marked map to an unmarked map to null transitions. At the same time, | 2067 // a marked map to an unmarked map to null transitions. At the same time, |
| 2044 // set all the prototype fields of maps back to their original value, | 2068 // set all the prototype fields of maps back to their original value, |
| 2045 // dropping the back pointers temporarily stored in the prototype field. | 2069 // dropping the back pointers temporarily stored in the prototype field. |
| 2046 // Setting the prototype field requires following the linked list of | 2070 // Setting the prototype field requires following the linked list of |
| 2047 // back pointers, reversing them all at once. This allows us to find | 2071 // back pointers, reversing them all at once. This allows us to find |
| 2048 // those maps with map transitions that need to be nulled, and only | 2072 // those maps with map transitions that need to be nulled, and only |
| 2049 // scan the descriptor arrays of those maps, not all maps. | 2073 // scan the descriptor arrays of those maps, not all maps. |
| (...skipping 1270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3320 while (buffer != NULL) { | 3344 while (buffer != NULL) { |
| 3321 SlotsBuffer* next_buffer = buffer->next(); | 3345 SlotsBuffer* next_buffer = buffer->next(); |
| 3322 DeallocateBuffer(buffer); | 3346 DeallocateBuffer(buffer); |
| 3323 buffer = next_buffer; | 3347 buffer = next_buffer; |
| 3324 } | 3348 } |
| 3325 *buffer_address = NULL; | 3349 *buffer_address = NULL; |
| 3326 } | 3350 } |
| 3327 | 3351 |
| 3328 | 3352 |
| 3329 } } // namespace v8::internal | 3353 } } // namespace v8::internal |
| OLD | NEW |