OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1117 | 1117 |
1118 while (head_start != head_end) { | 1118 while (head_start != head_end) { |
1119 int size = static_cast<int>(*(head_start++)); | 1119 int size = static_cast<int>(*(head_start++)); |
1120 HeapObject* obj = reinterpret_cast<HeapObject*>(*(head_start++)); | 1120 HeapObject* obj = reinterpret_cast<HeapObject*>(*(head_start++)); |
1121 emergency_stack_->Add(Entry(obj, size)); | 1121 emergency_stack_->Add(Entry(obj, size)); |
1122 } | 1122 } |
1123 rear_ = head_end; | 1123 rear_ = head_end; |
1124 } | 1124 } |
1125 | 1125 |
1126 | 1126 |
1127 class ScavengeWeakObjectRetainer : public WeakObjectRetainer { | |
1128 public: | |
1129 explicit ScavengeWeakObjectRetainer(Heap* heap) : heap_(heap) { } | |
1130 | |
1131 virtual Object* RetainAs(Object* object) { | |
1132 if (!heap_->InFromSpace(object)) { | |
1133 return object; | |
1134 } | |
1135 | |
1136 MapWord map_word = HeapObject::cast(object)->map_word(); | |
1137 if (map_word.IsForwardingAddress()) { | |
1138 return map_word.ToForwardingAddress(); | |
1139 } | |
1140 return NULL; | |
1141 } | |
1142 | |
1143 private: | |
1144 Heap* heap_; | |
1145 }; | |
1146 | |
1147 | |
1127 void Heap::Scavenge() { | 1148 void Heap::Scavenge() { |
1128 #ifdef DEBUG | 1149 #ifdef DEBUG |
1129 if (FLAG_verify_heap) VerifyNonPointerSpacePointers(); | 1150 if (FLAG_verify_heap) VerifyNonPointerSpacePointers(); |
1130 #endif | 1151 #endif |
1131 | 1152 |
1132 gc_state_ = SCAVENGE; | 1153 gc_state_ = SCAVENGE; |
1133 | 1154 |
1134 // Implements Cheney's copying algorithm | 1155 // Implements Cheney's copying algorithm |
1135 LOG(isolate_, ResourceEvent("scavenge", "begin")); | 1156 LOG(isolate_, ResourceEvent("scavenge", "begin")); |
1136 | 1157 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1215 &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1236 &UpdateNewSpaceReferenceInExternalStringTableEntry); |
1216 | 1237 |
1217 promotion_queue_.Destroy(); | 1238 promotion_queue_.Destroy(); |
1218 | 1239 |
1219 LiveObjectList::UpdateReferencesForScavengeGC(); | 1240 LiveObjectList::UpdateReferencesForScavengeGC(); |
1220 if (!FLAG_watch_ic_patching) { | 1241 if (!FLAG_watch_ic_patching) { |
1221 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | 1242 isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
1222 } | 1243 } |
1223 incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1244 incremental_marking()->UpdateMarkingDequeAfterScavenge(); |
1224 | 1245 |
1246 ScavengeWeakObjectRetainer weak_object_retainer(this); | |
1247 ProcessWeakReferences(&weak_object_retainer); | |
1248 | |
1225 ASSERT(new_space_front == new_space_.top()); | 1249 ASSERT(new_space_front == new_space_.top()); |
1226 | 1250 |
1227 // Set age mark. | 1251 // Set age mark. |
1228 new_space_.set_age_mark(new_space_.top()); | 1252 new_space_.set_age_mark(new_space_.top()); |
1229 | 1253 |
1230 new_space_.LowerInlineAllocationLimit( | 1254 new_space_.LowerInlineAllocationLimit( |
1231 new_space_.inline_allocation_limit_step()); | 1255 new_space_.inline_allocation_limit_step()); |
1232 | 1256 |
1233 // Update how much has survived scavenge. | 1257 // Update how much has survived scavenge. |
1234 IncrementYoungSurvivorsCounter(static_cast<int>( | 1258 IncrementYoungSurvivorsCounter(static_cast<int>( |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1301 Object** end = start + external_string_table_.old_space_strings_.length(); | 1325 Object** end = start + external_string_table_.old_space_strings_.length(); |
1302 for (Object** p = start; p < end; ++p) *p = updater_func(this, p); | 1326 for (Object** p = start; p < end; ++p) *p = updater_func(this, p); |
1303 } | 1327 } |
1304 | 1328 |
1305 UpdateNewSpaceReferencesInExternalStringTable(updater_func); | 1329 UpdateNewSpaceReferencesInExternalStringTable(updater_func); |
1306 } | 1330 } |
1307 | 1331 |
1308 | 1332 |
1309 static Object* ProcessFunctionWeakReferences(Heap* heap, | 1333 static Object* ProcessFunctionWeakReferences(Heap* heap, |
1310 Object* function, | 1334 Object* function, |
1311 WeakObjectRetainer* retainer) { | 1335 WeakObjectRetainer* retainer, |
1336 bool record_slots) { | |
1312 Object* undefined = heap->undefined_value(); | 1337 Object* undefined = heap->undefined_value(); |
1313 Object* head = undefined; | 1338 Object* head = undefined; |
1314 JSFunction* tail = NULL; | 1339 JSFunction* tail = NULL; |
1315 Object* candidate = function; | 1340 Object* candidate = function; |
1316 while (candidate != undefined) { | 1341 while (candidate != undefined) { |
1317 // Check whether to keep the candidate in the list. | 1342 // Check whether to keep the candidate in the list. |
1318 JSFunction* candidate_function = reinterpret_cast<JSFunction*>(candidate); | 1343 JSFunction* candidate_function = reinterpret_cast<JSFunction*>(candidate); |
1319 Object* retain = retainer->RetainAs(candidate); | 1344 Object* retain = retainer->RetainAs(candidate); |
1320 if (retain != NULL) { | 1345 if (retain != NULL) { |
1321 if (head == undefined) { | 1346 if (head == undefined) { |
1322 // First element in the list. | 1347 // First element in the list. |
1323 head = retain; | 1348 head = retain; |
1324 } else { | 1349 } else { |
1325 // Subsequent elements in the list. | 1350 // Subsequent elements in the list. |
1326 ASSERT(tail != NULL); | 1351 ASSERT(tail != NULL); |
1327 tail->set_next_function_link(retain); | 1352 tail->set_next_function_link(retain); |
1353 if (record_slots) { | |
1354 Object** next_function = | |
1355 HeapObject::RawField(tail, JSFunction::kNextFunctionLinkOffset); | |
1356 heap->mark_compact_collector()->RecordSlot( | |
1357 next_function, next_function, retain); | |
1358 } | |
1328 } | 1359 } |
1329 // Retained function is new tail. | 1360 // Retained function is new tail. |
1330 candidate_function = reinterpret_cast<JSFunction*>(retain); | 1361 candidate_function = reinterpret_cast<JSFunction*>(retain); |
1331 tail = candidate_function; | 1362 tail = candidate_function; |
1332 | 1363 |
1333 ASSERT(retain->IsUndefined() || retain->IsJSFunction()); | 1364 ASSERT(retain->IsUndefined() || retain->IsJSFunction()); |
1334 | 1365 |
1335 if (retain == undefined) break; | 1366 if (retain == undefined) break; |
1336 } | 1367 } |
1337 | 1368 |
1338 // Move to next element in the list. | 1369 // Move to next element in the list. |
1339 candidate = candidate_function->next_function_link(); | 1370 candidate = candidate_function->next_function_link(); |
1340 } | 1371 } |
1341 | 1372 |
1342 // Terminate the list if there is one or more elements. | 1373 // Terminate the list if there is one or more elements. |
1343 if (tail != NULL) { | 1374 if (tail != NULL) { |
1344 tail->set_next_function_link(undefined); | 1375 tail->set_next_function_link(undefined); |
1345 } | 1376 } |
1346 | 1377 |
1347 return head; | 1378 return head; |
1348 } | 1379 } |
1349 | 1380 |
1350 | 1381 |
1351 void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) { | 1382 void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) { |
1352 Object* undefined = undefined_value(); | 1383 Object* undefined = undefined_value(); |
1353 Object* head = undefined; | 1384 Object* head = undefined; |
1354 Context* tail = NULL; | 1385 Context* tail = NULL; |
1355 Object* candidate = global_contexts_list_; | 1386 Object* candidate = global_contexts_list_; |
1387 | |
1388 // We don't record weak slots during marking or scavenges. | |
1389 // Instead we do it once when we complete mark-compact cycle. | |
1390 // Note that write barrier has not effect if we are already the middle of | |
Michael Starzinger
2012/04/17 09:53:18
Missing "in" and s/not/no/
| |
1391 // compacting mark-sweep cycle and we have to record slots manually. | |
1392 bool record_slots = | |
1393 gc_state() == MARK_COMPACT && | |
1394 mark_compact_collector()->is_compacting(); | |
1395 | |
1356 while (candidate != undefined) { | 1396 while (candidate != undefined) { |
1357 // Check whether to keep the candidate in the list. | 1397 // Check whether to keep the candidate in the list. |
1358 Context* candidate_context = reinterpret_cast<Context*>(candidate); | 1398 Context* candidate_context = reinterpret_cast<Context*>(candidate); |
1359 Object* retain = retainer->RetainAs(candidate); | 1399 Object* retain = retainer->RetainAs(candidate); |
1360 if (retain != NULL) { | 1400 if (retain != NULL) { |
1361 if (head == undefined) { | 1401 if (head == undefined) { |
1362 // First element in the list. | 1402 // First element in the list. |
1363 head = retain; | 1403 head = retain; |
1364 } else { | 1404 } else { |
1365 // Subsequent elements in the list. | 1405 // Subsequent elements in the list. |
1366 ASSERT(tail != NULL); | 1406 ASSERT(tail != NULL); |
1367 tail->set_unchecked(this, | 1407 tail->set_unchecked(this, |
1368 Context::NEXT_CONTEXT_LINK, | 1408 Context::NEXT_CONTEXT_LINK, |
1369 retain, | 1409 retain, |
1370 UPDATE_WRITE_BARRIER); | 1410 UPDATE_WRITE_BARRIER); |
1411 | |
1412 if (record_slots) { | |
1413 Object** next_context = | |
1414 HeapObject::RawField( | |
1415 tail, FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK)); | |
1416 mark_compact_collector()->RecordSlot( | |
1417 next_context, next_context, retain); | |
1418 } | |
1371 } | 1419 } |
1372 // Retained context is new tail. | 1420 // Retained context is new tail. |
1373 candidate_context = reinterpret_cast<Context*>(retain); | 1421 candidate_context = reinterpret_cast<Context*>(retain); |
1374 tail = candidate_context; | 1422 tail = candidate_context; |
1375 | 1423 |
1376 if (retain == undefined) break; | 1424 if (retain == undefined) break; |
1377 | 1425 |
1378 // Process the weak list of optimized functions for the context. | 1426 // Process the weak list of optimized functions for the context. |
1379 Object* function_list_head = | 1427 Object* function_list_head = |
1380 ProcessFunctionWeakReferences( | 1428 ProcessFunctionWeakReferences( |
1381 this, | 1429 this, |
1382 candidate_context->get(Context::OPTIMIZED_FUNCTIONS_LIST), | 1430 candidate_context->get(Context::OPTIMIZED_FUNCTIONS_LIST), |
1383 retainer); | 1431 retainer, |
1432 record_slots); | |
1384 candidate_context->set_unchecked(this, | 1433 candidate_context->set_unchecked(this, |
1385 Context::OPTIMIZED_FUNCTIONS_LIST, | 1434 Context::OPTIMIZED_FUNCTIONS_LIST, |
1386 function_list_head, | 1435 function_list_head, |
1387 UPDATE_WRITE_BARRIER); | 1436 UPDATE_WRITE_BARRIER); |
1437 if (record_slots) { | |
1438 Object** optimized_functions = | |
1439 HeapObject::RawField( | |
1440 tail, FixedArray::SizeFor(Context::OPTIMIZED_FUNCTIONS_LIST)); | |
1441 mark_compact_collector()->RecordSlot( | |
1442 optimized_functions, optimized_functions, function_list_head); | |
1443 } | |
1388 } | 1444 } |
1389 | 1445 |
1390 // Move to next element in the list. | 1446 // Move to next element in the list. |
1391 candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK); | 1447 candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK); |
1392 } | 1448 } |
1393 | 1449 |
1394 // Terminate the list if there is one or more elements. | 1450 // Terminate the list if there is one or more elements. |
1395 if (tail != NULL) { | 1451 if (tail != NULL) { |
1396 tail->set_unchecked(this, | 1452 tail->set_unchecked(this, |
1397 Context::NEXT_CONTEXT_LINK, | 1453 Context::NEXT_CONTEXT_LINK, |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1636 if (maybe_result->ToObject(&result)) { | 1692 if (maybe_result->ToObject(&result)) { |
1637 HeapObject* target = HeapObject::cast(result); | 1693 HeapObject* target = HeapObject::cast(result); |
1638 | 1694 |
1639 // Order is important: slot might be inside of the target if target | 1695 // Order is important: slot might be inside of the target if target |
1640 // was allocated over a dead object and slot comes from the store | 1696 // was allocated over a dead object and slot comes from the store |
1641 // buffer. | 1697 // buffer. |
1642 *slot = target; | 1698 *slot = target; |
1643 MigrateObject(heap, object, target, object_size); | 1699 MigrateObject(heap, object, target, object_size); |
1644 | 1700 |
1645 if (object_contents == POINTER_OBJECT) { | 1701 if (object_contents == POINTER_OBJECT) { |
1646 heap->promotion_queue()->insert(target, object_size); | 1702 if (map->instance_type() == JS_FUNCTION_TYPE) { |
1703 heap->promotion_queue()->insert( | |
1704 target, JSFunction::kNonWeakFieldsEndOffset); | |
1705 } else { | |
1706 heap->promotion_queue()->insert(target, object_size); | |
1707 } | |
1647 } | 1708 } |
1648 | 1709 |
1649 heap->tracer()->increment_promoted_objects_size(object_size); | 1710 heap->tracer()->increment_promoted_objects_size(object_size); |
1650 return; | 1711 return; |
1651 } | 1712 } |
1652 } | 1713 } |
1653 MaybeObject* allocation = heap->new_space()->AllocateRaw(object_size); | 1714 MaybeObject* allocation = heap->new_space()->AllocateRaw(object_size); |
1654 heap->promotion_queue()->SetNewLimit(heap->new_space()->top()); | 1715 heap->promotion_queue()->SetNewLimit(heap->new_space()->top()); |
1655 Object* result = allocation->ToObjectUnchecked(); | 1716 Object* result = allocation->ToObjectUnchecked(); |
1656 HeapObject* target = HeapObject::cast(result); | 1717 HeapObject* target = HeapObject::cast(result); |
(...skipping 5349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7006 } else { | 7067 } else { |
7007 p ^= 0x1d1ed & (Page::kPageSize - 1); // I died. | 7068 p ^= 0x1d1ed & (Page::kPageSize - 1); // I died. |
7008 } | 7069 } |
7009 remembered_unmapped_pages_[remembered_unmapped_pages_index_] = | 7070 remembered_unmapped_pages_[remembered_unmapped_pages_index_] = |
7010 reinterpret_cast<Address>(p); | 7071 reinterpret_cast<Address>(p); |
7011 remembered_unmapped_pages_index_++; | 7072 remembered_unmapped_pages_index_++; |
7012 remembered_unmapped_pages_index_ %= kRememberedUnmappedPages; | 7073 remembered_unmapped_pages_index_ %= kRememberedUnmappedPages; |
7013 } | 7074 } |
7014 | 7075 |
7015 } } // namespace v8::internal | 7076 } } // namespace v8::internal |
OLD | NEW |