Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: vm/scavenger.cc

Issue 9027017: - Promote objects from new gen to old space if they survived a scavenge. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« vm/scavenger.h ('K') | « vm/scavenger.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 63
64 // Fast exit if the raw object is a Smi. 64 // Fast exit if the raw object is a Smi.
65 if (!raw_obj->IsHeapObject()) return; 65 if (!raw_obj->IsHeapObject()) return;
66 66
67 uword raw_addr = RawObject::ToAddr(raw_obj); 67 uword raw_addr = RawObject::ToAddr(raw_obj);
68 // Objects should be contained in the heap. 68 // Objects should be contained in the heap.
69 // TODO(iposva): Add an appropriate assert here or in the return block 69 // TODO(iposva): Add an appropriate assert here or in the return block
70 // below. 70 // below.
71 // The scavenger is only interested in objects located in the from space. 71 // The scavenger is only interested in objects located in the from space.
72 if (!scavenger_->from_->Contains(raw_addr)) { 72 if (!scavenger_->from_->Contains(raw_addr)) {
73 // Addresses being visited cannot point in the to space. As this would
74 // either mean the pointer is being visited twice or this pointer has not
75 // been evacuated during the last scavenge. Both of these situations are
76 // an error.
77 ASSERT(!scavenger_->to_->Contains(raw_addr));
78 return; 73 return;
79 } 74 }
80 75
81 // Read the header word of the object and determine if the object has 76 // Read the header word of the object and determine if the object has
82 // already been copied. 77 // already been copied.
83 uword header = *reinterpret_cast<uword*>(raw_addr); 78 uword header = *reinterpret_cast<uword*>(raw_addr);
84 uword new_addr = 0; 79 uword new_addr = 0;
85 if (IsForwarding(header)) { 80 if (IsForwarding(header)) {
86 // Get the new location of the object. 81 // Get the new location of the object.
87 new_addr = ForwardedAddr(header); 82 new_addr = ForwardedAddr(header);
88 } else { 83 } else {
89 intptr_t size = raw_obj->Size(); 84 intptr_t size = raw_obj->Size();
90 // TODO(iposva): Check whether object should be promoted. 85 // Check whether object should be promoted.
91 new_addr = scavenger_->TryAllocate(size); 86 if (scavenger_->survivor_end_ <= raw_addr) {
87 // Not a survivor of a previous scavenge. Just copy the object into the
88 // to space.
89 new_addr = scavenger_->TryAllocate(size);
90 } else {
91 // TODO(iposva): Experiment with less aggressive promotion. For example
92 // a coin toss determines if an object is promoted or whether it should
93 // survive in this generation.
94 //
95 // This object is a survivor of a previous scavenge. Attempt to promote
96 // the object.
97 new_addr = heap_->TryAllocate(size, Heap::kOld);
98 if (new_addr != 0) {
99 // If promotion succeeded then we need to remember it so that it can
100 // be traversed later.
101 scavenger_->PushToPromotedStack(new_addr);
102 } else {
103 // Promotion did not succeed. Copy into the to space instead.
104 scavenger_->had_promotion_failure_ = true;
105 new_addr = scavenger_->TryAllocate(size);
106 }
107 }
92 // During a scavenge we always succeed to at least copy all of the 108 // During a scavenge we always succeed to at least copy all of the
93 // current objects to the to space. 109 // current objects to the to space.
94 ASSERT(new_addr != 0); 110 ASSERT(new_addr != 0);
95 // Copy the object to the new location. 111 // Copy the object to the new location.
96 memmove(reinterpret_cast<void*>(new_addr), 112 memmove(reinterpret_cast<void*>(new_addr),
97 reinterpret_cast<void*>(raw_addr), 113 reinterpret_cast<void*>(raw_addr),
98 size); 114 size);
99 // Remember forwarding address. 115 // Remember forwarding address.
100 ForwardTo(raw_addr, new_addr); 116 ForwardTo(raw_addr, new_addr);
101 } 117 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 uword middle = space_->start() + semi_space_size; 177 uword middle = space_->start() + semi_space_size;
162 from_ = new MemoryRegion(reinterpret_cast<void*>(middle), semi_space_size); 178 from_ = new MemoryRegion(reinterpret_cast<void*>(middle), semi_space_size);
163 179
164 // Make sure that the two semi-spaces are aligned properly. 180 // Make sure that the two semi-spaces are aligned properly.
165 ASSERT(Utils::IsAligned(to_->start(), kObjectAlignment)); 181 ASSERT(Utils::IsAligned(to_->start(), kObjectAlignment));
166 ASSERT(Utils::IsAligned(from_->start(), kObjectAlignment)); 182 ASSERT(Utils::IsAligned(from_->start(), kObjectAlignment));
167 183
168 // Setup local fields. 184 // Setup local fields.
169 top_ = FirstObjectStart(); 185 top_ = FirstObjectStart();
170 end_ = to_->end(); 186 end_ = to_->end();
187
188 survivor_end_ = FirstObjectStart();
189
171 #if defined(DEBUG) 190 #if defined(DEBUG)
172 memset(to_->pointer(), 0xf3, to_->size()); 191 memset(to_->pointer(), 0xf3, to_->size());
173 memset(from_->pointer(), 0xf3, from_->size()); 192 memset(from_->pointer(), 0xf3, from_->size());
174 #endif // defined(DEBUG) 193 #endif // defined(DEBUG)
175 } 194 }
176 195
177 196
178 Scavenger::~Scavenger() { 197 Scavenger::~Scavenger() {
179 delete to_; 198 delete to_;
180 delete from_; 199 delete from_;
181 delete space_; 200 delete space_;
182 } 201 }
183 202
184 203
185 void Scavenger::Prologue() { 204 void Scavenger::Prologue() {
186 // Flip the two semi-spaces so that to_ is always the space for allocating 205 // Flip the two semi-spaces so that to_ is always the space for allocating
187 // objects. 206 // objects.
188 MemoryRegion* temp = from_; 207 MemoryRegion* temp = from_;
189 from_ = to_; 208 from_ = to_;
190 to_ = temp; 209 to_ = temp;
191 top_ = FirstObjectStart(); 210 top_ = FirstObjectStart();
192 end_ = to_->end(); 211 end_ = to_->end();
193 } 212 }
194 213
195 214
196 void Scavenger::Epilogue() { 215 void Scavenger::Epilogue() {
216 // All objects in the to space have been copied from the from space at this
217 // moment.
218 survivor_end_ = top_;
219
197 #if defined(DEBUG) 220 #if defined(DEBUG)
198 memset(from_->pointer(), 0xf3, from_->size()); 221 memset(from_->pointer(), 0xf3, from_->size());
199 #endif // defined(DEBUG) 222 #endif // defined(DEBUG)
200 } 223 }
201 224
202 225
203 void Scavenger::IterateRoots(Isolate* isolate, ObjectPointerVisitor* visitor) { 226 void Scavenger::IterateRoots(Isolate* isolate, ObjectPointerVisitor* visitor) {
204 isolate->VisitStrongObjectPointers(visitor, 227 isolate->VisitStrongObjectPointers(visitor,
205 StackFrameIterator::kDontValidateFrames); 228 StackFrameIterator::kDontValidateFrames);
206 heap_->IterateOldPointers(visitor); 229 heap_->IterateOldPointers(visitor);
207 } 230 }
208 231
209 232
210 void Scavenger::IterateWeakRoots(Isolate* isolate, 233 void Scavenger::IterateWeakRoots(Isolate* isolate,
211 ObjectPointerVisitor* visitor) { 234 ObjectPointerVisitor* visitor) {
212 isolate->VisitWeakObjectPointers(visitor); 235 isolate->VisitWeakObjectPointers(visitor);
213 } 236 }
214 237
215 238
216 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { 239 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) {
217 uword resolved_top = FirstObjectStart(); 240 uword resolved_top = FirstObjectStart();
218 // Iterate until all work has been drained. 241 // Iterate until all work has been drained.
219 while (resolved_top < top_) { 242 while ((resolved_top < top_) || PromotedStackHasMore()) {
220 RawObject* raw_obj = RawObject::FromAddr(resolved_top); 243 while (resolved_top < top_) {
221 resolved_top += raw_obj->VisitPointers(visitor); 244 RawObject* raw_obj = RawObject::FromAddr(resolved_top);
245 resolved_top += raw_obj->VisitPointers(visitor);
246 }
247 while (PromotedStackHasMore()) {
248 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack());
249 // Resolve or copy all objects referred to by the current object. This
250 // can potentially push more objects on this stack as well as add more
251 // objects to be resolved in the to space.
252 raw_object->VisitPointers(visitor);
253 }
222 } 254 }
223 } 255 }
224 256
225 257
226 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { 258 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
227 uword cur = FirstObjectStart(); 259 uword cur = FirstObjectStart();
228 while (cur < top_) { 260 while (cur < top_) {
229 RawObject* raw_obj = RawObject::FromAddr(cur); 261 RawObject* raw_obj = RawObject::FromAddr(cur);
230 cur += raw_obj->VisitPointers(visitor); 262 cur += raw_obj->VisitPointers(visitor);
231 } 263 }
232 } 264 }
233 265
234 266
235 void Scavenger::Scavenge() { 267 void Scavenger::Scavenge() {
236 // Scavenging is not reentrant. Make sure that is the case. 268 // Scavenging is not reentrant. Make sure that is the case.
237 ASSERT(!scavenging_); 269 ASSERT(!scavenging_);
238 scavenging_ = true; 270 scavenging_ = true;
239 Isolate* isolate = Isolate::Current(); 271 Isolate* isolate = Isolate::Current();
240 NoHandleScope no_handles(isolate); 272 NoHandleScope no_handles(isolate);
241 273
274 if (FLAG_verify_before_gc) {
275 OS::PrintErr("Verifying before Scavenge... ");
276 heap_->Verify();
277 OS::PrintErr(" done.\n");
278 }
279
242 Timer timer(FLAG_verbose_gc, "Scavenge"); 280 Timer timer(FLAG_verbose_gc, "Scavenge");
243 timer.Start(); 281 timer.Start();
244 // Setup the visitor and run a scavenge. 282 // Setup the visitor and run a scavenge.
245 ScavengerVisitor visitor(this); 283 ScavengerVisitor visitor(this);
246 Prologue(); 284 Prologue();
247 IterateRoots(isolate, &visitor); 285 IterateRoots(isolate, &visitor);
248 ProcessToSpace(&visitor); 286 ProcessToSpace(&visitor);
249 ScavengerWeakVisitor weak_visitor(this); 287 ScavengerWeakVisitor weak_visitor(this);
250 IterateWeakRoots(isolate, &weak_visitor); 288 IterateWeakRoots(isolate, &weak_visitor);
251 Epilogue(); 289 Epilogue();
252 timer.Stop(); 290 timer.Stop();
253 if (FLAG_verbose_gc) { 291 if (FLAG_verbose_gc) {
254 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); 292 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime());
255 } 293 }
256 294
295 if (FLAG_verify_after_gc) {
296 OS::PrintErr("Verifying after Scavenge... ");
297 heap_->Verify();
298 OS::PrintErr(" done.\n");
299 }
300
257 count_++; 301 count_++;
258 // Done scavenging. Reset the marker. 302 // Done scavenging. Reset the marker.
259 ASSERT(scavenging_); 303 ASSERT(scavenging_);
260 scavenging_ = false; 304 scavenging_ = false;
261 } 305 }
262 306
263 } // namespace dart 307 } // namespace dart
OLDNEW
« vm/scavenger.h ('K') | « vm/scavenger.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698