OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/scavenger.h" | 5 #include "vm/scavenger.h" |
6 | 6 |
7 #include "vm/dart.h" | 7 #include "vm/dart.h" |
8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
9 #include "vm/object.h" | 9 #include "vm/object.h" |
10 #include "vm/stack_frame.h" | 10 #include "vm/stack_frame.h" |
11 #include "vm/verifier.h" | 11 #include "vm/verifier.h" |
12 #include "vm/visitor.h" | 12 #include "vm/visitor.h" |
13 | 13 |
14 namespace dart { | 14 namespace dart { |
15 | 15 |
| 16 enum { |
| 17 kForwardingMask = 3, |
| 18 kNotForwarded = 1, // Tagged pointer. |
| 19 kForwarded = 3, // Tagged pointer and forwarding bit set. |
| 20 }; |
| 21 |
| 22 |
| 23 static inline bool IsForwarding(uword header) { |
| 24 uword bits = header & kForwardingMask; |
| 25 ASSERT((bits == kNotForwarded) || (bits == kForwarded)); |
| 26 return bits == kForwarded; |
| 27 } |
| 28 |
| 29 |
| 30 static inline uword ForwardedAddr(uword header) { |
| 31 ASSERT(IsForwarding(header)); |
| 32 return header & ~kForwardingMask; |
| 33 } |
| 34 |
| 35 |
| 36 static inline void ForwardTo(uword orignal, uword target) { |
| 37 // Make sure forwarding can be encoded. |
| 38 ASSERT((target & kForwardingMask) == 0); |
| 39 *reinterpret_cast<uword*>(orignal) = target | kForwarded; |
| 40 } |
| 41 |
| 42 |
16 class ScavengerVisitor : public ObjectPointerVisitor { | 43 class ScavengerVisitor : public ObjectPointerVisitor { |
17 public: | 44 public: |
18 explicit ScavengerVisitor(Scavenger* scavenger) | 45 explicit ScavengerVisitor(Scavenger* scavenger) |
19 : scavenger_(scavenger), | 46 : scavenger_(scavenger), |
20 heap_(scavenger->heap_), | 47 heap_(scavenger->heap_), |
21 vm_heap_(Dart::vm_isolate()->heap()) {} | 48 vm_heap_(Dart::vm_isolate()->heap()) {} |
22 | 49 |
23 void VisitPointers(RawObject** first, RawObject** last) { | 50 void VisitPointers(RawObject** first, RawObject** last) { |
24 for (RawObject** current = first; current <= last; current++) { | 51 for (RawObject** current = first; current <= last; current++) { |
25 ScavengePointer(current); | 52 ScavengePointer(current); |
26 } | 53 } |
27 } | 54 } |
28 | 55 |
29 private: | 56 private: |
30 enum { | |
31 kForwardingMask = 3, | |
32 kNotForwarded = 1, // Tagged pointer. | |
33 kForwarded = 3, // Tagged pointer and forwarding bit set. | |
34 }; | |
35 | |
36 static inline bool IsForwarding(uword header) { | |
37 uword bits = header & kForwardingMask; | |
38 ASSERT((bits == kNotForwarded) || (bits == kForwarded)); | |
39 return bits == kForwarded; | |
40 } | |
41 | |
42 static inline uword ForwardedAddr(uword header) { | |
43 ASSERT(IsForwarding(header)); | |
44 return header & ~kForwardingMask; | |
45 } | |
46 | |
47 static inline void ForwardTo(uword orignal, uword target) { | |
48 // Make sure forwarding can be encoded. | |
49 ASSERT((target & kForwardingMask) == 0); | |
50 *reinterpret_cast<uword*>(orignal) = target | kForwarded; | |
51 } | |
52 | |
53 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { | 57 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { |
54 // TODO(iposva): Implement store buffers. | 58 // TODO(iposva): Implement store buffers. |
55 } | 59 } |
56 | 60 |
57 void ScavengePointer(RawObject** p) { | 61 void ScavengePointer(RawObject** p) { |
58 RawObject* raw_obj = *p; | 62 RawObject* raw_obj = *p; |
59 | 63 |
60 // Fast exit if the raw object is a Smi. | 64 // Fast exit if the raw object is a Smi. |
61 if (!raw_obj->IsHeapObject()) return; | 65 if (!raw_obj->IsHeapObject()) return; |
62 | 66 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 // Update the reference. | 102 // Update the reference. |
99 RawObject* new_obj = RawObject::FromAddr(new_addr); | 103 RawObject* new_obj = RawObject::FromAddr(new_addr); |
100 *p = new_obj; | 104 *p = new_obj; |
101 // Update the store buffer as needed. | 105 // Update the store buffer as needed. |
102 UpdateStoreBuffer(p, new_obj); | 106 UpdateStoreBuffer(p, new_obj); |
103 } | 107 } |
104 | 108 |
105 Scavenger* scavenger_; | 109 Scavenger* scavenger_; |
106 Heap* heap_; | 110 Heap* heap_; |
107 Heap* vm_heap_; | 111 Heap* vm_heap_; |
| 112 |
| 113 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); |
108 }; | 114 }; |
109 | 115 |
110 | 116 |
| 117 class ScavengerWeakVisitor : public ObjectPointerVisitor { |
| 118 public: |
| 119 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { |
| 120 } |
| 121 |
| 122 void VisitPointers(RawObject** first, RawObject** last) { |
| 123 for (RawObject** current = first; current <= last; current++) { |
| 124 RawObject* raw_obj = *current; |
| 125 ASSERT(raw_obj->IsHeapObject()); |
| 126 uword raw_addr = RawObject::ToAddr(raw_obj); |
| 127 if (scavenger_->from_->Contains(raw_addr)) { |
| 128 uword header = *reinterpret_cast<uword*>(raw_addr); |
| 129 if (IsForwarding(header)) { |
| 130 *current = RawObject::FromAddr(ForwardedAddr(header)); |
| 131 } else { |
| 132 *current = Object::null(); |
| 133 } |
| 134 } |
| 135 } |
| 136 } |
| 137 |
| 138 private: |
| 139 Scavenger* scavenger_; |
| 140 |
| 141 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor); |
| 142 }; |
| 143 |
| 144 |
111 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) | 145 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) |
112 : heap_(heap), | 146 : heap_(heap), |
113 object_alignment_(object_alignment), | 147 object_alignment_(object_alignment), |
114 count_(0), | 148 count_(0), |
115 scavenging_(false) { | 149 scavenging_(false) { |
116 // Allocate the virtual memory for this scavenge heap. | 150 // Allocate the virtual memory for this scavenge heap. |
117 space_ = VirtualMemory::Reserve(max_capacity); | 151 space_ = VirtualMemory::Reserve(max_capacity); |
118 ASSERT(space_ != NULL); | 152 ASSERT(space_ != NULL); |
119 | 153 |
120 // Allocate the entire space at the beginning. | 154 // Allocate the entire space at the beginning. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 | 194 |
161 | 195 |
162 void Scavenger::Epilogue() { | 196 void Scavenger::Epilogue() { |
163 #if defined(DEBUG) | 197 #if defined(DEBUG) |
164 memset(from_->pointer(), 0xf3, from_->size()); | 198 memset(from_->pointer(), 0xf3, from_->size()); |
165 #endif // defined(DEBUG) | 199 #endif // defined(DEBUG) |
166 } | 200 } |
167 | 201 |
168 | 202 |
169 void Scavenger::IterateRoots(Isolate* isolate, ObjectPointerVisitor* visitor) { | 203 void Scavenger::IterateRoots(Isolate* isolate, ObjectPointerVisitor* visitor) { |
170 isolate->VisitObjectPointers(visitor, | 204 isolate->VisitStrongObjectPointers(visitor, |
171 StackFrameIterator::kDontValidateFrames); | 205 StackFrameIterator::kDontValidateFrames); |
172 heap_->IterateOldPointers(visitor); | 206 heap_->IterateOldPointers(visitor); |
173 } | 207 } |
174 | 208 |
175 | 209 |
| 210 void Scavenger::IterateWeakRoots(Isolate* isolate, |
| 211 ObjectPointerVisitor* visitor) { |
| 212 isolate->VisitWeakObjectPointers(visitor); |
| 213 } |
| 214 |
| 215 |
176 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { | 216 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { |
177 uword resolved_top = FirstObjectStart(); | 217 uword resolved_top = FirstObjectStart(); |
178 // Iterate until all work has been drained. | 218 // Iterate until all work has been drained. |
179 while (resolved_top < top_) { | 219 while (resolved_top < top_) { |
180 RawObject* raw_obj = RawObject::FromAddr(resolved_top); | 220 RawObject* raw_obj = RawObject::FromAddr(resolved_top); |
181 resolved_top += raw_obj->VisitPointers(visitor); | 221 resolved_top += raw_obj->VisitPointers(visitor); |
182 } | 222 } |
183 } | 223 } |
184 | 224 |
185 | 225 |
(...skipping 13 matching lines...) Expand all Loading... |
199 Isolate* isolate = Isolate::Current(); | 239 Isolate* isolate = Isolate::Current(); |
200 NoHandleScope no_handles(isolate); | 240 NoHandleScope no_handles(isolate); |
201 | 241 |
202 Timer timer(FLAG_verbose_gc, "Scavenge"); | 242 Timer timer(FLAG_verbose_gc, "Scavenge"); |
203 timer.Start(); | 243 timer.Start(); |
204 // Setup the visitor and run a scavenge. | 244 // Setup the visitor and run a scavenge. |
205 ScavengerVisitor visitor(this); | 245 ScavengerVisitor visitor(this); |
206 Prologue(); | 246 Prologue(); |
207 IterateRoots(isolate, &visitor); | 247 IterateRoots(isolate, &visitor); |
208 ProcessToSpace(&visitor); | 248 ProcessToSpace(&visitor); |
| 249 ScavengerWeakVisitor weak_visitor(this); |
| 250 IterateWeakRoots(isolate, &weak_visitor); |
209 Epilogue(); | 251 Epilogue(); |
210 timer.Stop(); | 252 timer.Stop(); |
211 if (FLAG_verbose_gc) { | 253 if (FLAG_verbose_gc) { |
212 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); | 254 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); |
213 } | 255 } |
214 | 256 |
215 count_++; | 257 count_++; |
216 // Done scavenging. Reset the marker. | 258 // Done scavenging. Reset the marker. |
217 ASSERT(scavenging_); | 259 ASSERT(scavenging_); |
218 scavenging_ = false; | 260 scavenging_ = false; |
219 } | 261 } |
220 | 262 |
221 } // namespace dart | 263 } // namespace dart |
OLD | NEW |