| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-cache.h" | 10 #include "src/compilation-cache.h" |
| (...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 candidate->set_code(lazy_compile); | 897 candidate->set_code(lazy_compile); |
| 898 } else { | 898 } else { |
| 899 DCHECK(Marking::IsBlack(code_mark)); | 899 DCHECK(Marking::IsBlack(code_mark)); |
| 900 candidate->set_code(code); | 900 candidate->set_code(code); |
| 901 } | 901 } |
| 902 | 902 |
| 903 // We are in the middle of a GC cycle so the write barrier in the code | 903 // We are in the middle of a GC cycle so the write barrier in the code |
| 904 // setter did not record the slot update and we have to do that manually. | 904 // setter did not record the slot update and we have to do that manually. |
| 905 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; | 905 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; |
| 906 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); | 906 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); |
| 907 isolate_->heap()->mark_compact_collector()->RecordCodeEntrySlot(slot, | 907 isolate_->heap()->mark_compact_collector()->RecordCodeEntrySlot( |
| 908 target); | 908 candidate, slot, target); |
| 909 | 909 |
| 910 Object** shared_code_slot = | 910 Object** shared_code_slot = |
| 911 HeapObject::RawField(shared, SharedFunctionInfo::kCodeOffset); | 911 HeapObject::RawField(shared, SharedFunctionInfo::kCodeOffset); |
| 912 isolate_->heap()->mark_compact_collector()->RecordSlot( | 912 isolate_->heap()->mark_compact_collector()->RecordSlot( |
| 913 shared_code_slot, shared_code_slot, *shared_code_slot); | 913 shared, shared_code_slot, *shared_code_slot); |
| 914 | 914 |
| 915 candidate = next_candidate; | 915 candidate = next_candidate; |
| 916 } | 916 } |
| 917 | 917 |
| 918 jsfunction_candidates_head_ = NULL; | 918 jsfunction_candidates_head_ = NULL; |
| 919 } | 919 } |
| 920 | 920 |
| 921 | 921 |
| 922 void CodeFlusher::ProcessSharedFunctionInfoCandidates() { | 922 void CodeFlusher::ProcessSharedFunctionInfoCandidates() { |
| 923 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kCompileLazy); | 923 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kCompileLazy); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 938 } | 938 } |
| 939 // Always flush the optimized code map if there is one. | 939 // Always flush the optimized code map if there is one. |
| 940 if (!candidate->optimized_code_map()->IsSmi()) { | 940 if (!candidate->optimized_code_map()->IsSmi()) { |
| 941 candidate->ClearOptimizedCodeMap(); | 941 candidate->ClearOptimizedCodeMap(); |
| 942 } | 942 } |
| 943 candidate->set_code(lazy_compile); | 943 candidate->set_code(lazy_compile); |
| 944 } | 944 } |
| 945 | 945 |
| 946 Object** code_slot = | 946 Object** code_slot = |
| 947 HeapObject::RawField(candidate, SharedFunctionInfo::kCodeOffset); | 947 HeapObject::RawField(candidate, SharedFunctionInfo::kCodeOffset); |
| 948 isolate_->heap()->mark_compact_collector()->RecordSlot(code_slot, code_slot, | 948 isolate_->heap()->mark_compact_collector()->RecordSlot(candidate, code_slot, |
| 949 *code_slot); | 949 *code_slot); |
| 950 | 950 |
| 951 candidate = next_candidate; | 951 candidate = next_candidate; |
| 952 } | 952 } |
| 953 | 953 |
| 954 shared_function_info_candidates_head_ = NULL; | 954 shared_function_info_candidates_head_ = NULL; |
| 955 } | 955 } |
| 956 | 956 |
| 957 | 957 |
| 958 void CodeFlusher::ProcessOptimizedCodeMaps() { | 958 void CodeFlusher::ProcessOptimizedCodeMaps() { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 988 if (Marking::IsWhite(Marking::MarkBitFrom(literals))) continue; | 988 if (Marking::IsWhite(Marking::MarkBitFrom(literals))) continue; |
| 989 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(literals))); | 989 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(literals))); |
| 990 // Move every slot in the entry and record slots when needed. | 990 // Move every slot in the entry and record slots when needed. |
| 991 code_map->set(new_length + SharedFunctionInfo::kCachedCodeOffset, code); | 991 code_map->set(new_length + SharedFunctionInfo::kCachedCodeOffset, code); |
| 992 code_map->set(new_length + SharedFunctionInfo::kContextOffset, context); | 992 code_map->set(new_length + SharedFunctionInfo::kContextOffset, context); |
| 993 code_map->set(new_length + SharedFunctionInfo::kLiteralsOffset, literals); | 993 code_map->set(new_length + SharedFunctionInfo::kLiteralsOffset, literals); |
| 994 code_map->set(new_length + SharedFunctionInfo::kOsrAstIdOffset, ast_id); | 994 code_map->set(new_length + SharedFunctionInfo::kOsrAstIdOffset, ast_id); |
| 995 Object** code_slot = code_map->RawFieldOfElementAt( | 995 Object** code_slot = code_map->RawFieldOfElementAt( |
| 996 new_length + SharedFunctionInfo::kCachedCodeOffset); | 996 new_length + SharedFunctionInfo::kCachedCodeOffset); |
| 997 isolate_->heap()->mark_compact_collector()->RecordSlot( | 997 isolate_->heap()->mark_compact_collector()->RecordSlot( |
| 998 code_slot, code_slot, *code_slot); | 998 code_map, code_slot, *code_slot); |
| 999 Object** context_slot = code_map->RawFieldOfElementAt( | 999 Object** context_slot = code_map->RawFieldOfElementAt( |
| 1000 new_length + SharedFunctionInfo::kContextOffset); | 1000 new_length + SharedFunctionInfo::kContextOffset); |
| 1001 isolate_->heap()->mark_compact_collector()->RecordSlot( | 1001 isolate_->heap()->mark_compact_collector()->RecordSlot( |
| 1002 context_slot, context_slot, *context_slot); | 1002 code_map, context_slot, *context_slot); |
| 1003 Object** literals_slot = code_map->RawFieldOfElementAt( | 1003 Object** literals_slot = code_map->RawFieldOfElementAt( |
| 1004 new_length + SharedFunctionInfo::kLiteralsOffset); | 1004 new_length + SharedFunctionInfo::kLiteralsOffset); |
| 1005 isolate_->heap()->mark_compact_collector()->RecordSlot( | 1005 isolate_->heap()->mark_compact_collector()->RecordSlot( |
| 1006 literals_slot, literals_slot, *literals_slot); | 1006 code_map, literals_slot, *literals_slot); |
| 1007 new_length += SharedFunctionInfo::kEntryLength; | 1007 new_length += SharedFunctionInfo::kEntryLength; |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 // Process context-independent entry in the optimized code map. | 1010 // Process context-independent entry in the optimized code map. |
| 1011 Object* shared_object = code_map->get(SharedFunctionInfo::kSharedCodeIndex); | 1011 Object* shared_object = code_map->get(SharedFunctionInfo::kSharedCodeIndex); |
| 1012 if (shared_object->IsCode()) { | 1012 if (shared_object->IsCode()) { |
| 1013 Code* shared_code = Code::cast(shared_object); | 1013 Code* shared_code = Code::cast(shared_object); |
| 1014 if (Marking::IsWhite(Marking::MarkBitFrom(shared_code))) { | 1014 if (Marking::IsWhite(Marking::MarkBitFrom(shared_code))) { |
| 1015 code_map->set_undefined(SharedFunctionInfo::kSharedCodeIndex); | 1015 code_map->set_undefined(SharedFunctionInfo::kSharedCodeIndex); |
| 1016 } else { | 1016 } else { |
| 1017 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(shared_code))); | 1017 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(shared_code))); |
| 1018 Object** slot = | 1018 Object** slot = |
| 1019 code_map->RawFieldOfElementAt(SharedFunctionInfo::kSharedCodeIndex); | 1019 code_map->RawFieldOfElementAt(SharedFunctionInfo::kSharedCodeIndex); |
| 1020 isolate_->heap()->mark_compact_collector()->RecordSlot(slot, slot, | 1020 isolate_->heap()->mark_compact_collector()->RecordSlot(code_map, slot, |
| 1021 *slot); | 1021 *slot); |
| 1022 } | 1022 } |
| 1023 } | 1023 } |
| 1024 | 1024 |
| 1025 // Trim the optimized code map if entries have been removed. | 1025 // Trim the optimized code map if entries have been removed. |
| 1026 if (new_length < old_length) { | 1026 if (new_length < old_length) { |
| 1027 holder->TrimOptimizedCodeMap(old_length - new_length); | 1027 holder->TrimOptimizedCodeMap(old_length - new_length); |
| 1028 } | 1028 } |
| 1029 | 1029 |
| 1030 holder = next_holder; | 1030 holder = next_holder; |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1247 FixedArraySubInstanceType dictionary_type); | 1247 FixedArraySubInstanceType dictionary_type); |
| 1248 | 1248 |
| 1249 template <MarkCompactMarkingVisitor::VisitorId id> | 1249 template <MarkCompactMarkingVisitor::VisitorId id> |
| 1250 class ObjectStatsTracker { | 1250 class ObjectStatsTracker { |
| 1251 public: | 1251 public: |
| 1252 static inline void Visit(Map* map, HeapObject* obj); | 1252 static inline void Visit(Map* map, HeapObject* obj); |
| 1253 }; | 1253 }; |
| 1254 | 1254 |
| 1255 static void Initialize(); | 1255 static void Initialize(); |
| 1256 | 1256 |
| 1257 INLINE(static void VisitPointer(Heap* heap, Object** p)) { | 1257 INLINE(static void VisitPointer(Heap* heap, HeapObject* object, Object** p)) { |
| 1258 MarkObjectByPointer(heap->mark_compact_collector(), p, p); | 1258 MarkObjectByPointer(heap->mark_compact_collector(), object, p); |
| 1259 } | 1259 } |
| 1260 | 1260 |
| 1261 INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { | 1261 INLINE(static void VisitPointers(Heap* heap, HeapObject* object, |
| 1262 Object** start, Object** end)) { |
| 1262 // Mark all objects pointed to in [start, end). | 1263 // Mark all objects pointed to in [start, end). |
| 1263 const int kMinRangeForMarkingRecursion = 64; | 1264 const int kMinRangeForMarkingRecursion = 64; |
| 1264 if (end - start >= kMinRangeForMarkingRecursion) { | 1265 if (end - start >= kMinRangeForMarkingRecursion) { |
| 1265 if (VisitUnmarkedObjects(heap, start, end)) return; | 1266 if (VisitUnmarkedObjects(heap, object, start, end)) return; |
| 1266 // We are close to a stack overflow, so just mark the objects. | 1267 // We are close to a stack overflow, so just mark the objects. |
| 1267 } | 1268 } |
| 1268 MarkCompactCollector* collector = heap->mark_compact_collector(); | 1269 MarkCompactCollector* collector = heap->mark_compact_collector(); |
| 1269 for (Object** p = start; p < end; p++) { | 1270 for (Object** p = start; p < end; p++) { |
| 1270 MarkObjectByPointer(collector, start, p); | 1271 MarkObjectByPointer(collector, object, p); |
| 1271 } | 1272 } |
| 1272 } | 1273 } |
| 1273 | 1274 |
| 1274 // Marks the object black and pushes it on the marking stack. | 1275 // Marks the object black and pushes it on the marking stack. |
| 1275 INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { | 1276 INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { |
| 1276 MarkBit mark = Marking::MarkBitFrom(object); | 1277 MarkBit mark = Marking::MarkBitFrom(object); |
| 1277 heap->mark_compact_collector()->MarkObject(object, mark); | 1278 heap->mark_compact_collector()->MarkObject(object, mark); |
| 1278 } | 1279 } |
| 1279 | 1280 |
| 1280 // Marks the object black without pushing it on the marking stack. | 1281 // Marks the object black without pushing it on the marking stack. |
| 1281 // Returns true if object needed marking and false otherwise. | 1282 // Returns true if object needed marking and false otherwise. |
| 1282 INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) { | 1283 INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) { |
| 1283 MarkBit mark_bit = Marking::MarkBitFrom(object); | 1284 MarkBit mark_bit = Marking::MarkBitFrom(object); |
| 1284 if (Marking::IsWhite(mark_bit)) { | 1285 if (Marking::IsWhite(mark_bit)) { |
| 1285 heap->mark_compact_collector()->SetMark(object, mark_bit); | 1286 heap->mark_compact_collector()->SetMark(object, mark_bit); |
| 1286 return true; | 1287 return true; |
| 1287 } | 1288 } |
| 1288 return false; | 1289 return false; |
| 1289 } | 1290 } |
| 1290 | 1291 |
| 1291 // Mark object pointed to by p. | 1292 // Mark object pointed to by p. |
| 1292 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, | 1293 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, |
| 1293 Object** anchor_slot, Object** p)) { | 1294 HeapObject* object, Object** p)) { |
| 1294 if (!(*p)->IsHeapObject()) return; | 1295 if (!(*p)->IsHeapObject()) return; |
| 1295 HeapObject* object = ShortCircuitConsString(p); | 1296 HeapObject* target_object = ShortCircuitConsString(p); |
| 1296 collector->RecordSlot(anchor_slot, p, object); | 1297 collector->RecordSlot(object, p, target_object); |
| 1297 MarkBit mark = Marking::MarkBitFrom(object); | 1298 MarkBit mark = Marking::MarkBitFrom(target_object); |
| 1298 collector->MarkObject(object, mark); | 1299 collector->MarkObject(target_object, mark); |
| 1299 } | 1300 } |
| 1300 | 1301 |
| 1301 | 1302 |
| 1302 // Visit an unmarked object. | 1303 // Visit an unmarked object. |
| 1303 INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector, | 1304 INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector, |
| 1304 HeapObject* obj)) { | 1305 HeapObject* obj)) { |
| 1305 #ifdef DEBUG | 1306 #ifdef DEBUG |
| 1306 DCHECK(collector->heap()->Contains(obj)); | 1307 DCHECK(collector->heap()->Contains(obj)); |
| 1307 DCHECK(!collector->heap()->mark_compact_collector()->IsMarked(obj)); | 1308 DCHECK(!collector->heap()->mark_compact_collector()->IsMarked(obj)); |
| 1308 #endif | 1309 #endif |
| 1309 Map* map = obj->map(); | 1310 Map* map = obj->map(); |
| 1310 Heap* heap = obj->GetHeap(); | 1311 Heap* heap = obj->GetHeap(); |
| 1311 MarkBit mark = Marking::MarkBitFrom(obj); | 1312 MarkBit mark = Marking::MarkBitFrom(obj); |
| 1312 heap->mark_compact_collector()->SetMark(obj, mark); | 1313 heap->mark_compact_collector()->SetMark(obj, mark); |
| 1313 // Mark the map pointer and the body. | 1314 // Mark the map pointer and the body. |
| 1314 MarkBit map_mark = Marking::MarkBitFrom(map); | 1315 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 1315 heap->mark_compact_collector()->MarkObject(map, map_mark); | 1316 heap->mark_compact_collector()->MarkObject(map, map_mark); |
| 1316 IterateBody(map, obj); | 1317 IterateBody(map, obj); |
| 1317 } | 1318 } |
| 1318 | 1319 |
| 1319 // Visit all unmarked objects pointed to by [start, end). | 1320 // Visit all unmarked objects pointed to by [start, end). |
| 1320 // Returns false if the operation fails (lack of stack space). | 1321 // Returns false if the operation fails (lack of stack space). |
| 1321 INLINE(static bool VisitUnmarkedObjects(Heap* heap, Object** start, | 1322 INLINE(static bool VisitUnmarkedObjects(Heap* heap, HeapObject* object, |
| 1322 Object** end)) { | 1323 Object** start, Object** end)) { |
| 1323 // Return false is we are close to the stack limit. | 1324 // Return false is we are close to the stack limit. |
| 1324 StackLimitCheck check(heap->isolate()); | 1325 StackLimitCheck check(heap->isolate()); |
| 1325 if (check.HasOverflowed()) return false; | 1326 if (check.HasOverflowed()) return false; |
| 1326 | 1327 |
| 1327 MarkCompactCollector* collector = heap->mark_compact_collector(); | 1328 MarkCompactCollector* collector = heap->mark_compact_collector(); |
| 1328 // Visit the unmarked objects. | 1329 // Visit the unmarked objects. |
| 1329 for (Object** p = start; p < end; p++) { | 1330 for (Object** p = start; p < end; p++) { |
| 1330 Object* o = *p; | 1331 Object* o = *p; |
| 1331 if (!o->IsHeapObject()) continue; | 1332 if (!o->IsHeapObject()) continue; |
| 1332 collector->RecordSlot(start, p, o); | 1333 collector->RecordSlot(object, p, o); |
| 1333 HeapObject* obj = HeapObject::cast(o); | 1334 HeapObject* obj = HeapObject::cast(o); |
| 1334 MarkBit mark = Marking::MarkBitFrom(obj); | 1335 MarkBit mark = Marking::MarkBitFrom(obj); |
| 1335 if (Marking::IsBlackOrGrey(mark)) continue; | 1336 if (Marking::IsBlackOrGrey(mark)) continue; |
| 1336 VisitUnmarkedObject(collector, obj); | 1337 VisitUnmarkedObject(collector, obj); |
| 1337 } | 1338 } |
| 1338 return true; | 1339 return true; |
| 1339 } | 1340 } |
| 1340 | 1341 |
| 1341 private: | 1342 private: |
| 1342 template <int id> | 1343 template <int id> |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1363 // Save a copy that can be reinstated if we need the code again. | 1364 // Save a copy that can be reinstated if we need the code again. |
| 1364 re->SetDataAt(JSRegExp::saved_code_index(is_one_byte), code); | 1365 re->SetDataAt(JSRegExp::saved_code_index(is_one_byte), code); |
| 1365 | 1366 |
| 1366 // Saving a copy might create a pointer into compaction candidate | 1367 // Saving a copy might create a pointer into compaction candidate |
| 1367 // that was not observed by marker. This might happen if JSRegExp data | 1368 // that was not observed by marker. This might happen if JSRegExp data |
| 1368 // was marked through the compilation cache before marker reached JSRegExp | 1369 // was marked through the compilation cache before marker reached JSRegExp |
| 1369 // object. | 1370 // object. |
| 1370 FixedArray* data = FixedArray::cast(re->data()); | 1371 FixedArray* data = FixedArray::cast(re->data()); |
| 1371 Object** slot = | 1372 Object** slot = |
| 1372 data->data_start() + JSRegExp::saved_code_index(is_one_byte); | 1373 data->data_start() + JSRegExp::saved_code_index(is_one_byte); |
| 1373 heap->mark_compact_collector()->RecordSlot(slot, slot, code); | 1374 heap->mark_compact_collector()->RecordSlot(data, slot, code); |
| 1374 | 1375 |
| 1375 // Set a number in the 0-255 range to guarantee no smi overflow. | 1376 // Set a number in the 0-255 range to guarantee no smi overflow. |
| 1376 re->SetDataAt(JSRegExp::code_index(is_one_byte), | 1377 re->SetDataAt(JSRegExp::code_index(is_one_byte), |
| 1377 Smi::FromInt(heap->sweep_generation() & 0xff)); | 1378 Smi::FromInt(heap->sweep_generation() & 0xff)); |
| 1378 } else if (code->IsSmi()) { | 1379 } else if (code->IsSmi()) { |
| 1379 int value = Smi::cast(code)->value(); | 1380 int value = Smi::cast(code)->value(); |
| 1380 // The regexp has not been compiled yet or there was a compilation error. | 1381 // The regexp has not been compiled yet or there was a compilation error. |
| 1381 if (value == JSRegExp::kUninitializedValue || | 1382 if (value == JSRegExp::kUninitializedValue || |
| 1382 value == JSRegExp::kCompilationErrorValue) { | 1383 value == JSRegExp::kCompilationErrorValue) { |
| 1383 return; | 1384 return; |
| (...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2145 // transition tree alive, not JSObjects. Do not age the map. | 2146 // transition tree alive, not JSObjects. Do not age the map. |
| 2146 new_age = age; | 2147 new_age = age; |
| 2147 } | 2148 } |
| 2148 MarkObject(map, map_mark); | 2149 MarkObject(map, map_mark); |
| 2149 } else { | 2150 } else { |
| 2150 new_age = FLAG_retain_maps_for_n_gc; | 2151 new_age = FLAG_retain_maps_for_n_gc; |
| 2151 } | 2152 } |
| 2152 if (i != new_length) { | 2153 if (i != new_length) { |
| 2153 retained_maps->Set(new_length, cell); | 2154 retained_maps->Set(new_length, cell); |
| 2154 Object** slot = retained_maps->Slot(new_length); | 2155 Object** slot = retained_maps->Slot(new_length); |
| 2155 RecordSlot(slot, slot, cell); | 2156 RecordSlot(retained_maps, slot, cell); |
| 2156 retained_maps->Set(new_length + 1, Smi::FromInt(new_age)); | 2157 retained_maps->Set(new_length + 1, Smi::FromInt(new_age)); |
| 2157 } else if (new_age != age) { | 2158 } else if (new_age != age) { |
| 2158 retained_maps->Set(new_length + 1, Smi::FromInt(new_age)); | 2159 retained_maps->Set(new_length + 1, Smi::FromInt(new_age)); |
| 2159 } | 2160 } |
| 2160 new_length += 2; | 2161 new_length += 2; |
| 2161 } | 2162 } |
| 2162 Object* undefined = heap()->undefined_value(); | 2163 Object* undefined = heap()->undefined_value(); |
| 2163 for (int i = new_length; i < length; i++) { | 2164 for (int i = new_length; i < length; i++) { |
| 2164 retained_maps->Clear(i, undefined); | 2165 retained_maps->Clear(i, undefined); |
| 2165 } | 2166 } |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2415 | 2416 |
| 2416 const int header = TransitionArray::kProtoTransitionHeaderSize; | 2417 const int header = TransitionArray::kProtoTransitionHeaderSize; |
| 2417 int new_number_of_transitions = 0; | 2418 int new_number_of_transitions = 0; |
| 2418 for (int i = 0; i < number_of_transitions; i++) { | 2419 for (int i = 0; i < number_of_transitions; i++) { |
| 2419 Object* cell = prototype_transitions->get(header + i); | 2420 Object* cell = prototype_transitions->get(header + i); |
| 2420 if (!WeakCell::cast(cell)->cleared()) { | 2421 if (!WeakCell::cast(cell)->cleared()) { |
| 2421 if (new_number_of_transitions != i) { | 2422 if (new_number_of_transitions != i) { |
| 2422 prototype_transitions->set(header + new_number_of_transitions, cell); | 2423 prototype_transitions->set(header + new_number_of_transitions, cell); |
| 2423 Object** slot = prototype_transitions->RawFieldOfElementAt( | 2424 Object** slot = prototype_transitions->RawFieldOfElementAt( |
| 2424 header + new_number_of_transitions); | 2425 header + new_number_of_transitions); |
| 2425 RecordSlot(slot, slot, cell); | 2426 RecordSlot(prototype_transitions, slot, cell); |
| 2426 } | 2427 } |
| 2427 new_number_of_transitions++; | 2428 new_number_of_transitions++; |
| 2428 } | 2429 } |
| 2429 } | 2430 } |
| 2430 | 2431 |
| 2431 if (new_number_of_transitions != number_of_transitions) { | 2432 if (new_number_of_transitions != number_of_transitions) { |
| 2432 TransitionArray::SetNumberOfPrototypeTransitions(prototype_transitions, | 2433 TransitionArray::SetNumberOfPrototypeTransitions(prototype_transitions, |
| 2433 new_number_of_transitions); | 2434 new_number_of_transitions); |
| 2434 } | 2435 } |
| 2435 | 2436 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2498 if (target->instance_descriptors() == descriptors) { | 2499 if (target->instance_descriptors() == descriptors) { |
| 2499 descriptors_owner_died = true; | 2500 descriptors_owner_died = true; |
| 2500 } | 2501 } |
| 2501 } else { | 2502 } else { |
| 2502 if (i != transition_index) { | 2503 if (i != transition_index) { |
| 2503 DCHECK(TransitionArray::IsFullTransitionArray(transitions)); | 2504 DCHECK(TransitionArray::IsFullTransitionArray(transitions)); |
| 2504 TransitionArray* t = TransitionArray::cast(transitions); | 2505 TransitionArray* t = TransitionArray::cast(transitions); |
| 2505 Name* key = t->GetKey(i); | 2506 Name* key = t->GetKey(i); |
| 2506 t->SetKey(transition_index, key); | 2507 t->SetKey(transition_index, key); |
| 2507 Object** key_slot = t->GetKeySlot(transition_index); | 2508 Object** key_slot = t->GetKeySlot(transition_index); |
| 2508 RecordSlot(key_slot, key_slot, key); | 2509 RecordSlot(t, key_slot, key); |
| 2509 // Target slots do not need to be recorded since maps are not compacted. | 2510 // Target slots do not need to be recorded since maps are not compacted. |
| 2510 t->SetTarget(transition_index, t->GetTarget(i)); | 2511 t->SetTarget(transition_index, t->GetTarget(i)); |
| 2511 } | 2512 } |
| 2512 transition_index++; | 2513 transition_index++; |
| 2513 } | 2514 } |
| 2514 } | 2515 } |
| 2515 | 2516 |
| 2516 // If there are no transitions to be cleared, return. | 2517 // If there are no transitions to be cleared, return. |
| 2517 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 2518 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
| 2518 // properly cleared. | 2519 // properly cleared. |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2594 void MarkCompactCollector::ProcessWeakCollections() { | 2595 void MarkCompactCollector::ProcessWeakCollections() { |
| 2595 GCTracer::Scope gc_scope(heap()->tracer(), | 2596 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2596 GCTracer::Scope::MC_WEAKCOLLECTION_PROCESS); | 2597 GCTracer::Scope::MC_WEAKCOLLECTION_PROCESS); |
| 2597 Object* weak_collection_obj = heap()->encountered_weak_collections(); | 2598 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
| 2598 while (weak_collection_obj != Smi::FromInt(0)) { | 2599 while (weak_collection_obj != Smi::FromInt(0)) { |
| 2599 JSWeakCollection* weak_collection = | 2600 JSWeakCollection* weak_collection = |
| 2600 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2601 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
| 2601 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); | 2602 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); |
| 2602 if (weak_collection->table()->IsHashTable()) { | 2603 if (weak_collection->table()->IsHashTable()) { |
| 2603 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); | 2604 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); |
| 2604 Object** anchor = reinterpret_cast<Object**>(table->address()); | |
| 2605 for (int i = 0; i < table->Capacity(); i++) { | 2605 for (int i = 0; i < table->Capacity(); i++) { |
| 2606 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { | 2606 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { |
| 2607 Object** key_slot = | 2607 Object** key_slot = |
| 2608 table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i)); | 2608 table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i)); |
| 2609 RecordSlot(anchor, key_slot, *key_slot); | 2609 RecordSlot(table, key_slot, *key_slot); |
| 2610 Object** value_slot = | 2610 Object** value_slot = |
| 2611 table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i)); | 2611 table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i)); |
| 2612 MarkCompactMarkingVisitor::MarkObjectByPointer(this, anchor, | 2612 MarkCompactMarkingVisitor::MarkObjectByPointer(this, table, |
| 2613 value_slot); | 2613 value_slot); |
| 2614 } | 2614 } |
| 2615 } | 2615 } |
| 2616 } | 2616 } |
| 2617 weak_collection_obj = weak_collection->next(); | 2617 weak_collection_obj = weak_collection->next(); |
| 2618 } | 2618 } |
| 2619 } | 2619 } |
| 2620 | 2620 |
| 2621 | 2621 |
| 2622 void MarkCompactCollector::ClearWeakCollections() { | 2622 void MarkCompactCollector::ClearWeakCollections() { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2671 // alive as long as the cell value is alive. | 2671 // alive as long as the cell value is alive. |
| 2672 // TODO(ulan): remove this once we remove Heap::weak_object_to_code_table. | 2672 // TODO(ulan): remove this once we remove Heap::weak_object_to_code_table. |
| 2673 if (value->IsCell()) { | 2673 if (value->IsCell()) { |
| 2674 Object* cell_value = Cell::cast(value)->value(); | 2674 Object* cell_value = Cell::cast(value)->value(); |
| 2675 if (cell_value->IsHeapObject() && | 2675 if (cell_value->IsHeapObject() && |
| 2676 MarkCompactCollector::IsMarked(HeapObject::cast(cell_value))) { | 2676 MarkCompactCollector::IsMarked(HeapObject::cast(cell_value))) { |
| 2677 // Resurrect the cell. | 2677 // Resurrect the cell. |
| 2678 MarkBit mark = Marking::MarkBitFrom(value); | 2678 MarkBit mark = Marking::MarkBitFrom(value); |
| 2679 SetMark(value, mark); | 2679 SetMark(value, mark); |
| 2680 Object** slot = HeapObject::RawField(value, Cell::kValueOffset); | 2680 Object** slot = HeapObject::RawField(value, Cell::kValueOffset); |
| 2681 RecordSlot(slot, slot, *slot); | 2681 RecordSlot(value, slot, *slot); |
| 2682 slot = HeapObject::RawField(weak_cell, WeakCell::kValueOffset); | 2682 slot = HeapObject::RawField(weak_cell, WeakCell::kValueOffset); |
| 2683 RecordSlot(slot, slot, *slot); | 2683 RecordSlot(weak_cell, slot, *slot); |
| 2684 } else { | 2684 } else { |
| 2685 weak_cell->clear(); | 2685 weak_cell->clear(); |
| 2686 } | 2686 } |
| 2687 } else { | 2687 } else { |
| 2688 weak_cell->clear(); | 2688 weak_cell->clear(); |
| 2689 } | 2689 } |
| 2690 } else { | 2690 } else { |
| 2691 Object** slot = HeapObject::RawField(weak_cell, WeakCell::kValueOffset); | 2691 Object** slot = HeapObject::RawField(weak_cell, WeakCell::kValueOffset); |
| 2692 RecordSlot(slot, slot, *slot); | 2692 RecordSlot(weak_cell, slot, *slot); |
| 2693 } | 2693 } |
| 2694 weak_cell_obj = weak_cell->next(); | 2694 weak_cell_obj = weak_cell->next(); |
| 2695 weak_cell->clear_next(heap()); | 2695 weak_cell->clear_next(heap()); |
| 2696 } | 2696 } |
| 2697 heap()->set_encountered_weak_cells(Smi::FromInt(0)); | 2697 heap()->set_encountered_weak_cells(Smi::FromInt(0)); |
| 2698 } | 2698 } |
| 2699 | 2699 |
| 2700 | 2700 |
| 2701 void MarkCompactCollector::AbortWeakCells() { | 2701 void MarkCompactCollector::AbortWeakCells() { |
| 2702 Object* weak_cell_obj = heap()->encountered_weak_cells(); | 2702 Object* weak_cell_obj = heap()->encountered_weak_cells(); |
| (...skipping 2002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4705 page->SetFlag(Page::POPULAR_PAGE); | 4705 page->SetFlag(Page::POPULAR_PAGE); |
| 4706 | 4706 |
| 4707 // We were not collecting slots on this page that point | 4707 // We were not collecting slots on this page that point |
| 4708 // to other evacuation candidates thus we have to | 4708 // to other evacuation candidates thus we have to |
| 4709 // rescan the page after evacuation to discover and update all | 4709 // rescan the page after evacuation to discover and update all |
| 4710 // pointers to evacuated objects. | 4710 // pointers to evacuated objects. |
| 4711 page->SetFlag(Page::RESCAN_ON_EVACUATION); | 4711 page->SetFlag(Page::RESCAN_ON_EVACUATION); |
| 4712 } | 4712 } |
| 4713 | 4713 |
| 4714 | 4714 |
| 4715 void MarkCompactCollector::RecordCodeEntrySlot(Address slot, Code* target) { | 4715 void MarkCompactCollector::RecordCodeEntrySlot(HeapObject* object, Address slot, |
| 4716 Code* target) { |
| 4716 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); | 4717 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); |
| 4717 if (target_page->IsEvacuationCandidate() && | 4718 if (target_page->IsEvacuationCandidate() && |
| 4718 !ShouldSkipEvacuationSlotRecording(reinterpret_cast<Object**>(slot))) { | 4719 !ShouldSkipEvacuationSlotRecording(object)) { |
| 4719 if (!SlotsBuffer::AddTo(&slots_buffer_allocator_, | 4720 if (!SlotsBuffer::AddTo(&slots_buffer_allocator_, |
| 4720 target_page->slots_buffer_address(), | 4721 target_page->slots_buffer_address(), |
| 4721 SlotsBuffer::CODE_ENTRY_SLOT, slot, | 4722 SlotsBuffer::CODE_ENTRY_SLOT, slot, |
| 4722 SlotsBuffer::FAIL_ON_OVERFLOW)) { | 4723 SlotsBuffer::FAIL_ON_OVERFLOW)) { |
| 4723 EvictPopularEvacuationCandidate(target_page); | 4724 EvictPopularEvacuationCandidate(target_page); |
| 4724 } | 4725 } |
| 4725 } | 4726 } |
| 4726 } | 4727 } |
| 4727 | 4728 |
| 4728 | 4729 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4800 SlotsBuffer* buffer = *buffer_address; | 4801 SlotsBuffer* buffer = *buffer_address; |
| 4801 while (buffer != NULL) { | 4802 while (buffer != NULL) { |
| 4802 SlotsBuffer* next_buffer = buffer->next(); | 4803 SlotsBuffer* next_buffer = buffer->next(); |
| 4803 DeallocateBuffer(buffer); | 4804 DeallocateBuffer(buffer); |
| 4804 buffer = next_buffer; | 4805 buffer = next_buffer; |
| 4805 } | 4806 } |
| 4806 *buffer_address = NULL; | 4807 *buffer_address = NULL; |
| 4807 } | 4808 } |
| 4808 } // namespace internal | 4809 } // namespace internal |
| 4809 } // namespace v8 | 4810 } // namespace v8 |
| OLD | NEW |