OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 marking_stack_.Push(map); | 1070 marking_stack_.Push(map); |
1071 } | 1071 } |
1072 } else { | 1072 } else { |
1073 SetMark(object); | 1073 SetMark(object); |
1074 marking_stack_.Push(object); | 1074 marking_stack_.Push(object); |
1075 } | 1075 } |
1076 } | 1076 } |
1077 | 1077 |
1078 | 1078 |
1079 void MarkCompactCollector::MarkMapContents(Map* map) { | 1079 void MarkCompactCollector::MarkMapContents(Map* map) { |
| 1080 // Mark prototype transitions array but don't push it into marking stack. |
| 1081 // This will make references from it weak. We will clean dead prototype |
| 1082 // transitions in ClearNonLiveTransitions. |
| 1083 FixedArray* prototype_transitions = map->unchecked_prototype_transitions(); |
| 1084 if (!prototype_transitions->IsMarked()) SetMark(prototype_transitions); |
| 1085 |
1080 MarkDescriptorArray(reinterpret_cast<DescriptorArray*>( | 1086 MarkDescriptorArray(reinterpret_cast<DescriptorArray*>( |
1081 *HeapObject::RawField(map, Map::kInstanceDescriptorsOffset))); | 1087 *HeapObject::RawField(map, Map::kInstanceDescriptorsOffset))); |
1082 | 1088 |
1083 // Mark the Object* fields of the Map. | 1089 // Mark the Object* fields of the Map. |
1084 // Since the descriptor array has been marked already, it is fine | 1090 // Since the descriptor array has been marked already, it is fine |
1085 // that one of these fields contains a pointer to it. | 1091 // that one of these fields contains a pointer to it. |
1086 Object** start_slot = HeapObject::RawField(map, | 1092 Object** start_slot = HeapObject::RawField(map, |
1087 Map::kPointerFieldsBeginOffset); | 1093 Map::kPointerFieldsBeginOffset); |
1088 | 1094 |
1089 Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset); | 1095 Object** end_slot = HeapObject::RawField(map, Map::kPointerFieldsEndOffset); |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1487 | 1493 |
1488 // Safe to use during marking phase only. | 1494 // Safe to use during marking phase only. |
1489 bool MarkCompactCollector::SafeIsMap(HeapObject* object) { | 1495 bool MarkCompactCollector::SafeIsMap(HeapObject* object) { |
1490 MapWord metamap = object->map_word(); | 1496 MapWord metamap = object->map_word(); |
1491 metamap.ClearMark(); | 1497 metamap.ClearMark(); |
1492 return metamap.ToMap()->instance_type() == MAP_TYPE; | 1498 return metamap.ToMap()->instance_type() == MAP_TYPE; |
1493 } | 1499 } |
1494 | 1500 |
1495 | 1501 |
1496 void MarkCompactCollector::ClearNonLiveTransitions() { | 1502 void MarkCompactCollector::ClearNonLiveTransitions() { |
1497 HeapObjectIterator map_iterator(heap() ->map_space(), &SizeOfMarkedObject); | 1503 HeapObjectIterator map_iterator(heap()->map_space(), &SizeOfMarkedObject); |
1498 // Iterate over the map space, setting map transitions that go from | 1504 // Iterate over the map space, setting map transitions that go from |
1499 // a marked map to an unmarked map to null transitions. At the same time, | 1505 // a marked map to an unmarked map to null transitions. At the same time, |
1500 // set all the prototype fields of maps back to their original value, | 1506 // set all the prototype fields of maps back to their original value, |
1501 // dropping the back pointers temporarily stored in the prototype field. | 1507 // dropping the back pointers temporarily stored in the prototype field. |
1502 // Setting the prototype field requires following the linked list of | 1508 // Setting the prototype field requires following the linked list of |
1503 // back pointers, reversing them all at once. This allows us to find | 1509 // back pointers, reversing them all at once. This allows us to find |
1504 // those maps with map transitions that need to be nulled, and only | 1510 // those maps with map transitions that need to be nulled, and only |
1505 // scan the descriptor arrays of those maps, not all maps. | 1511 // scan the descriptor arrays of those maps, not all maps. |
1506 // All of these actions are carried out only on maps of JSObjects | 1512 // All of these actions are carried out only on maps of JSObjects |
1507 // and related subtypes. | 1513 // and related subtypes. |
1508 for (HeapObject* obj = map_iterator.next(); | 1514 for (HeapObject* obj = map_iterator.next(); |
1509 obj != NULL; obj = map_iterator.next()) { | 1515 obj != NULL; obj = map_iterator.next()) { |
1510 Map* map = reinterpret_cast<Map*>(obj); | 1516 Map* map = reinterpret_cast<Map*>(obj); |
1511 if (!map->IsMarked() && map->IsByteArray()) continue; | 1517 if (!map->IsMarked() && map->IsByteArray()) continue; |
1512 | 1518 |
1513 ASSERT(SafeIsMap(map)); | 1519 ASSERT(SafeIsMap(map)); |
1514 // Only JSObject and subtypes have map transitions and back pointers. | 1520 // Only JSObject and subtypes have map transitions and back pointers. |
1515 if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; | 1521 if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; |
1516 if (map->instance_type() > JS_FUNCTION_TYPE) continue; | 1522 if (map->instance_type() > JS_FUNCTION_TYPE) continue; |
1517 | 1523 |
1518 if (map->IsMarked() && map->attached_to_shared_function_info()) { | 1524 if (map->IsMarked() && map->attached_to_shared_function_info()) { |
1519 // This map is used for inobject slack tracking and has been detached | 1525 // This map is used for inobject slack tracking and has been detached |
1520 // from SharedFunctionInfo during the mark phase. | 1526 // from SharedFunctionInfo during the mark phase. |
1521 // Since it survived the GC, reattach it now. | 1527 // Since it survived the GC, reattach it now. |
1522 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); | 1528 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); |
1523 } | 1529 } |
1524 | 1530 |
| 1531 // Clear dead prototype transitions. |
| 1532 FixedArray* prototype_transitions = map->unchecked_prototype_transitions(); |
| 1533 if (prototype_transitions->length() > 0) { |
| 1534 int finger = Smi::cast(prototype_transitions->get(0))->value(); |
| 1535 int new_finger = 1; |
| 1536 for (int i = 1; i < finger; i += 2) { |
| 1537 Object* prototype = prototype_transitions->get(i); |
| 1538 Object* cached_map = prototype_transitions->get(i + 1); |
| 1539 if (HeapObject::cast(prototype)->IsMarked() && |
| 1540 HeapObject::cast(cached_map)->IsMarked()) { |
| 1541 if (new_finger != i) { |
| 1542 prototype_transitions->set_unchecked(heap_, |
| 1543 new_finger, |
| 1544 prototype, |
| 1545 UPDATE_WRITE_BARRIER); |
| 1546 prototype_transitions->set_unchecked(heap_, |
| 1547 new_finger + 1, |
| 1548 cached_map, |
| 1549 SKIP_WRITE_BARRIER); |
| 1550 } |
| 1551 new_finger += 2; |
| 1552 } |
| 1553 } |
| 1554 |
| 1555 // Fill slots that became free with undefined value. |
| 1556 Object* undefined = heap()->raw_unchecked_undefined_value(); |
| 1557 for (int i = new_finger; i < finger; i++) { |
| 1558 prototype_transitions->set_unchecked(heap_, |
| 1559 i, |
| 1560 undefined, |
| 1561 SKIP_WRITE_BARRIER); |
| 1562 } |
| 1563 prototype_transitions->set_unchecked(0, Smi::FromInt(new_finger)); |
| 1564 } |
| 1565 |
1525 // Follow the chain of back pointers to find the prototype. | 1566 // Follow the chain of back pointers to find the prototype. |
1526 Map* current = map; | 1567 Map* current = map; |
1527 while (SafeIsMap(current)) { | 1568 while (SafeIsMap(current)) { |
1528 current = reinterpret_cast<Map*>(current->prototype()); | 1569 current = reinterpret_cast<Map*>(current->prototype()); |
1529 ASSERT(current->IsHeapObject()); | 1570 ASSERT(current->IsHeapObject()); |
1530 } | 1571 } |
1531 Object* real_prototype = current; | 1572 Object* real_prototype = current; |
1532 | 1573 |
1533 // Follow back pointers, setting them to prototype, | 1574 // Follow back pointers, setting them to prototype, |
1534 // clearing map transitions when necessary. | 1575 // clearing map transitions when necessary. |
(...skipping 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3090 } | 3131 } |
3091 | 3132 |
3092 | 3133 |
3093 void MarkCompactCollector::Initialize() { | 3134 void MarkCompactCollector::Initialize() { |
3094 StaticPointersToNewGenUpdatingVisitor::Initialize(); | 3135 StaticPointersToNewGenUpdatingVisitor::Initialize(); |
3095 StaticMarkingVisitor::Initialize(); | 3136 StaticMarkingVisitor::Initialize(); |
3096 } | 3137 } |
3097 | 3138 |
3098 | 3139 |
3099 } } // namespace v8::internal | 3140 } } // namespace v8::internal |
OLD | NEW |