| 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/heap/mark-compact.h" | 5 #include "src/heap/mark-compact.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 1211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1222 if (code_flusher_ != NULL) { | 1222 if (code_flusher_ != NULL) { |
| 1223 delete code_flusher_; | 1223 delete code_flusher_; |
| 1224 code_flusher_ = NULL; | 1224 code_flusher_ = NULL; |
| 1225 } | 1225 } |
| 1226 } | 1226 } |
| 1227 | 1227 |
| 1228 | 1228 |
| 1229 class MarkCompactMarkingVisitor | 1229 class MarkCompactMarkingVisitor |
| 1230 : public StaticMarkingVisitor<MarkCompactMarkingVisitor> { | 1230 : public StaticMarkingVisitor<MarkCompactMarkingVisitor> { |
| 1231 public: | 1231 public: |
| 1232 static void ObjectStatsVisitBase(StaticVisitorBase::VisitorId id, Map* map, | |
| 1233 HeapObject* obj); | |
| 1234 | |
| 1235 static void ObjectStatsCountFixedArray( | |
| 1236 FixedArrayBase* fixed_array, FixedArraySubInstanceType fast_type, | |
| 1237 FixedArraySubInstanceType dictionary_type); | |
| 1238 | |
| 1239 template <MarkCompactMarkingVisitor::VisitorId id> | |
| 1240 class ObjectStatsTracker { | |
| 1241 public: | |
| 1242 static inline void Visit(Map* map, HeapObject* obj); | |
| 1243 }; | |
| 1244 | |
| 1245 static void Initialize(); | 1232 static void Initialize(); |
| 1246 | 1233 |
| 1247 INLINE(static void VisitPointer(Heap* heap, HeapObject* object, Object** p)) { | 1234 INLINE(static void VisitPointer(Heap* heap, HeapObject* object, Object** p)) { |
| 1248 MarkObjectByPointer(heap->mark_compact_collector(), object, p); | 1235 MarkObjectByPointer(heap->mark_compact_collector(), object, p); |
| 1249 } | 1236 } |
| 1250 | 1237 |
| 1251 INLINE(static void VisitPointers(Heap* heap, HeapObject* object, | 1238 INLINE(static void VisitPointers(Heap* heap, HeapObject* object, |
| 1252 Object** start, Object** end)) { | 1239 Object** start, Object** end)) { |
| 1253 // Mark all objects pointed to in [start, end). | 1240 // Mark all objects pointed to in [start, end). |
| 1254 const int kMinRangeForMarkingRecursion = 64; | 1241 const int kMinRangeForMarkingRecursion = 64; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1397 VisitJSRegExp(map, object); | 1384 VisitJSRegExp(map, object); |
| 1398 return; | 1385 return; |
| 1399 } | 1386 } |
| 1400 JSRegExp* re = reinterpret_cast<JSRegExp*>(object); | 1387 JSRegExp* re = reinterpret_cast<JSRegExp*>(object); |
| 1401 // Flush code or set age on both one byte and two byte code. | 1388 // Flush code or set age on both one byte and two byte code. |
| 1402 UpdateRegExpCodeAgeAndFlush(heap, re, true); | 1389 UpdateRegExpCodeAgeAndFlush(heap, re, true); |
| 1403 UpdateRegExpCodeAgeAndFlush(heap, re, false); | 1390 UpdateRegExpCodeAgeAndFlush(heap, re, false); |
| 1404 // Visit the fields of the RegExp, including the updated FixedArray. | 1391 // Visit the fields of the RegExp, including the updated FixedArray. |
| 1405 VisitJSRegExp(map, object); | 1392 VisitJSRegExp(map, object); |
| 1406 } | 1393 } |
| 1407 | |
| 1408 static VisitorDispatchTable<Callback> non_count_table_; | |
| 1409 }; | |
| 1410 | |
| 1411 | |
| 1412 void MarkCompactMarkingVisitor::ObjectStatsCountFixedArray( | |
| 1413 FixedArrayBase* fixed_array, FixedArraySubInstanceType fast_type, | |
| 1414 FixedArraySubInstanceType dictionary_type) { | |
| 1415 Heap* heap = fixed_array->map()->GetHeap(); | |
| 1416 if (fixed_array->map() != heap->fixed_cow_array_map() && | |
| 1417 fixed_array->map() != heap->fixed_double_array_map() && | |
| 1418 fixed_array != heap->empty_fixed_array()) { | |
| 1419 if (fixed_array->IsDictionary()) { | |
| 1420 heap->object_stats_->RecordFixedArraySubTypeStats(dictionary_type, | |
| 1421 fixed_array->Size()); | |
| 1422 } else { | |
| 1423 heap->object_stats_->RecordFixedArraySubTypeStats(fast_type, | |
| 1424 fixed_array->Size()); | |
| 1425 } | |
| 1426 } | |
| 1427 } | |
| 1428 | |
| 1429 | |
| 1430 void MarkCompactMarkingVisitor::ObjectStatsVisitBase( | |
| 1431 MarkCompactMarkingVisitor::VisitorId id, Map* map, HeapObject* obj) { | |
| 1432 Heap* heap = map->GetHeap(); | |
| 1433 int object_size = obj->Size(); | |
| 1434 heap->object_stats_->RecordObjectStats(map->instance_type(), object_size); | |
| 1435 non_count_table_.GetVisitorById(id)(map, obj); | |
| 1436 if (obj->IsJSObject()) { | |
| 1437 JSObject* object = JSObject::cast(obj); | |
| 1438 ObjectStatsCountFixedArray(object->elements(), DICTIONARY_ELEMENTS_SUB_TYPE, | |
| 1439 FAST_ELEMENTS_SUB_TYPE); | |
| 1440 ObjectStatsCountFixedArray(object->properties(), | |
| 1441 DICTIONARY_PROPERTIES_SUB_TYPE, | |
| 1442 FAST_PROPERTIES_SUB_TYPE); | |
| 1443 } | |
| 1444 } | |
| 1445 | |
| 1446 | |
| 1447 template <MarkCompactMarkingVisitor::VisitorId id> | |
| 1448 void MarkCompactMarkingVisitor::ObjectStatsTracker<id>::Visit(Map* map, | |
| 1449 HeapObject* obj) { | |
| 1450 ObjectStatsVisitBase(id, map, obj); | |
| 1451 } | |
| 1452 | |
| 1453 | |
| 1454 template <> | |
| 1455 class MarkCompactMarkingVisitor::ObjectStatsTracker< | |
| 1456 MarkCompactMarkingVisitor::kVisitMap> { | |
| 1457 public: | |
| 1458 static inline void Visit(Map* map, HeapObject* obj) { | |
| 1459 Heap* heap = map->GetHeap(); | |
| 1460 Map* map_obj = Map::cast(obj); | |
| 1461 DCHECK(map->instance_type() == MAP_TYPE); | |
| 1462 DescriptorArray* array = map_obj->instance_descriptors(); | |
| 1463 if (map_obj->owns_descriptors() && | |
| 1464 array != heap->empty_descriptor_array()) { | |
| 1465 int fixed_array_size = array->Size(); | |
| 1466 heap->object_stats_->RecordFixedArraySubTypeStats( | |
| 1467 DESCRIPTOR_ARRAY_SUB_TYPE, fixed_array_size); | |
| 1468 } | |
| 1469 if (TransitionArray::IsFullTransitionArray(map_obj->raw_transitions())) { | |
| 1470 int fixed_array_size = | |
| 1471 TransitionArray::cast(map_obj->raw_transitions())->Size(); | |
| 1472 heap->object_stats_->RecordFixedArraySubTypeStats( | |
| 1473 TRANSITION_ARRAY_SUB_TYPE, fixed_array_size); | |
| 1474 } | |
| 1475 if (map_obj->has_code_cache()) { | |
| 1476 CodeCache* cache = CodeCache::cast(map_obj->code_cache()); | |
| 1477 heap->object_stats_->RecordFixedArraySubTypeStats( | |
| 1478 MAP_CODE_CACHE_SUB_TYPE, cache->default_cache()->Size()); | |
| 1479 if (!cache->normal_type_cache()->IsUndefined()) { | |
| 1480 heap->object_stats_->RecordFixedArraySubTypeStats( | |
| 1481 MAP_CODE_CACHE_SUB_TYPE, | |
| 1482 FixedArray::cast(cache->normal_type_cache())->Size()); | |
| 1483 } | |
| 1484 } | |
| 1485 ObjectStatsVisitBase(kVisitMap, map, obj); | |
| 1486 } | |
| 1487 }; | 1394 }; |
| 1488 | 1395 |
| 1489 | 1396 |
| 1490 template <> | |
| 1491 class MarkCompactMarkingVisitor::ObjectStatsTracker< | |
| 1492 MarkCompactMarkingVisitor::kVisitCode> { | |
| 1493 public: | |
| 1494 static inline void Visit(Map* map, HeapObject* obj) { | |
| 1495 Heap* heap = map->GetHeap(); | |
| 1496 int object_size = obj->Size(); | |
| 1497 DCHECK(map->instance_type() == CODE_TYPE); | |
| 1498 Code* code_obj = Code::cast(obj); | |
| 1499 heap->object_stats_->RecordCodeSubTypeStats( | |
| 1500 code_obj->kind(), code_obj->GetAge(), object_size); | |
| 1501 ObjectStatsVisitBase(kVisitCode, map, obj); | |
| 1502 } | |
| 1503 }; | |
| 1504 | |
| 1505 | |
| 1506 template <> | |
| 1507 class MarkCompactMarkingVisitor::ObjectStatsTracker< | |
| 1508 MarkCompactMarkingVisitor::kVisitSharedFunctionInfo> { | |
| 1509 public: | |
| 1510 static inline void Visit(Map* map, HeapObject* obj) { | |
| 1511 Heap* heap = map->GetHeap(); | |
| 1512 SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj); | |
| 1513 if (sfi->scope_info() != heap->empty_fixed_array()) { | |
| 1514 heap->object_stats_->RecordFixedArraySubTypeStats( | |
| 1515 SCOPE_INFO_SUB_TYPE, FixedArray::cast(sfi->scope_info())->Size()); | |
| 1516 } | |
| 1517 ObjectStatsVisitBase(kVisitSharedFunctionInfo, map, obj); | |
| 1518 } | |
| 1519 }; | |
| 1520 | |
| 1521 | |
| 1522 template <> | |
| 1523 class MarkCompactMarkingVisitor::ObjectStatsTracker< | |
| 1524 MarkCompactMarkingVisitor::kVisitFixedArray> { | |
| 1525 public: | |
| 1526 static inline void Visit(Map* map, HeapObject* obj) { | |
| 1527 Heap* heap = map->GetHeap(); | |
| 1528 FixedArray* fixed_array = FixedArray::cast(obj); | |
| 1529 if (fixed_array == heap->string_table()) { | |
| 1530 heap->object_stats_->RecordFixedArraySubTypeStats(STRING_TABLE_SUB_TYPE, | |
| 1531 fixed_array->Size()); | |
| 1532 } | |
| 1533 ObjectStatsVisitBase(kVisitFixedArray, map, obj); | |
| 1534 } | |
| 1535 }; | |
| 1536 | |
| 1537 | |
| 1538 void MarkCompactMarkingVisitor::Initialize() { | 1397 void MarkCompactMarkingVisitor::Initialize() { |
| 1539 StaticMarkingVisitor<MarkCompactMarkingVisitor>::Initialize(); | 1398 StaticMarkingVisitor<MarkCompactMarkingVisitor>::Initialize(); |
| 1540 | 1399 |
| 1541 table_.Register(kVisitJSRegExp, &VisitRegExpAndFlushCode); | 1400 table_.Register(kVisitJSRegExp, &VisitRegExpAndFlushCode); |
| 1542 | 1401 |
| 1543 if (FLAG_track_gc_object_stats) { | 1402 if (FLAG_track_gc_object_stats) { |
| 1544 // Copy the visitor table to make call-through possible. | 1403 ObjectStatsVisitor::Initialize(&table_); |
| 1545 non_count_table_.CopyFrom(&table_); | |
| 1546 #define VISITOR_ID_COUNT_FUNCTION(id) \ | |
| 1547 table_.Register(kVisit##id, ObjectStatsTracker<kVisit##id>::Visit); | |
| 1548 VISITOR_ID_LIST(VISITOR_ID_COUNT_FUNCTION) | |
| 1549 #undef VISITOR_ID_COUNT_FUNCTION | |
| 1550 } | 1404 } |
| 1551 } | 1405 } |
| 1552 | 1406 |
| 1553 | 1407 |
| 1554 VisitorDispatchTable<MarkCompactMarkingVisitor::Callback> | |
| 1555 MarkCompactMarkingVisitor::non_count_table_; | |
| 1556 | |
| 1557 | |
| 1558 class CodeMarkingVisitor : public ThreadVisitor { | 1408 class CodeMarkingVisitor : public ThreadVisitor { |
| 1559 public: | 1409 public: |
| 1560 explicit CodeMarkingVisitor(MarkCompactCollector* collector) | 1410 explicit CodeMarkingVisitor(MarkCompactCollector* collector) |
| 1561 : collector_(collector) {} | 1411 : collector_(collector) {} |
| 1562 | 1412 |
| 1563 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 1413 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
| 1564 collector_->PrepareThreadForCodeFlushing(isolate, top); | 1414 collector_->PrepareThreadForCodeFlushing(isolate, top); |
| 1565 } | 1415 } |
| 1566 | 1416 |
| 1567 private: | 1417 private: |
| (...skipping 3248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4816 SlotsBuffer* buffer = *buffer_address; | 4666 SlotsBuffer* buffer = *buffer_address; |
| 4817 while (buffer != NULL) { | 4667 while (buffer != NULL) { |
| 4818 SlotsBuffer* next_buffer = buffer->next(); | 4668 SlotsBuffer* next_buffer = buffer->next(); |
| 4819 DeallocateBuffer(buffer); | 4669 DeallocateBuffer(buffer); |
| 4820 buffer = next_buffer; | 4670 buffer = next_buffer; |
| 4821 } | 4671 } |
| 4822 *buffer_address = NULL; | 4672 *buffer_address = NULL; |
| 4823 } | 4673 } |
| 4824 } // namespace internal | 4674 } // namespace internal |
| 4825 } // namespace v8 | 4675 } // namespace v8 |
| OLD | NEW |