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 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
931 // page dirty marks. Therefore, we only replace the string with its left | 931 // page dirty marks. Therefore, we only replace the string with its left |
932 // substring when page dirty marks do not change. | 932 // substring when page dirty marks do not change. |
933 Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first(); | 933 Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first(); |
934 if (!heap->InNewSpace(object) && heap->InNewSpace(first)) return object; | 934 if (!heap->InNewSpace(object) && heap->InNewSpace(first)) return object; |
935 | 935 |
936 *p = first; | 936 *p = first; |
937 return HeapObject::cast(first); | 937 return HeapObject::cast(first); |
938 } | 938 } |
939 | 939 |
940 | 940 |
941 class StaticMarkingVisitor : public StaticVisitorBase { | 941 class MarkCompactMarkingVisitor |
| 942 : public StaticMarkingVisitor<MarkCompactMarkingVisitor> { |
942 public: | 943 public: |
943 static inline void IterateBody(Map* map, HeapObject* obj) { | |
944 table_.GetVisitor(map)(map, obj); | |
945 } | |
946 | |
947 template<int id> | |
948 class ObjectStatsTracker { | |
949 public: | |
950 static inline void Visit(Map* map, HeapObject* obj); | |
951 }; | |
952 | |
953 static void Initialize(); | 944 static void Initialize(); |
954 | 945 |
955 INLINE(static void VisitPointer(Heap* heap, Object** p)) { | 946 INLINE(static void VisitPointer(Heap* heap, Object** p)) { |
956 MarkObjectByPointer(heap->mark_compact_collector(), p, p); | 947 MarkObjectByPointer(heap->mark_compact_collector(), p, p); |
957 } | 948 } |
958 | 949 |
959 INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { | 950 INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { |
960 // Mark all objects pointed to in [start, end). | 951 // Mark all objects pointed to in [start, end). |
961 const int kMinRangeForMarkingRecursion = 64; | 952 const int kMinRangeForMarkingRecursion = 64; |
962 if (end - start >= kMinRangeForMarkingRecursion) { | 953 if (end - start >= kMinRangeForMarkingRecursion) { |
963 if (VisitUnmarkedObjects(heap, start, end)) return; | 954 if (VisitUnmarkedObjects(heap, start, end)) return; |
964 // We are close to a stack overflow, so just mark the objects. | 955 // We are close to a stack overflow, so just mark the objects. |
965 } | 956 } |
966 MarkCompactCollector* collector = heap->mark_compact_collector(); | 957 MarkCompactCollector* collector = heap->mark_compact_collector(); |
967 for (Object** p = start; p < end; p++) { | 958 for (Object** p = start; p < end; p++) { |
968 MarkObjectByPointer(collector, start, p); | 959 MarkObjectByPointer(collector, start, p); |
969 } | 960 } |
970 } | 961 } |
971 | 962 |
972 static void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo) { | 963 INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { |
973 ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL); | 964 MarkBit mark = Marking::MarkBitFrom(object); |
974 JSGlobalPropertyCell* cell = | 965 heap->mark_compact_collector()->MarkObject(object, mark); |
975 JSGlobalPropertyCell::cast(rinfo->target_cell()); | |
976 MarkBit mark = Marking::MarkBitFrom(cell); | |
977 heap->mark_compact_collector()->MarkObject(cell, mark); | |
978 } | 966 } |
979 | 967 |
980 static inline void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo) { | 968 static inline void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo) { |
981 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 969 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
982 // TODO(mstarzinger): We do not short-circuit cons strings here, verify | 970 // TODO(mstarzinger): We do not short-circuit cons strings here, verify |
983 // that there can be no such embedded pointers and add assertion here. | 971 // that there can be no such embedded pointers and add assertion here. |
984 HeapObject* object = HeapObject::cast(rinfo->target_object()); | 972 HeapObject* object = HeapObject::cast(rinfo->target_object()); |
985 heap->mark_compact_collector()->RecordRelocSlot(rinfo, object); | 973 heap->mark_compact_collector()->RecordRelocSlot(rinfo, object); |
986 MarkBit mark = Marking::MarkBitFrom(object); | 974 MarkObject(heap, object); |
987 heap->mark_compact_collector()->MarkObject(object, mark); | |
988 } | 975 } |
989 | 976 |
990 static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) { | 977 static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo) { |
991 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); | 978 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
992 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 979 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
993 if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub() | 980 if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub() |
994 && (target->ic_state() == MEGAMORPHIC || | 981 && (target->ic_state() == MEGAMORPHIC || |
995 heap->mark_compact_collector()->flush_monomorphic_ics_ || | 982 heap->mark_compact_collector()->flush_monomorphic_ics_ || |
996 target->ic_age() != heap->global_ic_age())) { | 983 target->ic_age() != heap->global_ic_age())) { |
997 IC::Clear(rinfo->pc()); | 984 IC::Clear(rinfo->pc()); |
998 target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 985 target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
999 } | 986 } |
1000 MarkBit code_mark = Marking::MarkBitFrom(target); | |
1001 heap->mark_compact_collector()->MarkObject(target, code_mark); | |
1002 heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); | 987 heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); |
1003 } | 988 MarkObject(heap, target); |
1004 | |
1005 static inline void VisitDebugTarget(Heap* heap, RelocInfo* rinfo) { | |
1006 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && | |
1007 rinfo->IsPatchedReturnSequence()) || | |
1008 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | |
1009 rinfo->IsPatchedDebugBreakSlotSequence())); | |
1010 Code* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | |
1011 MarkBit code_mark = Marking::MarkBitFrom(target); | |
1012 heap->mark_compact_collector()->MarkObject(target, code_mark); | |
1013 heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); | |
1014 } | 989 } |
1015 | 990 |
1016 // Mark object pointed to by p. | 991 // Mark object pointed to by p. |
1017 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, | 992 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, |
1018 Object** anchor_slot, | 993 Object** anchor_slot, |
1019 Object** p)) { | 994 Object** p)) { |
1020 if (!(*p)->IsHeapObject()) return; | 995 if (!(*p)->IsHeapObject()) return; |
1021 HeapObject* object = ShortCircuitConsString(p); | 996 HeapObject* object = ShortCircuitConsString(p); |
1022 collector->RecordSlot(anchor_slot, p, object); | 997 collector->RecordSlot(anchor_slot, p, object); |
1023 MarkBit mark = Marking::MarkBitFrom(object); | 998 MarkBit mark = Marking::MarkBitFrom(object); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1058 if (!o->IsHeapObject()) continue; | 1033 if (!o->IsHeapObject()) continue; |
1059 collector->RecordSlot(start, p, o); | 1034 collector->RecordSlot(start, p, o); |
1060 HeapObject* obj = HeapObject::cast(o); | 1035 HeapObject* obj = HeapObject::cast(o); |
1061 MarkBit mark = Marking::MarkBitFrom(obj); | 1036 MarkBit mark = Marking::MarkBitFrom(obj); |
1062 if (mark.Get()) continue; | 1037 if (mark.Get()) continue; |
1063 VisitUnmarkedObject(collector, obj); | 1038 VisitUnmarkedObject(collector, obj); |
1064 } | 1039 } |
1065 return true; | 1040 return true; |
1066 } | 1041 } |
1067 | 1042 |
1068 static inline void VisitExternalReference(Address* p) { } | 1043 static void VisitCode(Map* map, HeapObject* object) { |
1069 static inline void VisitExternalReference(RelocInfo* rinfo) { } | 1044 Heap* heap = map->GetHeap(); |
1070 static inline void VisitRuntimeEntry(RelocInfo* rinfo) { } | 1045 Code* code = reinterpret_cast<Code*>(object); |
1071 | 1046 if (FLAG_cleanup_code_caches_at_gc) { |
1072 private: | 1047 code->ClearTypeFeedbackCells(heap); |
1073 class DataObjectVisitor { | |
1074 public: | |
1075 template<int size> | |
1076 static void VisitSpecialized(Map* map, HeapObject* object) { | |
1077 } | 1048 } |
1078 | 1049 code->CodeIterateBody<MarkCompactMarkingVisitor>(heap); |
1079 static void Visit(Map* map, HeapObject* object) { | 1050 } |
1080 } | |
1081 }; | |
1082 | |
1083 typedef FlexibleBodyVisitor<StaticMarkingVisitor, | |
1084 JSObject::BodyDescriptor, | |
1085 void> JSObjectVisitor; | |
1086 | |
1087 typedef FlexibleBodyVisitor<StaticMarkingVisitor, | |
1088 StructBodyDescriptor, | |
1089 void> StructObjectVisitor; | |
1090 | 1051 |
1091 static void VisitJSWeakMap(Map* map, HeapObject* object) { | 1052 static void VisitJSWeakMap(Map* map, HeapObject* object) { |
1092 MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); | 1053 MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); |
1093 JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(object); | 1054 JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(object); |
1094 | 1055 |
1095 // Enqueue weak map in linked list of encountered weak maps. | 1056 // Enqueue weak map in linked list of encountered weak maps. |
1096 if (weak_map->next() == Smi::FromInt(0)) { | 1057 if (weak_map->next() == Smi::FromInt(0)) { |
1097 weak_map->set_next(collector->encountered_weak_maps()); | 1058 weak_map->set_next(collector->encountered_weak_maps()); |
1098 collector->set_encountered_weak_maps(weak_map); | 1059 collector->set_encountered_weak_maps(weak_map); |
1099 } | 1060 } |
1100 | 1061 |
1101 // Skip visiting the backing hash table containing the mappings. | 1062 // Skip visiting the backing hash table containing the mappings. |
1102 int object_size = JSWeakMap::BodyDescriptor::SizeOf(map, object); | 1063 int object_size = JSWeakMap::BodyDescriptor::SizeOf(map, object); |
1103 BodyVisitorBase<StaticMarkingVisitor>::IteratePointers( | 1064 BodyVisitorBase<MarkCompactMarkingVisitor>::IteratePointers( |
1104 map->GetHeap(), | 1065 map->GetHeap(), |
1105 object, | 1066 object, |
1106 JSWeakMap::BodyDescriptor::kStartOffset, | 1067 JSWeakMap::BodyDescriptor::kStartOffset, |
1107 JSWeakMap::kTableOffset); | 1068 JSWeakMap::kTableOffset); |
1108 BodyVisitorBase<StaticMarkingVisitor>::IteratePointers( | 1069 BodyVisitorBase<MarkCompactMarkingVisitor>::IteratePointers( |
1109 map->GetHeap(), | 1070 map->GetHeap(), |
1110 object, | 1071 object, |
1111 JSWeakMap::kTableOffset + kPointerSize, | 1072 JSWeakMap::kTableOffset + kPointerSize, |
1112 object_size); | 1073 object_size); |
1113 | 1074 |
1114 // Mark the backing hash table without pushing it on the marking stack. | 1075 // Mark the backing hash table without pushing it on the marking stack. |
1115 Object* table_object = weak_map->table(); | 1076 Object* table_object = weak_map->table(); |
1116 if (!table_object->IsHashTable()) return; | 1077 if (!table_object->IsHashTable()) return; |
1117 ObjectHashTable* table = ObjectHashTable::cast(table_object); | 1078 ObjectHashTable* table = ObjectHashTable::cast(table_object); |
1118 Object** table_slot = | 1079 Object** table_slot = |
1119 HeapObject::RawField(weak_map, JSWeakMap::kTableOffset); | 1080 HeapObject::RawField(weak_map, JSWeakMap::kTableOffset); |
1120 MarkBit table_mark = Marking::MarkBitFrom(table); | 1081 MarkBit table_mark = Marking::MarkBitFrom(table); |
1121 collector->RecordSlot(table_slot, table_slot, table); | 1082 collector->RecordSlot(table_slot, table_slot, table); |
1122 if (!table_mark.Get()) collector->SetMark(table, table_mark); | 1083 if (!table_mark.Get()) collector->SetMark(table, table_mark); |
1123 // Recording the map slot can be skipped, because maps are not compacted. | 1084 // Recording the map slot can be skipped, because maps are not compacted. |
1124 collector->MarkObject(table->map(), Marking::MarkBitFrom(table->map())); | 1085 collector->MarkObject(table->map(), Marking::MarkBitFrom(table->map())); |
1125 ASSERT(MarkCompactCollector::IsMarked(table->map())); | 1086 ASSERT(MarkCompactCollector::IsMarked(table->map())); |
1126 } | 1087 } |
1127 | 1088 |
1128 static void VisitCode(Map* map, HeapObject* object) { | 1089 private: |
1129 Heap* heap = map->GetHeap(); | 1090 template<int id> |
1130 Code* code = reinterpret_cast<Code*>(object); | 1091 static inline void TrackObjectStatsAndVisit(Map* map, HeapObject* obj); |
1131 if (FLAG_cleanup_code_caches_at_gc) { | |
1132 code->ClearTypeFeedbackCells(heap); | |
1133 } | |
1134 code->CodeIterateBody<StaticMarkingVisitor>(heap); | |
1135 } | |
1136 | 1092 |
1137 // Code flushing support. | 1093 // Code flushing support. |
1138 | 1094 |
1139 // How many collections newly compiled code object will survive before being | 1095 // How many collections newly compiled code object will survive before being |
1140 // flushed. | 1096 // flushed. |
1141 static const int kCodeAgeThreshold = 5; | 1097 static const int kCodeAgeThreshold = 5; |
1142 | 1098 |
1143 static const int kRegExpCodeThreshold = 5; | 1099 static const int kRegExpCodeThreshold = 5; |
1144 | 1100 |
1145 inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) { | 1101 inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1240 | 1196 |
1241 static inline bool IsValidNotBuiltinContext(Object* ctx) { | 1197 static inline bool IsValidNotBuiltinContext(Object* ctx) { |
1242 return ctx->IsContext() && | 1198 return ctx->IsContext() && |
1243 !Context::cast(ctx)->global()->IsJSBuiltinsObject(); | 1199 !Context::cast(ctx)->global()->IsJSBuiltinsObject(); |
1244 } | 1200 } |
1245 | 1201 |
1246 | 1202 |
1247 static void VisitSharedFunctionInfoGeneric(Map* map, HeapObject* object) { | 1203 static void VisitSharedFunctionInfoGeneric(Map* map, HeapObject* object) { |
1248 SharedFunctionInfo::cast(object)->BeforeVisitingPointers(); | 1204 SharedFunctionInfo::cast(object)->BeforeVisitingPointers(); |
1249 | 1205 |
1250 FixedBodyVisitor<StaticMarkingVisitor, | 1206 FixedBodyVisitor<MarkCompactMarkingVisitor, |
1251 SharedFunctionInfo::BodyDescriptor, | 1207 SharedFunctionInfo::BodyDescriptor, |
1252 void>::Visit(map, object); | 1208 void>::Visit(map, object); |
1253 } | 1209 } |
1254 | 1210 |
1255 | 1211 |
1256 static void UpdateRegExpCodeAgeAndFlush(Heap* heap, | 1212 static void UpdateRegExpCodeAgeAndFlush(Heap* heap, |
1257 JSRegExp* re, | 1213 JSRegExp* re, |
1258 bool is_ascii) { | 1214 bool is_ascii) { |
1259 // Make sure that the fixed array is in fact initialized on the RegExp. | 1215 // Make sure that the fixed array is in fact initialized on the RegExp. |
1260 // We could potentially trigger a GC when initializing the RegExp. | 1216 // We could potentially trigger a GC when initializing the RegExp. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 | 1264 |
1309 // Works by setting the current sweep_generation (as a smi) in the | 1265 // Works by setting the current sweep_generation (as a smi) in the |
1310 // code object place in the data array of the RegExp and keeps a copy | 1266 // code object place in the data array of the RegExp and keeps a copy |
1311 // around that can be reinstated if we reuse the RegExp before flushing. | 1267 // around that can be reinstated if we reuse the RegExp before flushing. |
1312 // If we did not use the code for kRegExpCodeThreshold mark sweep GCs | 1268 // If we did not use the code for kRegExpCodeThreshold mark sweep GCs |
1313 // we flush the code. | 1269 // we flush the code. |
1314 static void VisitRegExpAndFlushCode(Map* map, HeapObject* object) { | 1270 static void VisitRegExpAndFlushCode(Map* map, HeapObject* object) { |
1315 Heap* heap = map->GetHeap(); | 1271 Heap* heap = map->GetHeap(); |
1316 MarkCompactCollector* collector = heap->mark_compact_collector(); | 1272 MarkCompactCollector* collector = heap->mark_compact_collector(); |
1317 if (!collector->is_code_flushing_enabled()) { | 1273 if (!collector->is_code_flushing_enabled()) { |
1318 VisitJSRegExpFields(map, object); | 1274 VisitJSRegExp(map, object); |
1319 return; | 1275 return; |
1320 } | 1276 } |
1321 JSRegExp* re = reinterpret_cast<JSRegExp*>(object); | 1277 JSRegExp* re = reinterpret_cast<JSRegExp*>(object); |
1322 // Flush code or set age on both ASCII and two byte code. | 1278 // Flush code or set age on both ASCII and two byte code. |
1323 UpdateRegExpCodeAgeAndFlush(heap, re, true); | 1279 UpdateRegExpCodeAgeAndFlush(heap, re, true); |
1324 UpdateRegExpCodeAgeAndFlush(heap, re, false); | 1280 UpdateRegExpCodeAgeAndFlush(heap, re, false); |
1325 // Visit the fields of the RegExp, including the updated FixedArray. | 1281 // Visit the fields of the RegExp, including the updated FixedArray. |
1326 VisitJSRegExpFields(map, object); | 1282 VisitJSRegExp(map, object); |
1327 } | 1283 } |
1328 | 1284 |
1329 | 1285 |
1330 static void VisitSharedFunctionInfoAndFlushCode(Map* map, | 1286 static void VisitSharedFunctionInfoAndFlushCode(Map* map, |
1331 HeapObject* object) { | 1287 HeapObject* object) { |
1332 Heap* heap = map->GetHeap(); | 1288 Heap* heap = map->GetHeap(); |
1333 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object); | 1289 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(object); |
1334 if (shared->ic_age() != heap->global_ic_age()) { | 1290 if (shared->ic_age() != heap->global_ic_age()) { |
1335 shared->ResetForNewContext(heap->global_ic_age()); | 1291 shared->ResetForNewContext(heap->global_ic_age()); |
1336 } | 1292 } |
(...skipping 18 matching lines...) Expand all Loading... |
1355 known_flush_code_candidate = IsFlushable(heap, shared); | 1311 known_flush_code_candidate = IsFlushable(heap, shared); |
1356 if (known_flush_code_candidate) { | 1312 if (known_flush_code_candidate) { |
1357 heap->mark_compact_collector()->code_flusher()->AddCandidate(shared); | 1313 heap->mark_compact_collector()->code_flusher()->AddCandidate(shared); |
1358 } | 1314 } |
1359 } | 1315 } |
1360 | 1316 |
1361 VisitSharedFunctionInfoFields(heap, object, known_flush_code_candidate); | 1317 VisitSharedFunctionInfoFields(heap, object, known_flush_code_candidate); |
1362 } | 1318 } |
1363 | 1319 |
1364 | 1320 |
1365 static void VisitCodeEntry(Heap* heap, Address entry_address) { | |
1366 Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); | |
1367 MarkBit mark = Marking::MarkBitFrom(code); | |
1368 heap->mark_compact_collector()->MarkObject(code, mark); | |
1369 heap->mark_compact_collector()-> | |
1370 RecordCodeEntrySlot(entry_address, code); | |
1371 } | |
1372 | |
1373 static void VisitGlobalContext(Map* map, HeapObject* object) { | |
1374 FixedBodyVisitor<StaticMarkingVisitor, | |
1375 Context::MarkCompactBodyDescriptor, | |
1376 void>::Visit(map, object); | |
1377 | |
1378 MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); | |
1379 for (int idx = Context::FIRST_WEAK_SLOT; | |
1380 idx < Context::GLOBAL_CONTEXT_SLOTS; | |
1381 ++idx) { | |
1382 Object** slot = | |
1383 HeapObject::RawField(object, FixedArray::OffsetOfElementAt(idx)); | |
1384 collector->RecordSlot(slot, slot, *slot); | |
1385 } | |
1386 } | |
1387 | |
1388 static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) { | 1321 static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) { |
1389 Heap* heap = map->GetHeap(); | 1322 Heap* heap = map->GetHeap(); |
1390 MarkCompactCollector* collector = heap->mark_compact_collector(); | 1323 MarkCompactCollector* collector = heap->mark_compact_collector(); |
1391 if (!collector->is_code_flushing_enabled()) { | 1324 if (!collector->is_code_flushing_enabled()) { |
1392 VisitJSFunction(map, object); | 1325 VisitJSFunction(map, object); |
1393 return; | 1326 return; |
1394 } | 1327 } |
1395 | 1328 |
1396 JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object); | 1329 JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object); |
1397 // The function must have a valid context and not be a builtin. | 1330 // The function must have a valid context and not be a builtin. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1459 } | 1392 } |
1460 | 1393 |
1461 VisitPointers( | 1394 VisitPointers( |
1462 heap, | 1395 heap, |
1463 HeapObject::RawField(object, | 1396 HeapObject::RawField(object, |
1464 JSFunction::kCodeEntryOffset + kPointerSize), | 1397 JSFunction::kCodeEntryOffset + kPointerSize), |
1465 HeapObject::RawField(object, | 1398 HeapObject::RawField(object, |
1466 JSFunction::kNonWeakFieldsEndOffset)); | 1399 JSFunction::kNonWeakFieldsEndOffset)); |
1467 } | 1400 } |
1468 | 1401 |
1469 static inline void VisitJSRegExpFields(Map* map, | |
1470 HeapObject* object) { | |
1471 int last_property_offset = | |
1472 JSRegExp::kSize + kPointerSize * map->inobject_properties(); | |
1473 VisitPointers(map->GetHeap(), | |
1474 SLOT_ADDR(object, JSRegExp::kPropertiesOffset), | |
1475 SLOT_ADDR(object, last_property_offset)); | |
1476 } | |
1477 | |
1478 | 1402 |
1479 static void VisitSharedFunctionInfoFields(Heap* heap, | 1403 static void VisitSharedFunctionInfoFields(Heap* heap, |
1480 HeapObject* object, | 1404 HeapObject* object, |
1481 bool flush_code_candidate) { | 1405 bool flush_code_candidate) { |
1482 VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kNameOffset)); | 1406 VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kNameOffset)); |
1483 | 1407 |
1484 if (!flush_code_candidate) { | 1408 if (!flush_code_candidate) { |
1485 VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kCodeOffset)); | 1409 VisitPointer(heap, SLOT_ADDR(object, SharedFunctionInfo::kCodeOffset)); |
1486 } | 1410 } |
1487 | 1411 |
1488 VisitPointers(heap, | 1412 VisitPointers(heap, |
1489 SLOT_ADDR(object, SharedFunctionInfo::kOptimizedCodeMapOffset), | 1413 SLOT_ADDR(object, SharedFunctionInfo::kOptimizedCodeMapOffset), |
1490 SLOT_ADDR(object, SharedFunctionInfo::kSize)); | 1414 SLOT_ADDR(object, SharedFunctionInfo::kSize)); |
1491 } | 1415 } |
1492 | 1416 |
1493 #undef SLOT_ADDR | 1417 #undef SLOT_ADDR |
1494 | 1418 |
1495 typedef void (*Callback)(Map* map, HeapObject* object); | |
1496 | |
1497 static VisitorDispatchTable<Callback> table_; | |
1498 static VisitorDispatchTable<Callback> non_count_table_; | 1419 static VisitorDispatchTable<Callback> non_count_table_; |
1499 }; | 1420 }; |
1500 | 1421 |
1501 | 1422 |
1502 template<int id> | 1423 template<int id> |
1503 void StaticMarkingVisitor::ObjectStatsTracker<id>::Visit( | 1424 void MarkCompactMarkingVisitor::TrackObjectStatsAndVisit(Map* map, |
1504 Map* map, HeapObject* obj) { | 1425 HeapObject* obj) { |
1505 Heap* heap = map->GetHeap(); | 1426 Heap* heap = map->GetHeap(); |
1506 int object_size = obj->Size(); | 1427 int object_size = obj->Size(); |
1507 heap->RecordObjectStats(map->instance_type(), -1, object_size); | 1428 heap->RecordObjectStats(map->instance_type(), -1, object_size); |
1508 non_count_table_.GetVisitorById(static_cast<VisitorId>(id))(map, obj); | 1429 non_count_table_.GetVisitorById(static_cast<VisitorId>(id))(map, obj); |
1509 } | 1430 } |
1510 | 1431 |
1511 | 1432 |
1512 template<> | 1433 template<> |
1513 class StaticMarkingVisitor::ObjectStatsTracker< | 1434 void MarkCompactMarkingVisitor::TrackObjectStatsAndVisit< |
1514 StaticMarkingVisitor::kVisitCode> { | 1435 MarkCompactMarkingVisitor::kVisitCode>(Map* map, HeapObject* obj) { |
1515 public: | 1436 Heap* heap = map->GetHeap(); |
1516 static inline void Visit(Map* map, HeapObject* obj) { | 1437 int object_size = obj->Size(); |
1517 Heap* heap = map->GetHeap(); | 1438 ASSERT(map->instance_type() == CODE_TYPE); |
1518 int object_size = obj->Size(); | 1439 heap->RecordObjectStats(CODE_TYPE, -1, object_size); |
1519 ASSERT(map->instance_type() == CODE_TYPE); | 1440 heap->RecordObjectStats(CODE_TYPE, Code::cast(obj)->kind(), object_size); |
1520 heap->RecordObjectStats(CODE_TYPE, -1, object_size); | 1441 non_count_table_.GetVisitorById(static_cast<VisitorId>(kVisitCode))(map, obj); |
1521 heap->RecordObjectStats(CODE_TYPE, Code::cast(obj)->kind(), object_size); | 1442 } |
1522 non_count_table_.GetVisitorById( | |
1523 static_cast<VisitorId>(kVisitCode))(map, obj); | |
1524 } | |
1525 }; | |
1526 | 1443 |
1527 | 1444 |
1528 void StaticMarkingVisitor::Initialize() { | 1445 void MarkCompactMarkingVisitor::Initialize() { |
1529 table_.Register(kVisitShortcutCandidate, | 1446 StaticMarkingVisitor<MarkCompactMarkingVisitor>::Initialize(); |
1530 &FixedBodyVisitor<StaticMarkingVisitor, | |
1531 ConsString::BodyDescriptor, | |
1532 void>::Visit); | |
1533 | |
1534 table_.Register(kVisitConsString, | |
1535 &FixedBodyVisitor<StaticMarkingVisitor, | |
1536 ConsString::BodyDescriptor, | |
1537 void>::Visit); | |
1538 | |
1539 table_.Register(kVisitSlicedString, | |
1540 &FixedBodyVisitor<StaticMarkingVisitor, | |
1541 SlicedString::BodyDescriptor, | |
1542 void>::Visit); | |
1543 | |
1544 table_.Register(kVisitFixedArray, | |
1545 &FlexibleBodyVisitor<StaticMarkingVisitor, | |
1546 FixedArray::BodyDescriptor, | |
1547 void>::Visit); | |
1548 | |
1549 table_.Register(kVisitGlobalContext, &VisitGlobalContext); | |
1550 | |
1551 table_.Register(kVisitFixedDoubleArray, DataObjectVisitor::Visit); | |
1552 | |
1553 table_.Register(kVisitByteArray, &DataObjectVisitor::Visit); | |
1554 table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit); | |
1555 table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit); | |
1556 table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit); | |
1557 | |
1558 table_.Register(kVisitJSWeakMap, &VisitJSWeakMap); | |
1559 | |
1560 table_.Register(kVisitOddball, | |
1561 &FixedBodyVisitor<StaticMarkingVisitor, | |
1562 Oddball::BodyDescriptor, | |
1563 void>::Visit); | |
1564 table_.Register(kVisitMap, | |
1565 &FixedBodyVisitor<StaticMarkingVisitor, | |
1566 Map::BodyDescriptor, | |
1567 void>::Visit); | |
1568 | |
1569 table_.Register(kVisitCode, &VisitCode); | |
1570 | 1447 |
1571 table_.Register(kVisitSharedFunctionInfo, | 1448 table_.Register(kVisitSharedFunctionInfo, |
1572 &VisitSharedFunctionInfoAndFlushCode); | 1449 &VisitSharedFunctionInfoAndFlushCode); |
1573 | 1450 |
1574 table_.Register(kVisitJSFunction, | 1451 table_.Register(kVisitJSFunction, |
1575 &VisitJSFunctionAndFlushCode); | 1452 &VisitJSFunctionAndFlushCode); |
1576 | 1453 |
1577 table_.Register(kVisitJSRegExp, | 1454 table_.Register(kVisitJSRegExp, |
1578 &VisitRegExpAndFlushCode); | 1455 &VisitRegExpAndFlushCode); |
1579 | 1456 |
1580 table_.Register(kVisitPropertyCell, | |
1581 &FixedBodyVisitor<StaticMarkingVisitor, | |
1582 JSGlobalPropertyCell::BodyDescriptor, | |
1583 void>::Visit); | |
1584 | |
1585 table_.RegisterSpecializations<DataObjectVisitor, | |
1586 kVisitDataObject, | |
1587 kVisitDataObjectGeneric>(); | |
1588 | |
1589 table_.RegisterSpecializations<JSObjectVisitor, | |
1590 kVisitJSObject, | |
1591 kVisitJSObjectGeneric>(); | |
1592 | |
1593 table_.RegisterSpecializations<StructObjectVisitor, | |
1594 kVisitStruct, | |
1595 kVisitStructGeneric>(); | |
1596 | |
1597 if (FLAG_track_gc_object_stats) { | 1457 if (FLAG_track_gc_object_stats) { |
1598 // Copy the visitor table to make call-through possible. | 1458 // Copy the visitor table to make call-through possible. |
1599 non_count_table_.CopyFrom(&table_); | 1459 non_count_table_.CopyFrom(&table_); |
1600 #define VISITOR_ID_COUNT_FUNCTION(id) \ | 1460 #define VISITOR_ID_COUNT_FUNCTION(id) \ |
1601 table_.Register(kVisit##id, ObjectStatsTracker<kVisit##id>::Visit); | 1461 table_.Register(kVisit##id, TrackObjectStatsAndVisit<kVisit##id>); |
1602 VISITOR_ID_LIST(VISITOR_ID_COUNT_FUNCTION) | 1462 VISITOR_ID_LIST(VISITOR_ID_COUNT_FUNCTION) |
1603 #undef VISITOR_ID_COUNT_FUNCTION | 1463 #undef VISITOR_ID_COUNT_FUNCTION |
1604 } | 1464 } |
1605 } | 1465 } |
1606 | 1466 |
1607 | 1467 |
1608 VisitorDispatchTable<StaticMarkingVisitor::Callback> | 1468 VisitorDispatchTable<MarkCompactMarkingVisitor::Callback> |
1609 StaticMarkingVisitor::table_; | 1469 MarkCompactMarkingVisitor::non_count_table_; |
1610 VisitorDispatchTable<StaticMarkingVisitor::Callback> | |
1611 StaticMarkingVisitor::non_count_table_; | |
1612 | 1470 |
1613 | 1471 |
1614 class MarkingVisitor : public ObjectVisitor { | 1472 class MarkingVisitor : public ObjectVisitor { |
1615 public: | 1473 public: |
1616 explicit MarkingVisitor(Heap* heap) : heap_(heap) { } | 1474 explicit MarkingVisitor(Heap* heap) : heap_(heap) { } |
1617 | 1475 |
1618 void VisitPointer(Object** p) { | 1476 void VisitPointer(Object** p) { |
1619 StaticMarkingVisitor::VisitPointer(heap_, p); | 1477 MarkCompactMarkingVisitor::VisitPointer(heap_, p); |
1620 } | 1478 } |
1621 | 1479 |
1622 void VisitPointers(Object** start, Object** end) { | 1480 void VisitPointers(Object** start, Object** end) { |
1623 StaticMarkingVisitor::VisitPointers(heap_, start, end); | 1481 MarkCompactMarkingVisitor::VisitPointers(heap_, start, end); |
1624 } | 1482 } |
1625 | 1483 |
1626 private: | 1484 private: |
1627 Heap* heap_; | 1485 Heap* heap_; |
1628 }; | 1486 }; |
1629 | 1487 |
1630 | 1488 |
1631 class CodeMarkingVisitor : public ThreadVisitor { | 1489 class CodeMarkingVisitor : public ThreadVisitor { |
1632 public: | 1490 public: |
1633 explicit CodeMarkingVisitor(MarkCompactCollector* collector) | 1491 explicit CodeMarkingVisitor(MarkCompactCollector* collector) |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1772 MarkBit mark_bit = Marking::MarkBitFrom(object); | 1630 MarkBit mark_bit = Marking::MarkBitFrom(object); |
1773 if (mark_bit.Get()) return; | 1631 if (mark_bit.Get()) return; |
1774 | 1632 |
1775 Map* map = object->map(); | 1633 Map* map = object->map(); |
1776 // Mark the object. | 1634 // Mark the object. |
1777 collector_->SetMark(object, mark_bit); | 1635 collector_->SetMark(object, mark_bit); |
1778 | 1636 |
1779 // Mark the map pointer and body, and push them on the marking stack. | 1637 // Mark the map pointer and body, and push them on the marking stack. |
1780 MarkBit map_mark = Marking::MarkBitFrom(map); | 1638 MarkBit map_mark = Marking::MarkBitFrom(map); |
1781 collector_->MarkObject(map, map_mark); | 1639 collector_->MarkObject(map, map_mark); |
1782 StaticMarkingVisitor::IterateBody(map, object); | 1640 MarkCompactMarkingVisitor::IterateBody(map, object); |
1783 | 1641 |
1784 // Mark all the objects reachable from the map and body. May leave | 1642 // Mark all the objects reachable from the map and body. May leave |
1785 // overflowed objects in the heap. | 1643 // overflowed objects in the heap. |
1786 collector_->EmptyMarkingDeque(); | 1644 collector_->EmptyMarkingDeque(); |
1787 } | 1645 } |
1788 | 1646 |
1789 MarkCompactCollector* collector_; | 1647 MarkCompactCollector* collector_; |
1790 }; | 1648 }; |
1791 | 1649 |
1792 | 1650 |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2242 while (!marking_deque_.IsEmpty()) { | 2100 while (!marking_deque_.IsEmpty()) { |
2243 HeapObject* object = marking_deque_.Pop(); | 2101 HeapObject* object = marking_deque_.Pop(); |
2244 ASSERT(object->IsHeapObject()); | 2102 ASSERT(object->IsHeapObject()); |
2245 ASSERT(heap()->Contains(object)); | 2103 ASSERT(heap()->Contains(object)); |
2246 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); | 2104 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); |
2247 | 2105 |
2248 Map* map = object->map(); | 2106 Map* map = object->map(); |
2249 MarkBit map_mark = Marking::MarkBitFrom(map); | 2107 MarkBit map_mark = Marking::MarkBitFrom(map); |
2250 MarkObject(map, map_mark); | 2108 MarkObject(map, map_mark); |
2251 | 2109 |
2252 StaticMarkingVisitor::IterateBody(map, object); | 2110 MarkCompactMarkingVisitor::IterateBody(map, object); |
2253 } | 2111 } |
2254 | 2112 |
2255 // Process encountered weak maps, mark objects only reachable by those | 2113 // Process encountered weak maps, mark objects only reachable by those |
2256 // weak maps and repeat until fix-point is reached. | 2114 // weak maps and repeat until fix-point is reached. |
2257 ProcessWeakMaps(); | 2115 ProcessWeakMaps(); |
2258 } | 2116 } |
2259 } | 2117 } |
2260 | 2118 |
2261 | 2119 |
2262 // Sweep the heap for overflowed objects, clear their overflow bits, and | 2120 // Sweep the heap for overflowed objects, clear their overflow bits, and |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2381 if (was_marked_incrementally_) { | 2239 if (was_marked_incrementally_) { |
2382 // There is no write barrier on cells so we have to scan them now at the end | 2240 // There is no write barrier on cells so we have to scan them now at the end |
2383 // of the incremental marking. | 2241 // of the incremental marking. |
2384 { | 2242 { |
2385 HeapObjectIterator cell_iterator(heap()->cell_space()); | 2243 HeapObjectIterator cell_iterator(heap()->cell_space()); |
2386 HeapObject* cell; | 2244 HeapObject* cell; |
2387 while ((cell = cell_iterator.Next()) != NULL) { | 2245 while ((cell = cell_iterator.Next()) != NULL) { |
2388 ASSERT(cell->IsJSGlobalPropertyCell()); | 2246 ASSERT(cell->IsJSGlobalPropertyCell()); |
2389 if (IsMarked(cell)) { | 2247 if (IsMarked(cell)) { |
2390 int offset = JSGlobalPropertyCell::kValueOffset; | 2248 int offset = JSGlobalPropertyCell::kValueOffset; |
2391 StaticMarkingVisitor::VisitPointer( | 2249 MarkCompactMarkingVisitor::VisitPointer( |
2392 heap(), | 2250 heap(), |
2393 reinterpret_cast<Object**>(cell->address() + offset)); | 2251 reinterpret_cast<Object**>(cell->address() + offset)); |
2394 } | 2252 } |
2395 } | 2253 } |
2396 } | 2254 } |
2397 } | 2255 } |
2398 | 2256 |
2399 RootMarkingVisitor root_visitor(heap()); | 2257 RootMarkingVisitor root_visitor(heap()); |
2400 MarkRoots(&root_visitor); | 2258 MarkRoots(&root_visitor); |
2401 | 2259 |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2640 Object** anchor = reinterpret_cast<Object**>(table->address()); | 2498 Object** anchor = reinterpret_cast<Object**>(table->address()); |
2641 for (int i = 0; i < table->Capacity(); i++) { | 2499 for (int i = 0; i < table->Capacity(); i++) { |
2642 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { | 2500 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { |
2643 Object** key_slot = | 2501 Object** key_slot = |
2644 HeapObject::RawField(table, FixedArray::OffsetOfElementAt( | 2502 HeapObject::RawField(table, FixedArray::OffsetOfElementAt( |
2645 ObjectHashTable::EntryToIndex(i))); | 2503 ObjectHashTable::EntryToIndex(i))); |
2646 RecordSlot(anchor, key_slot, *key_slot); | 2504 RecordSlot(anchor, key_slot, *key_slot); |
2647 Object** value_slot = | 2505 Object** value_slot = |
2648 HeapObject::RawField(table, FixedArray::OffsetOfElementAt( | 2506 HeapObject::RawField(table, FixedArray::OffsetOfElementAt( |
2649 ObjectHashTable::EntryToValueIndex(i))); | 2507 ObjectHashTable::EntryToValueIndex(i))); |
2650 StaticMarkingVisitor::MarkObjectByPointer(this, anchor, value_slot); | 2508 MarkCompactMarkingVisitor::MarkObjectByPointer(this, anchor, value_slot)
; |
2651 } | 2509 } |
2652 } | 2510 } |
2653 weak_map_obj = weak_map->next(); | 2511 weak_map_obj = weak_map->next(); |
2654 } | 2512 } |
2655 } | 2513 } |
2656 | 2514 |
2657 | 2515 |
2658 void MarkCompactCollector::ClearWeakMaps() { | 2516 void MarkCompactCollector::ClearWeakMaps() { |
2659 Object* weak_map_obj = encountered_weak_maps(); | 2517 Object* weak_map_obj = encountered_weak_maps(); |
2660 while (weak_map_obj != Smi::FromInt(0)) { | 2518 while (weak_map_obj != Smi::FromInt(0)) { |
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4039 GDBJITInterface::RemoveCode(reinterpret_cast<Code*>(obj)); | 3897 GDBJITInterface::RemoveCode(reinterpret_cast<Code*>(obj)); |
4040 } | 3898 } |
4041 #endif | 3899 #endif |
4042 if (obj->IsCode()) { | 3900 if (obj->IsCode()) { |
4043 PROFILE(isolate, CodeDeleteEvent(obj->address())); | 3901 PROFILE(isolate, CodeDeleteEvent(obj->address())); |
4044 } | 3902 } |
4045 } | 3903 } |
4046 | 3904 |
4047 | 3905 |
4048 void MarkCompactCollector::Initialize() { | 3906 void MarkCompactCollector::Initialize() { |
4049 StaticMarkingVisitor::Initialize(); | 3907 MarkCompactMarkingVisitor::Initialize(); |
| 3908 IncrementalMarking::Initialize(); |
4050 } | 3909 } |
4051 | 3910 |
4052 | 3911 |
4053 bool SlotsBuffer::IsTypedSlot(ObjectSlot slot) { | 3912 bool SlotsBuffer::IsTypedSlot(ObjectSlot slot) { |
4054 return reinterpret_cast<uintptr_t>(slot) < NUMBER_OF_SLOT_TYPES; | 3913 return reinterpret_cast<uintptr_t>(slot) < NUMBER_OF_SLOT_TYPES; |
4055 } | 3914 } |
4056 | 3915 |
4057 | 3916 |
4058 bool SlotsBuffer::AddTo(SlotsBufferAllocator* allocator, | 3917 bool SlotsBuffer::AddTo(SlotsBufferAllocator* allocator, |
4059 SlotsBuffer** buffer_address, | 3918 SlotsBuffer** buffer_address, |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4184 while (buffer != NULL) { | 4043 while (buffer != NULL) { |
4185 SlotsBuffer* next_buffer = buffer->next(); | 4044 SlotsBuffer* next_buffer = buffer->next(); |
4186 DeallocateBuffer(buffer); | 4045 DeallocateBuffer(buffer); |
4187 buffer = next_buffer; | 4046 buffer = next_buffer; |
4188 } | 4047 } |
4189 *buffer_address = NULL; | 4048 *buffer_address = NULL; |
4190 } | 4049 } |
4191 | 4050 |
4192 | 4051 |
4193 } } // namespace v8::internal | 4052 } } // namespace v8::internal |
OLD | NEW |