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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « src/mark-compact.h ('k') | src/messages.js » ('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 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 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 static void VerifyMarkbitsAreClean(PagedSpace* space) { 276 static void VerifyMarkbitsAreClean(PagedSpace* space) {
277 PageIterator it(space); 277 PageIterator it(space);
278 278
279 while (it.has_next()) { 279 while (it.has_next()) {
280 Page* p = it.next(); 280 Page* p = it.next();
281 ASSERT(p->markbits()->IsClean()); 281 ASSERT(p->markbits()->IsClean());
282 } 282 }
283 } 283 }
284 284
285 static void VerifyMarkbitsAreClean(NewSpace* space) { 285 static void VerifyMarkbitsAreClean(NewSpace* space) {
286 NewSpacePageIterator it(space->ToSpaceStart(), space->ToSpaceEnd()); 286 NewSpacePageIterator it(space->bottom(), space->top());
287 287
288 while (it.has_next()) { 288 while (it.has_next()) {
289 NewSpacePage* p = it.next(); 289 NewSpacePage* p = it.next();
290 ASSERT(p->markbits()->IsClean()); 290 ASSERT(p->markbits()->IsClean());
291 } 291 }
292 } 292 }
293 293
294 static void VerifyMarkbitsAreClean(Heap* heap) { 294 static void VerifyMarkbitsAreClean(Heap* heap) {
295 VerifyMarkbitsAreClean(heap->old_pointer_space()); 295 VerifyMarkbitsAreClean(heap->old_pointer_space());
296 VerifyMarkbitsAreClean(heap->old_data_space()); 296 VerifyMarkbitsAreClean(heap->old_data_space());
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 ASSERT(!FLAG_always_compact || !FLAG_never_compact); 415 ASSERT(!FLAG_always_compact || !FLAG_never_compact);
416 416
417 if (FLAG_collect_maps) CreateBackPointers(); 417 if (FLAG_collect_maps) CreateBackPointers();
418 #ifdef ENABLE_GDB_JIT_INTERFACE 418 #ifdef ENABLE_GDB_JIT_INTERFACE
419 if (FLAG_gdbjit) { 419 if (FLAG_gdbjit) {
420 // If GDBJIT interface is active disable compaction. 420 // If GDBJIT interface is active disable compaction.
421 compacting_collection_ = false; 421 compacting_collection_ = false;
422 } 422 }
423 #endif 423 #endif
424 424
425 if (heap()->incremental_marking()->IsMarking() && PreciseSweepingRequired()) {
426 heap()->incremental_marking()->Abort();
427 }
428
425 if (!FLAG_never_compact) StartCompaction(); 429 if (!FLAG_never_compact) StartCompaction();
426 430
427 PagedSpaces spaces; 431 PagedSpaces spaces;
428 for (PagedSpace* space = spaces.next(); 432 for (PagedSpace* space = spaces.next();
429 space != NULL; 433 space != NULL;
430 space = spaces.next()) { 434 space = spaces.next()) {
431 space->PrepareForMarkCompact(); 435 space->PrepareForMarkCompact();
432 } 436 }
433 437
434 if (!heap()->incremental_marking()->IsMarking()) { 438 if (!heap()->incremental_marking()->IsMarking()) {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 void>::Visit); 671 void>::Visit);
668 672
669 673
670 table_.Register(kVisitFixedArray, 674 table_.Register(kVisitFixedArray,
671 &FlexibleBodyVisitor<StaticMarkingVisitor, 675 &FlexibleBodyVisitor<StaticMarkingVisitor,
672 FixedArray::BodyDescriptor, 676 FixedArray::BodyDescriptor,
673 void>::Visit); 677 void>::Visit);
674 678
675 table_.Register(kVisitGlobalContext, &VisitGlobalContext); 679 table_.Register(kVisitGlobalContext, &VisitGlobalContext);
676 680
681 table_.Register(kVisitFixedDoubleArray, DataObjectVisitor::Visit);
682
677 table_.Register(kVisitByteArray, &DataObjectVisitor::Visit); 683 table_.Register(kVisitByteArray, &DataObjectVisitor::Visit);
678 table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit); 684 table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit);
679 table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit); 685 table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit);
680 table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit); 686 table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit);
681 687
682 table_.Register(kVisitOddball, 688 table_.Register(kVisitOddball,
683 &FixedBodyVisitor<StaticMarkingVisitor, 689 &FixedBodyVisitor<StaticMarkingVisitor,
684 Oddball::BodyDescriptor, 690 Oddball::BodyDescriptor,
685 void>::Visit); 691 void>::Visit);
686 table_.Register(kVisitMap, 692 table_.Register(kVisitMap,
687 &FixedBodyVisitor<StaticMarkingVisitor, 693 &FixedBodyVisitor<StaticMarkingVisitor,
688 Map::BodyDescriptor, 694 Map::BodyDescriptor,
689 void>::Visit); 695 void>::Visit);
690 696
691 table_.Register(kVisitCode, &VisitCode); 697 table_.Register(kVisitCode, &VisitCode);
692 698
693 table_.Register(kVisitSharedFunctionInfo, 699 table_.Register(kVisitSharedFunctionInfo,
694 &VisitSharedFunctionInfoAndFlushCode); 700 &VisitSharedFunctionInfoAndFlushCode);
695 701
696 table_.Register(kVisitJSFunction, 702 table_.Register(kVisitJSFunction,
697 &VisitJSFunctionAndFlushCode); 703 &VisitJSFunctionAndFlushCode);
698 704
705 table_.Register(kVisitJSRegExp,
706 &VisitRegExpAndFlushCode);
707
699 table_.Register(kVisitPropertyCell, 708 table_.Register(kVisitPropertyCell,
700 &FixedBodyVisitor<StaticMarkingVisitor, 709 &FixedBodyVisitor<StaticMarkingVisitor,
701 JSGlobalPropertyCell::BodyDescriptor, 710 JSGlobalPropertyCell::BodyDescriptor,
702 void>::Visit); 711 void>::Visit);
703 712
704 table_.RegisterSpecializations<DataObjectVisitor, 713 table_.RegisterSpecializations<DataObjectVisitor,
705 kVisitDataObject, 714 kVisitDataObject,
706 kVisitDataObjectGeneric>(); 715 kVisitDataObjectGeneric>();
707 716
708 table_.RegisterSpecializations<JSObjectVisitor, 717 table_.RegisterSpecializations<JSObjectVisitor,
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>( 852 reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>(
844 map->GetHeap()); 853 map->GetHeap());
845 } 854 }
846 855
847 // Code flushing support. 856 // Code flushing support.
848 857
849 // How many collections newly compiled code object will survive before being 858 // How many collections newly compiled code object will survive before being
850 // flushed. 859 // flushed.
851 static const int kCodeAgeThreshold = 5; 860 static const int kCodeAgeThreshold = 5;
852 861
862 static const int kRegExpCodeThreshold = 5;
863
853 inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) { 864 inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) {
854 Object* undefined = heap->undefined_value(); 865 Object* undefined = heap->undefined_value();
855 return (info->script() != undefined) && 866 return (info->script() != undefined) &&
856 (reinterpret_cast<Script*>(info->script())->source() != undefined); 867 (reinterpret_cast<Script*>(info->script())->source() != undefined);
857 } 868 }
858 869
859 870
860 inline static bool IsCompiled(JSFunction* function) { 871 inline static bool IsCompiled(JSFunction* function) {
861 return function->unchecked_code() != 872 return function->unchecked_code() !=
862 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); 873 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
948 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object); 959 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object);
949 960
950 if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap(); 961 if (shared->IsInobjectSlackTrackingInProgress()) shared->DetachInitialMap();
951 962
952 FixedBodyVisitor<StaticMarkingVisitor, 963 FixedBodyVisitor<StaticMarkingVisitor,
953 SharedFunctionInfo::BodyDescriptor, 964 SharedFunctionInfo::BodyDescriptor,
954 void>::Visit(map, object); 965 void>::Visit(map, object);
955 } 966 }
956 967
957 968
969 static void UpdateRegExpCodeAgeAndFlush(Heap* heap,
970 JSRegExp* re,
971 bool is_ascii) {
972 // Make sure that the fixed array is in fact initialized on the RegExp.
973 // We could potentially trigger a GC when initializing the RegExp.
974 if (HeapObject::cast(re->data())->map()->instance_type() !=
975 FIXED_ARRAY_TYPE) return;
976
977 // Make sure this is a RegExp that actually contains code.
978 if (re->TypeTagUnchecked() != JSRegExp::IRREGEXP) return;
979
980 Object* code = re->DataAtUnchecked(JSRegExp::code_index(is_ascii));
981 if (!code->IsSmi() &&
982 HeapObject::cast(code)->map()->instance_type() == CODE_TYPE) {
983 // Save a copy that can be reinstated if we need the code again.
984 re->SetDataAtUnchecked(JSRegExp::saved_code_index(is_ascii),
985 code,
986 heap);
987 // Set a number in the 0-255 range to guarantee no smi overflow.
988 re->SetDataAtUnchecked(JSRegExp::code_index(is_ascii),
989 Smi::FromInt(heap->sweep_generation() & 0xff),
990 heap);
991 } else if (code->IsSmi()) {
992 int value = Smi::cast(code)->value();
993 // The regexp has not been compiled yet or there was a compilation error.
994 if (value == JSRegExp::kUninitializedValue ||
995 value == JSRegExp::kCompilationErrorValue) {
996 return;
997 }
998
999 // Check if we should flush now.
1000 if (value == ((heap->sweep_generation() - kRegExpCodeThreshold) & 0xff)) {
1001 re->SetDataAtUnchecked(JSRegExp::code_index(is_ascii),
1002 Smi::FromInt(JSRegExp::kUninitializedValue),
1003 heap);
1004 re->SetDataAtUnchecked(JSRegExp::saved_code_index(is_ascii),
1005 Smi::FromInt(JSRegExp::kUninitializedValue),
1006 heap);
1007 }
1008 }
1009 }
1010
1011
1012 // Works by setting the current sweep_generation (as a smi) in the
1013 // code object place in the data array of the RegExp and keeps a copy
1014 // around that can be reinstated if we reuse the RegExp before flushing.
1015 // If we did not use the code for kRegExpCodeThreshold mark sweep GCs
1016 // we flush the code.
1017 static void VisitRegExpAndFlushCode(Map* map, HeapObject* object) {
1018 Heap* heap = map->GetHeap();
1019 MarkCompactCollector* collector = heap->mark_compact_collector();
1020 if (!collector->is_code_flushing_enabled()) {
1021 VisitJSRegExpFields(map, object);
1022 return;
1023 }
1024 JSRegExp* re = reinterpret_cast<JSRegExp*>(object);
1025 // Flush code or set age on both ascii and two byte code.
1026 UpdateRegExpCodeAgeAndFlush(heap, re, true);
1027 UpdateRegExpCodeAgeAndFlush(heap, re, false);
1028 // Visit the fields of the RegExp, including the updated FixedArray.
1029 VisitJSRegExpFields(map, object);
1030 }
1031
1032
958 static void VisitSharedFunctionInfoAndFlushCode(Map* map, 1033 static void VisitSharedFunctionInfoAndFlushCode(Map* map,
959 HeapObject* object) { 1034 HeapObject* object) {
960 MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); 1035 MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector();
961 if (!collector->is_code_flushing_enabled()) { 1036 if (!collector->is_code_flushing_enabled()) {
962 VisitSharedFunctionInfoGeneric(map, object); 1037 VisitSharedFunctionInfoGeneric(map, object);
963 return; 1038 return;
964 } 1039 }
965 VisitSharedFunctionInfoAndFlushCodeGeneric(map, object, false); 1040 VisitSharedFunctionInfoAndFlushCodeGeneric(map, object, false);
966 } 1041 }
967 1042
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 HeapObject::RawField(object, 1182 HeapObject::RawField(object,
1108 JSFunction::kNonWeakFieldsEndOffset)); 1183 JSFunction::kNonWeakFieldsEndOffset));
1109 1184
1110 // Don't visit the next function list field as it is a weak reference. 1185 // Don't visit the next function list field as it is a weak reference.
1111 Object** next_function = 1186 Object** next_function =
1112 HeapObject::RawField(object, JSFunction::kNextFunctionLinkOffset); 1187 HeapObject::RawField(object, JSFunction::kNextFunctionLinkOffset);
1113 heap->mark_compact_collector()->RecordSlot( 1188 heap->mark_compact_collector()->RecordSlot(
1114 next_function, next_function, *next_function); 1189 next_function, next_function, *next_function);
1115 } 1190 }
1116 1191
1192 static inline void VisitJSRegExpFields(Map* map,
1193 HeapObject* object) {
1194 int last_property_offset =
1195 JSRegExp::kSize + kPointerSize * map->inobject_properties();
1196 VisitPointers(map->GetHeap(),
1197 SLOT_ADDR(object, JSRegExp::kPropertiesOffset),
1198 SLOT_ADDR(object, last_property_offset));
1199 }
1200
1117 1201
1118 static void VisitSharedFunctionInfoFields(Heap* heap, 1202 static void VisitSharedFunctionInfoFields(Heap* heap,
1119 HeapObject* object, 1203 HeapObject* object,
1120 bool flush_code_candidate) { 1204 bool flush_code_candidate) {
1121 VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kNameOffset)); 1205 VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kNameOffset));
1122 1206
1123 if (!flush_code_candidate) { 1207 if (!flush_code_candidate) {
1124 VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kCodeOffset)); 1208 VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kCodeOffset));
1125 } 1209 }
1126 1210
(...skipping 19 matching lines...) Expand all
1146 explicit MarkingVisitor(Heap* heap) : heap_(heap) { } 1230 explicit MarkingVisitor(Heap* heap) : heap_(heap) { }
1147 1231
1148 void VisitPointer(Object** p) { 1232 void VisitPointer(Object** p) {
1149 StaticMarkingVisitor::VisitPointer(heap_, p); 1233 StaticMarkingVisitor::VisitPointer(heap_, p);
1150 } 1234 }
1151 1235
1152 void VisitPointers(Object** start, Object** end) { 1236 void VisitPointers(Object** start, Object** end) {
1153 StaticMarkingVisitor::VisitPointers(heap_, start, end); 1237 StaticMarkingVisitor::VisitPointers(heap_, start, end);
1154 } 1238 }
1155 1239
1156 void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) {
1157 StaticMarkingVisitor::VisitCodeTarget(heap, rinfo);
1158 }
1159
1160 void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo) {
1161 StaticMarkingVisitor::VisitGlobalPropertyCell(heap, rinfo);
1162 }
1163
1164 void VisitDebugTarget(Heap* heap, RelocInfo* rinfo) {
1165 StaticMarkingVisitor::VisitDebugTarget(heap, rinfo);
1166 }
1167
1168 private: 1240 private:
1169 Heap* heap_; 1241 Heap* heap_;
1170 }; 1242 };
1171 1243
1172 1244
1173 class CodeMarkingVisitor : public ThreadVisitor { 1245 class CodeMarkingVisitor : public ThreadVisitor {
1174 public: 1246 public:
1175 explicit CodeMarkingVisitor(MarkCompactCollector* collector) 1247 explicit CodeMarkingVisitor(MarkCompactCollector* collector)
1176 : collector_(collector) {} 1248 : collector_(collector) {}
1177 1249
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1322 // Set the entry to null_value (as deleted). 1394 // Set the entry to null_value (as deleted).
1323 *p = heap_->null_value(); 1395 *p = heap_->null_value();
1324 pointers_removed_++; 1396 pointers_removed_++;
1325 } 1397 }
1326 } 1398 }
1327 } 1399 }
1328 1400
1329 int PointersRemoved() { 1401 int PointersRemoved() {
1330 return pointers_removed_; 1402 return pointers_removed_;
1331 } 1403 }
1404
1332 private: 1405 private:
1333 Heap* heap_; 1406 Heap* heap_;
1334 int pointers_removed_; 1407 int pointers_removed_;
1335 }; 1408 };
1336 1409
1337 1410
1338 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects 1411 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects
1339 // are retained. 1412 // are retained.
1340 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { 1413 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
1341 public: 1414 public:
(...skipping 11 matching lines...) Expand all
1353 ASSERT(IsMarked(object)); 1426 ASSERT(IsMarked(object));
1354 ASSERT(HEAP->Contains(object)); 1427 ASSERT(HEAP->Contains(object));
1355 if (object->IsMap()) { 1428 if (object->IsMap()) {
1356 Map* map = Map::cast(object); 1429 Map* map = Map::cast(object);
1357 if (FLAG_cleanup_code_caches_at_gc) { 1430 if (FLAG_cleanup_code_caches_at_gc) {
1358 map->ClearCodeCache(heap()); 1431 map->ClearCodeCache(heap());
1359 } 1432 }
1360 1433
1361 // When map collection is enabled we have to mark through map's transitions 1434 // When map collection is enabled we have to mark through map's transitions
1362 // in a special way to make transition links weak. 1435 // in a special way to make transition links weak.
1363 // Only maps with instance types between FIRST_JS_OBJECT_TYPE and 1436 // Only maps for subclasses of JSReceiver can have transitions.
1364 // JS_FUNCTION_TYPE can have transitions. 1437 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
1365 if (FLAG_collect_maps && 1438 if (FLAG_collect_maps && map->instance_type() >= FIRST_JS_RECEIVER_TYPE) {
1366 map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
1367 map->instance_type() <= JS_FUNCTION_TYPE) {
1368 MarkMapContents(map); 1439 MarkMapContents(map);
1369 } else { 1440 } else {
1370 marking_deque_.PushBlack(map); 1441 marking_deque_.PushBlack(map);
1371 } 1442 }
1372 } else { 1443 } else {
1373 marking_deque_.PushBlack(object); 1444 marking_deque_.PushBlack(object);
1374 } 1445 }
1375 } 1446 }
1376 1447
1377 1448
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 marking_deque_.PushBlack(descriptors); 1524 marking_deque_.PushBlack(descriptors);
1454 } 1525 }
1455 1526
1456 1527
1457 void MarkCompactCollector::CreateBackPointers() { 1528 void MarkCompactCollector::CreateBackPointers() {
1458 HeapObjectIterator iterator(heap()->map_space()); 1529 HeapObjectIterator iterator(heap()->map_space());
1459 for (HeapObject* next_object = iterator.Next(); 1530 for (HeapObject* next_object = iterator.Next();
1460 next_object != NULL; next_object = iterator.Next()) { 1531 next_object != NULL; next_object = iterator.Next()) {
1461 if (next_object->IsMap()) { // Could also be FreeSpace object on free list. 1532 if (next_object->IsMap()) { // Could also be FreeSpace object on free list.
1462 Map* map = Map::cast(next_object); 1533 Map* map = Map::cast(next_object);
1463 if (map->instance_type() >= FIRST_JS_OBJECT_TYPE && 1534 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
1464 map->instance_type() <= JS_FUNCTION_TYPE) { 1535 if (map->instance_type() >= FIRST_JS_RECEIVER_TYPE) {
1465 map->CreateBackPointers(); 1536 map->CreateBackPointers();
1466 } else { 1537 } else {
1467 ASSERT(map->instance_descriptors() == heap()->empty_descriptor_array()); 1538 ASSERT(map->instance_descriptors() == heap()->empty_descriptor_array());
1468 } 1539 }
1469 } 1540 }
1470 } 1541 }
1471 } 1542 }
1472 1543
1473 1544
1474 // Fill the marking stack with overflowed objects returned by the given 1545 // Fill the marking stack with overflowed objects returned by the given
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
1848 1919
1849 // Repeat host application specific marking to mark unmarked objects 1920 // Repeat host application specific marking to mark unmarked objects
1850 // reachable from the weak roots. 1921 // reachable from the weak roots.
1851 ProcessExternalMarking(); 1922 ProcessExternalMarking();
1852 1923
1853 AfterMarking(); 1924 AfterMarking();
1854 } 1925 }
1855 1926
1856 1927
1857 void MarkCompactCollector::AfterMarking() { 1928 void MarkCompactCollector::AfterMarking() {
1929 // Object literal map caches reference symbols (cache keys) and maps
1930 // (cache values). At this point still useful maps have already been
1931 // marked. Mark the keys for the alive values before we process the
1932 // symbol table.
1933 ProcessMapCaches();
1934
1858 // Prune the symbol table removing all symbols only pointed to by the 1935 // Prune the symbol table removing all symbols only pointed to by the
1859 // symbol table. Cannot use symbol_table() here because the symbol 1936 // symbol table. Cannot use symbol_table() here because the symbol
1860 // table is marked. 1937 // table is marked.
1861 SymbolTable* symbol_table = heap()->symbol_table(); 1938 SymbolTable* symbol_table = heap()->symbol_table();
1862 SymbolTableCleaner v(heap()); 1939 SymbolTableCleaner v(heap());
1863 symbol_table->IterateElements(&v); 1940 symbol_table->IterateElements(&v);
1864 symbol_table->ElementsRemoved(v.PointersRemoved()); 1941 symbol_table->ElementsRemoved(v.PointersRemoved());
1865 heap()->external_string_table_.Iterate(&v); 1942 heap()->external_string_table_.Iterate(&v);
1866 heap()->external_string_table_.CleanUp(); 1943 heap()->external_string_table_.CleanUp();
1867 1944
1868 // Process the weak references. 1945 // Process the weak references.
1869 MarkCompactWeakObjectRetainer mark_compact_object_retainer; 1946 MarkCompactWeakObjectRetainer mark_compact_object_retainer;
1870 heap()->ProcessWeakReferences(&mark_compact_object_retainer); 1947 heap()->ProcessWeakReferences(&mark_compact_object_retainer);
1871 1948
1872 // Remove object groups after marking phase. 1949 // Remove object groups after marking phase.
1873 heap()->isolate()->global_handles()->RemoveObjectGroups(); 1950 heap()->isolate()->global_handles()->RemoveObjectGroups();
1874 heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); 1951 heap()->isolate()->global_handles()->RemoveImplicitRefGroups();
1875 1952
1876 // Flush code from collected candidates. 1953 // Flush code from collected candidates.
1877 if (is_code_flushing_enabled()) { 1954 if (is_code_flushing_enabled()) {
1878 code_flusher_->ProcessCandidates(); 1955 code_flusher_->ProcessCandidates();
1879 } 1956 }
1880 1957
1881 // Clean up dead objects from the runtime profiler. 1958 // Clean up dead objects from the runtime profiler.
1882 heap()->isolate()->runtime_profiler()->RemoveDeadSamples(); 1959 heap()->isolate()->runtime_profiler()->RemoveDeadSamples();
1883 } 1960 }
1884 1961
1885 1962
1963 void MarkCompactCollector::ProcessMapCaches() {
1964 Object* raw_context = heap()->global_contexts_list_;
1965 while (raw_context != heap()->undefined_value()) {
1966 Context* context = reinterpret_cast<Context*>(raw_context);
1967 if (IsMarked(context)) {
1968 HeapObject* raw_map_cache =
1969 HeapObject::cast(context->get(Context::MAP_CACHE_INDEX));
1970 // A map cache may be reachable from the stack. In this case
1971 // it's already transitively marked and it's too late to clean
1972 // up its parts.
1973 if (!IsMarked(raw_map_cache) &&
1974 raw_map_cache != heap()->undefined_value()) {
1975 MapCache* map_cache = reinterpret_cast<MapCache*>(raw_map_cache);
1976 int existing_elements = map_cache->NumberOfElements();
1977 int used_elements = 0;
1978 for (int i = MapCache::kElementsStartIndex;
1979 i < map_cache->length();
1980 i += MapCache::kEntrySize) {
1981 Object* raw_key = map_cache->get(i);
1982 if (raw_key == heap()->undefined_value() ||
1983 raw_key == heap()->null_value()) continue;
1984 STATIC_ASSERT(MapCache::kEntrySize == 2);
1985 Object* raw_map = map_cache->get(i + 1);
1986 if (raw_map->IsHeapObject() && IsMarked(raw_map)) {
1987 ++used_elements;
1988 } else {
1989 // Delete useless entries with unmarked maps.
1990 ASSERT(raw_map->IsMap());
1991 map_cache->set_null_unchecked(heap(), i);
1992 map_cache->set_null_unchecked(heap(), i + 1);
1993 }
1994 }
1995 if (used_elements == 0) {
1996 context->set(Context::MAP_CACHE_INDEX, heap()->undefined_value());
1997 } else {
1998 // Note: we don't actually shrink the cache here to avoid
1999 // extra complexity during GC. We rely on subsequent cache
2000 // usages (EnsureCapacity) to do this.
2001 map_cache->ElementsRemoved(existing_elements - used_elements);
2002 MarkBit map_cache_markbit = Marking::MarkBitFrom(map_cache);
2003 MarkObject(map_cache, map_cache_markbit);
2004 }
2005 }
2006 }
2007 // Move to next element in the list.
2008 raw_context = context->get(Context::NEXT_CONTEXT_LINK);
2009 }
2010 ProcessMarkingDeque();
2011 }
2012
2013
1886 #ifdef DEBUG 2014 #ifdef DEBUG
1887 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { 2015 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) {
1888 live_bytes_ += obj->Size(); 2016 live_bytes_ += obj->Size();
1889 if (heap()->new_space()->Contains(obj)) { 2017 if (heap()->new_space()->Contains(obj)) {
1890 live_young_objects_size_ += obj->Size(); 2018 live_young_objects_size_ += obj->Size();
1891 } else if (heap()->map_space()->Contains(obj)) { 2019 } else if (heap()->map_space()->Contains(obj)) {
1892 ASSERT(obj->IsMap()); 2020 ASSERT(obj->IsMap());
1893 live_map_objects_size_ += obj->Size(); 2021 live_map_objects_size_ += obj->Size();
1894 } else if (heap()->cell_space()->Contains(obj)) { 2022 } else if (heap()->cell_space()->Contains(obj)) {
1895 ASSERT(obj->IsJSGlobalPropertyCell()); 2023 ASSERT(obj->IsJSGlobalPropertyCell());
(...skipping 26 matching lines...) Expand all
1922 // All of these actions are carried out only on maps of JSObjects 2050 // All of these actions are carried out only on maps of JSObjects
1923 // and related subtypes. 2051 // and related subtypes.
1924 for (HeapObject* obj = map_iterator.Next(); 2052 for (HeapObject* obj = map_iterator.Next();
1925 obj != NULL; obj = map_iterator.Next()) { 2053 obj != NULL; obj = map_iterator.Next()) {
1926 Map* map = reinterpret_cast<Map*>(obj); 2054 Map* map = reinterpret_cast<Map*>(obj);
1927 MarkBit map_mark = Marking::MarkBitFrom(map); 2055 MarkBit map_mark = Marking::MarkBitFrom(map);
1928 if (map->IsFreeSpace()) continue; 2056 if (map->IsFreeSpace()) continue;
1929 2057
1930 ASSERT(map->IsMap()); 2058 ASSERT(map->IsMap());
1931 // Only JSObject and subtypes have map transitions and back pointers. 2059 // Only JSObject and subtypes have map transitions and back pointers.
1932 if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; 2060 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
1933 if (map->instance_type() > JS_FUNCTION_TYPE) continue; 2061 if (map->instance_type() < FIRST_JS_RECEIVER_TYPE) continue;
1934 2062
1935 if (map_mark.Get() && 2063 if (map_mark.Get() &&
1936 map->attached_to_shared_function_info()) { 2064 map->attached_to_shared_function_info()) {
1937 // This map is used for inobject slack tracking and has been detached 2065 // This map is used for inobject slack tracking and has been detached
1938 // from SharedFunctionInfo during the mark phase. 2066 // from SharedFunctionInfo during the mark phase.
1939 // Since it survived the GC, reattach it now. 2067 // Since it survived the GC, reattach it now.
1940 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); 2068 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map);
1941 } 2069 }
1942 2070
1943 // Clear dead prototype transitions. 2071 // Clear dead prototype transitions.
2072 int number_of_transitions = map->NumberOfProtoTransitions();
1944 FixedArray* prototype_transitions = map->prototype_transitions(); 2073 FixedArray* prototype_transitions = map->prototype_transitions();
1945 if (prototype_transitions->length() > 0) {
1946 int finger = Smi::cast(prototype_transitions->get(0))->value();
1947 int new_finger = 1;
1948 for (int i = 1; i < finger; i += 2) {
1949 HeapObject* prototype = HeapObject::cast(prototype_transitions->get(i));
1950 Map* cached_map = Map::cast(prototype_transitions->get(i + 1));
1951 MarkBit prototype_mark = Marking::MarkBitFrom(prototype);
1952 MarkBit cached_map_mark = Marking::MarkBitFrom(cached_map);
1953 if (prototype_mark.Get() && cached_map_mark.Get()) {
1954 if (new_finger != i) {
1955 prototype_transitions->set_unchecked(heap_,
1956 new_finger,
1957 prototype,
1958 UPDATE_WRITE_BARRIER);
1959 prototype_transitions->set_unchecked(heap_,
1960 new_finger + 1,
1961 cached_map,
1962 SKIP_WRITE_BARRIER);
1963 }
1964 2074
1965 Object** prototype_slot = 2075 int new_number_of_transitions = 0;
1966 prototype_transitions->data_start() + new_finger; 2076 const int header = Map::kProtoTransitionHeaderSize;
1967 RecordSlot(prototype_slot, prototype_slot, prototype); 2077 const int proto_offset =
1968 new_finger += 2; 2078 header + Map::kProtoTransitionPrototypeOffset;
2079 const int map_offset = header + Map::kProtoTransitionMapOffset;
2080 const int step = Map::kProtoTransitionElementsPerEntry;
2081 for (int i = 0; i < number_of_transitions; i++) {
2082 Object* prototype = prototype_transitions->get(proto_offset + i * step);
2083 Object* cached_map = prototype_transitions->get(map_offset + i * step);
2084 if (IsMarked(prototype) && IsMarked(cached_map)) {
2085 if (new_number_of_transitions != i) {
2086 prototype_transitions->set_unchecked(
2087 heap_,
2088 proto_offset + new_number_of_transitions * step,
2089 prototype,
2090 UPDATE_WRITE_BARRIER);
2091 prototype_transitions->set_unchecked(
2092 heap_,
2093 map_offset + new_number_of_transitions * step,
2094 cached_map,
2095 SKIP_WRITE_BARRIER);
1969 } 2096 }
2097 new_number_of_transitions++;
1970 } 2098 }
1971 2099
1972 // Fill slots that became free with undefined value. 2100 // Fill slots that became free with undefined value.
1973 Object* undefined = heap()->undefined_value(); 2101 Object* undefined = heap()->undefined_value();
1974 for (int i = new_finger; i < finger; i++) { 2102 for (int i = new_number_of_transitions * step;
2103 i < number_of_transitions * step;
2104 i++) {
1975 prototype_transitions->set_unchecked(heap_, 2105 prototype_transitions->set_unchecked(heap_,
1976 i, 2106 header + i,
1977 undefined, 2107 undefined,
1978 SKIP_WRITE_BARRIER); 2108 SKIP_WRITE_BARRIER);
1979 2109
1980 // TODO(gc) we should not evacuate first page of data space. 2110 // TODO(gc) we should not evacuate first page of data space.
1981 // but we are doing it now to increase coverage. 2111 // but we are doing it now to increase coverage.
1982 Object** undefined_slot = 2112 Object** undefined_slot =
1983 prototype_transitions->data_start() + i; 2113 prototype_transitions->data_start() + i;
1984 RecordSlot(undefined_slot, undefined_slot, undefined); 2114 RecordSlot(undefined_slot, undefined_slot, undefined);
1985 } 2115 }
1986 prototype_transitions->set_unchecked(0, Smi::FromInt(new_finger)); 2116 map->SetNumberOfProtoTransitions(new_number_of_transitions);
1987 } 2117 }
1988 2118
1989 // Follow the chain of back pointers to find the prototype. 2119 // Follow the chain of back pointers to find the prototype.
1990 Map* current = map; 2120 Map* current = map;
1991 while (current->IsMap()) { 2121 while (current->IsMap()) {
1992 current = reinterpret_cast<Map*>(current->prototype()); 2122 current = reinterpret_cast<Map*>(current->prototype());
1993 ASSERT(current->IsHeapObject()); 2123 ASSERT(current->IsHeapObject());
1994 } 2124 }
1995 Object* real_prototype = current; 2125 Object* real_prototype = current;
1996 2126
(...skipping 1193 matching lines...) Expand 10 before | Expand all | Expand 10 after
3190 while (buffer != NULL) { 3320 while (buffer != NULL) {
3191 SlotsBuffer* next_buffer = buffer->next(); 3321 SlotsBuffer* next_buffer = buffer->next();
3192 DeallocateBuffer(buffer); 3322 DeallocateBuffer(buffer);
3193 buffer = next_buffer; 3323 buffer = next_buffer;
3194 } 3324 }
3195 *buffer_address = NULL; 3325 *buffer_address = NULL;
3196 } 3326 }
3197 3327
3198 3328
3199 } } // namespace v8::internal 3329 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mark-compact.h ('k') | src/messages.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698