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/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 1557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1568 // objects lie between a 'front' mark and a 'rear' mark that is | 1568 // objects lie between a 'front' mark and a 'rear' mark that is |
1569 // updated as a side effect of promoting an object. | 1569 // updated as a side effect of promoting an object. |
1570 // | 1570 // |
1571 // There is guaranteed to be enough room at the top of the to space | 1571 // There is guaranteed to be enough room at the top of the to space |
1572 // for the addresses of promoted objects: every object promoted | 1572 // for the addresses of promoted objects: every object promoted |
1573 // frees up its size in bytes from the top of the new space, and | 1573 // frees up its size in bytes from the top of the new space, and |
1574 // objects are at least one pointer in size. | 1574 // objects are at least one pointer in size. |
1575 Address new_space_front = new_space_.ToSpaceStart(); | 1575 Address new_space_front = new_space_.ToSpaceStart(); |
1576 promotion_queue_.Initialize(); | 1576 promotion_queue_.Initialize(); |
1577 | 1577 |
1578 #ifdef DEBUG | |
1579 store_buffer()->Clean(); | |
1580 #endif | |
1581 | |
1582 ScavengeVisitor scavenge_visitor(this); | 1578 ScavengeVisitor scavenge_visitor(this); |
1583 // Copy roots. | 1579 // Copy roots. |
1584 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); | 1580 IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); |
1585 | 1581 |
1586 // Copy objects reachable from the old generation. | 1582 // Copy objects reachable from the old generation. |
1587 { | 1583 { |
1588 StoreBufferRebuildScope scope(this, store_buffer(), | 1584 StoreBufferRebuildScope scope(this, store_buffer(), |
1589 &ScavengeStoreBufferCallback); | 1585 &ScavengeStoreBufferCallback); |
1590 store_buffer()->IteratePointersToNewSpace(&ScavengeObject); | 1586 store_buffer()->IteratePointersToNewSpace(&ScavengeObject); |
1591 } | 1587 } |
(...skipping 3362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4954 } else if (record_slots && | 4950 } else if (record_slots && |
4955 MarkCompactCollector::IsOnEvacuationCandidate(object)) { | 4951 MarkCompactCollector::IsOnEvacuationCandidate(object)) { |
4956 mark_compact_collector()->RecordSlot(slot, slot, object); | 4952 mark_compact_collector()->RecordSlot(slot, slot, object); |
4957 } | 4953 } |
4958 } | 4954 } |
4959 slot_address += kPointerSize; | 4955 slot_address += kPointerSize; |
4960 } | 4956 } |
4961 } | 4957 } |
4962 | 4958 |
4963 | 4959 |
4964 #ifdef DEBUG | |
4965 typedef bool (*CheckStoreBufferFilter)(Object** addr); | |
4966 | |
4967 | |
4968 bool IsAMapPointerAddress(Object** addr) { | |
4969 uintptr_t a = reinterpret_cast<uintptr_t>(addr); | |
4970 int mod = a % Map::kSize; | |
4971 return mod >= Map::kPointerFieldsBeginOffset && | |
4972 mod < Map::kPointerFieldsEndOffset; | |
4973 } | |
4974 | |
4975 | |
4976 bool EverythingsAPointer(Object** addr) { return true; } | |
4977 | |
4978 | |
4979 static void CheckStoreBuffer(Heap* heap, Object** current, Object** limit, | |
4980 Object**** store_buffer_position, | |
4981 Object*** store_buffer_top, | |
4982 CheckStoreBufferFilter filter, | |
4983 Address special_garbage_start, | |
4984 Address special_garbage_end) { | |
4985 Map* free_space_map = heap->free_space_map(); | |
4986 for (; current < limit; current++) { | |
4987 Object* o = *current; | |
4988 Address current_address = reinterpret_cast<Address>(current); | |
4989 // Skip free space. | |
4990 if (o == free_space_map) { | |
4991 Address current_address = reinterpret_cast<Address>(current); | |
4992 FreeSpace* free_space = | |
4993 FreeSpace::cast(HeapObject::FromAddress(current_address)); | |
4994 int skip = free_space->Size(); | |
4995 DCHECK(current_address + skip <= reinterpret_cast<Address>(limit)); | |
4996 DCHECK(skip > 0); | |
4997 current_address += skip - kPointerSize; | |
4998 current = reinterpret_cast<Object**>(current_address); | |
4999 continue; | |
5000 } | |
5001 // Skip the current linear allocation space between top and limit which is | |
5002 // unmarked with the free space map, but can contain junk. | |
5003 if (current_address == special_garbage_start && | |
5004 special_garbage_end != special_garbage_start) { | |
5005 current_address = special_garbage_end - kPointerSize; | |
5006 current = reinterpret_cast<Object**>(current_address); | |
5007 continue; | |
5008 } | |
5009 if (!(*filter)(current)) continue; | |
5010 DCHECK(current_address < special_garbage_start || | |
5011 current_address >= special_garbage_end); | |
5012 DCHECK(reinterpret_cast<uintptr_t>(o) != kFreeListZapValue); | |
5013 // We have to check that the pointer does not point into new space | |
5014 // without trying to cast it to a heap object since the hash field of | |
5015 // a string can contain values like 1 and 3 which are tagged null | |
5016 // pointers. | |
5017 if (!heap->InNewSpace(o)) continue; | |
5018 while (**store_buffer_position < current && | |
5019 *store_buffer_position < store_buffer_top) { | |
5020 (*store_buffer_position)++; | |
5021 } | |
5022 if (**store_buffer_position != current || | |
5023 *store_buffer_position == store_buffer_top) { | |
5024 Object** obj_start = current; | |
5025 while (!(*obj_start)->IsMap()) obj_start--; | |
5026 UNREACHABLE(); | |
5027 } | |
5028 } | |
5029 } | |
5030 | |
5031 | |
5032 // Check that the store buffer contains all intergenerational pointers by | |
5033 // scanning a page and ensuring that all pointers to young space are in the | |
5034 // store buffer. | |
5035 void Heap::OldPointerSpaceCheckStoreBuffer() { | |
5036 OldSpace* space = old_pointer_space(); | |
5037 PageIterator pages(space); | |
5038 | |
5039 store_buffer()->SortUniq(); | |
5040 | |
5041 while (pages.has_next()) { | |
5042 Page* page = pages.next(); | |
5043 Object** current = reinterpret_cast<Object**>(page->area_start()); | |
5044 | |
5045 Address end = page->area_end(); | |
5046 | |
5047 Object*** store_buffer_position = store_buffer()->Start(); | |
5048 Object*** store_buffer_top = store_buffer()->Top(); | |
5049 | |
5050 Object** limit = reinterpret_cast<Object**>(end); | |
5051 CheckStoreBuffer(this, current, limit, &store_buffer_position, | |
5052 store_buffer_top, &EverythingsAPointer, space->top(), | |
5053 space->limit()); | |
5054 } | |
5055 } | |
5056 | |
5057 | |
5058 void Heap::MapSpaceCheckStoreBuffer() { | |
5059 MapSpace* space = map_space(); | |
5060 PageIterator pages(space); | |
5061 | |
5062 store_buffer()->SortUniq(); | |
5063 | |
5064 while (pages.has_next()) { | |
5065 Page* page = pages.next(); | |
5066 Object** current = reinterpret_cast<Object**>(page->area_start()); | |
5067 | |
5068 Address end = page->area_end(); | |
5069 | |
5070 Object*** store_buffer_position = store_buffer()->Start(); | |
5071 Object*** store_buffer_top = store_buffer()->Top(); | |
5072 | |
5073 Object** limit = reinterpret_cast<Object**>(end); | |
5074 CheckStoreBuffer(this, current, limit, &store_buffer_position, | |
5075 store_buffer_top, &IsAMapPointerAddress, space->top(), | |
5076 space->limit()); | |
5077 } | |
5078 } | |
5079 | |
5080 | |
5081 void Heap::LargeObjectSpaceCheckStoreBuffer() { | |
5082 LargeObjectIterator it(lo_space()); | |
5083 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { | |
5084 // We only have code, sequential strings, or fixed arrays in large | |
5085 // object space, and only fixed arrays can possibly contain pointers to | |
5086 // the young generation. | |
5087 if (object->IsFixedArray()) { | |
5088 Object*** store_buffer_position = store_buffer()->Start(); | |
5089 Object*** store_buffer_top = store_buffer()->Top(); | |
5090 Object** current = reinterpret_cast<Object**>(object->address()); | |
5091 Object** limit = | |
5092 reinterpret_cast<Object**>(object->address() + object->Size()); | |
5093 CheckStoreBuffer(this, current, limit, &store_buffer_position, | |
5094 store_buffer_top, &EverythingsAPointer, NULL, NULL); | |
5095 } | |
5096 } | |
5097 } | |
5098 #endif | |
5099 | |
5100 | |
5101 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) { | 4960 void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) { |
5102 IterateStrongRoots(v, mode); | 4961 IterateStrongRoots(v, mode); |
5103 IterateWeakRoots(v, mode); | 4962 IterateWeakRoots(v, mode); |
5104 } | 4963 } |
5105 | 4964 |
5106 | 4965 |
5107 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { | 4966 void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { |
5108 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex])); | 4967 v->VisitPointer(reinterpret_cast<Object**>(&roots_[kStringTableRootIndex])); |
5109 v->Synchronize(VisitorSynchronization::kStringTable); | 4968 v->Synchronize(VisitorSynchronization::kStringTable); |
5110 if (mode != VISIT_ALL_IN_SCAVENGE && mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { | 4969 if (mode != VISIT_ALL_IN_SCAVENGE && mode != VISIT_ALL_IN_SWEEP_NEWSPACE) { |
(...skipping 1467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6578 static_cast<int>(object_sizes_last_time_[index])); | 6437 static_cast<int>(object_sizes_last_time_[index])); |
6579 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) | 6438 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) |
6580 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 6439 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
6581 | 6440 |
6582 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 6441 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
6583 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 6442 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
6584 ClearObjectStats(); | 6443 ClearObjectStats(); |
6585 } | 6444 } |
6586 } | 6445 } |
6587 } // namespace v8::internal | 6446 } // namespace v8::internal |
OLD | NEW |