OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/scavenger.h" | 5 #include "src/heap/scavenger.h" |
6 | 6 |
7 #include "src/contexts.h" | 7 #include "src/contexts.h" |
8 #include "src/heap/heap.h" | 8 #include "src/heap/heap.h" |
9 #include "src/heap/objects-visiting-inl.h" | 9 #include "src/heap/objects-visiting-inl.h" |
10 #include "src/heap/scavenger-inl.h" | 10 #include "src/heap/scavenger-inl.h" |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 heap->promotion_queue()->insert( | 193 heap->promotion_queue()->insert( |
194 target, object_size, | 194 target, object_size, |
195 Marking::IsBlack(Marking::MarkBitFrom(object))); | 195 Marking::IsBlack(Marking::MarkBitFrom(object))); |
196 } | 196 } |
197 heap->IncrementPromotedObjectsSize(object_size); | 197 heap->IncrementPromotedObjectsSize(object_size); |
198 return true; | 198 return true; |
199 } | 199 } |
200 return false; | 200 return false; |
201 } | 201 } |
202 | 202 |
203 | |
204 template <ObjectContents object_contents, AllocationAlignment alignment> | 203 template <ObjectContents object_contents, AllocationAlignment alignment> |
205 static inline void EvacuateObject(Map* map, HeapObject** slot, | 204 static inline void EvacuateObject(Map* map, HeapObject** slot, |
206 HeapObject* object, int object_size) { | 205 HeapObject* object, int object_size, |
| 206 PromotionMode promotion_mode) { |
207 SLOW_DCHECK(object_size <= Page::kAllocatableMemory); | 207 SLOW_DCHECK(object_size <= Page::kAllocatableMemory); |
208 SLOW_DCHECK(object->Size() == object_size); | 208 SLOW_DCHECK(object->Size() == object_size); |
209 Heap* heap = map->GetHeap(); | 209 Heap* heap = map->GetHeap(); |
210 | 210 |
211 if (!heap->ShouldBePromoted(object->address(), object_size)) { | 211 if (promotion_mode != FORCE_PROMOTION && |
| 212 !heap->ShouldBePromoted(object->address(), object_size)) { |
212 // A semi-space copy may fail due to fragmentation. In that case, we | 213 // A semi-space copy may fail due to fragmentation. In that case, we |
213 // try to promote the object. | 214 // try to promote the object. |
214 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) { | 215 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) { |
215 return; | 216 return; |
216 } | 217 } |
217 } | 218 } |
218 | 219 |
219 if (PromoteObject<object_contents, alignment>(map, slot, object, | 220 if (PromoteObject<object_contents, alignment>(map, slot, object, |
220 object_size)) { | 221 object_size)) { |
221 return; | 222 return; |
222 } | 223 } |
223 | 224 if (promotion_mode == FORCE_PROMOTION) { |
| 225 FatalProcessOutOfMemory("Scavenger: forced promotion\n"); |
| 226 } |
224 // If promotion failed, we try to copy the object to the other semi-space | 227 // If promotion failed, we try to copy the object to the other semi-space |
225 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return; | 228 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return; |
226 | 229 |
227 FatalProcessOutOfMemory("Scavenger: semi-space copy\n"); | 230 FatalProcessOutOfMemory("Scavenger: semi-space copy\n"); |
228 } | 231 } |
229 | 232 |
230 | |
231 static inline void EvacuateJSFunction(Map* map, HeapObject** slot, | 233 static inline void EvacuateJSFunction(Map* map, HeapObject** slot, |
232 HeapObject* object) { | 234 HeapObject* object, |
233 ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object); | 235 PromotionMode promotion_mode) { |
| 236 ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object, |
| 237 promotion_mode); |
234 | 238 |
235 if (marks_handling == IGNORE_MARKS) return; | 239 if (marks_handling == IGNORE_MARKS) return; |
236 | 240 |
237 MapWord map_word = object->map_word(); | 241 MapWord map_word = object->map_word(); |
238 DCHECK(map_word.IsForwardingAddress()); | 242 DCHECK(map_word.IsForwardingAddress()); |
239 HeapObject* target = map_word.ToForwardingAddress(); | 243 HeapObject* target = map_word.ToForwardingAddress(); |
240 | 244 |
241 MarkBit mark_bit = Marking::MarkBitFrom(target); | 245 MarkBit mark_bit = Marking::MarkBitFrom(target); |
242 if (Marking::IsBlack(mark_bit)) { | 246 if (Marking::IsBlack(mark_bit)) { |
243 // This object is black and it might not be rescanned by marker. | 247 // This object is black and it might not be rescanned by marker. |
244 // We should explicitly record code entry slot for compaction because | 248 // We should explicitly record code entry slot for compaction because |
245 // promotion queue processing (IteratePromotedObjectPointers) will | 249 // promotion queue processing (IteratePromotedObjectPointers) will |
246 // miss it as it is not HeapObject-tagged. | 250 // miss it as it is not HeapObject-tagged. |
247 Address code_entry_slot = | 251 Address code_entry_slot = |
248 target->address() + JSFunction::kCodeEntryOffset; | 252 target->address() + JSFunction::kCodeEntryOffset; |
249 Code* code = Code::cast(Code::GetObjectFromEntryAddress(code_entry_slot)); | 253 Code* code = Code::cast(Code::GetObjectFromEntryAddress(code_entry_slot)); |
250 map->GetHeap()->mark_compact_collector()->RecordCodeEntrySlot( | 254 map->GetHeap()->mark_compact_collector()->RecordCodeEntrySlot( |
251 target, code_entry_slot, code); | 255 target, code_entry_slot, code); |
252 } | 256 } |
253 } | 257 } |
254 | 258 |
255 | |
256 static inline void EvacuateFixedArray(Map* map, HeapObject** slot, | 259 static inline void EvacuateFixedArray(Map* map, HeapObject** slot, |
257 HeapObject* object) { | 260 HeapObject* object, |
| 261 PromotionMode promotion_mode) { |
258 int length = reinterpret_cast<FixedArray*>(object)->synchronized_length(); | 262 int length = reinterpret_cast<FixedArray*>(object)->synchronized_length(); |
259 int object_size = FixedArray::SizeFor(length); | 263 int object_size = FixedArray::SizeFor(length); |
260 EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, | 264 EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, object_size, |
261 object_size); | 265 promotion_mode); |
262 } | 266 } |
263 | 267 |
264 | |
265 static inline void EvacuateFixedDoubleArray(Map* map, HeapObject** slot, | 268 static inline void EvacuateFixedDoubleArray(Map* map, HeapObject** slot, |
266 HeapObject* object) { | 269 HeapObject* object, |
| 270 PromotionMode promotion_mode) { |
267 int length = reinterpret_cast<FixedDoubleArray*>(object)->length(); | 271 int length = reinterpret_cast<FixedDoubleArray*>(object)->length(); |
268 int object_size = FixedDoubleArray::SizeFor(length); | 272 int object_size = FixedDoubleArray::SizeFor(length); |
269 EvacuateObject<DATA_OBJECT, kDoubleAligned>(map, slot, object, object_size); | 273 EvacuateObject<DATA_OBJECT, kDoubleAligned>(map, slot, object, object_size, |
| 274 promotion_mode); |
270 } | 275 } |
271 | 276 |
272 | |
273 static inline void EvacuateFixedTypedArray(Map* map, HeapObject** slot, | 277 static inline void EvacuateFixedTypedArray(Map* map, HeapObject** slot, |
274 HeapObject* object) { | 278 HeapObject* object, |
| 279 PromotionMode promotion_mode) { |
275 int object_size = reinterpret_cast<FixedTypedArrayBase*>(object)->size(); | 280 int object_size = reinterpret_cast<FixedTypedArrayBase*>(object)->size(); |
276 EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, | 281 EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, object_size, |
277 object_size); | 282 promotion_mode); |
278 } | 283 } |
279 | 284 |
280 | |
281 static inline void EvacuateFixedFloat64Array(Map* map, HeapObject** slot, | 285 static inline void EvacuateFixedFloat64Array(Map* map, HeapObject** slot, |
282 HeapObject* object) { | 286 HeapObject* object, |
| 287 PromotionMode promotion_mode) { |
283 int object_size = reinterpret_cast<FixedFloat64Array*>(object)->size(); | 288 int object_size = reinterpret_cast<FixedFloat64Array*>(object)->size(); |
284 EvacuateObject<POINTER_OBJECT, kDoubleAligned>(map, slot, object, | 289 EvacuateObject<POINTER_OBJECT, kDoubleAligned>(map, slot, object, |
285 object_size); | 290 object_size, promotion_mode); |
286 } | 291 } |
287 | 292 |
288 | |
289 static inline void EvacuateJSArrayBuffer(Map* map, HeapObject** slot, | 293 static inline void EvacuateJSArrayBuffer(Map* map, HeapObject** slot, |
290 HeapObject* object) { | 294 HeapObject* object, |
291 ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object); | 295 PromotionMode promotion_mode) { |
| 296 ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object, |
| 297 promotion_mode); |
292 | 298 |
293 Heap* heap = map->GetHeap(); | 299 Heap* heap = map->GetHeap(); |
294 MapWord map_word = object->map_word(); | 300 MapWord map_word = object->map_word(); |
295 DCHECK(map_word.IsForwardingAddress()); | 301 DCHECK(map_word.IsForwardingAddress()); |
296 HeapObject* target = map_word.ToForwardingAddress(); | 302 HeapObject* target = map_word.ToForwardingAddress(); |
297 if (!heap->InNewSpace(target)) { | 303 if (!heap->InNewSpace(target)) { |
298 heap->array_buffer_tracker()->Promote(JSArrayBuffer::cast(target)); | 304 heap->array_buffer_tracker()->Promote(JSArrayBuffer::cast(target)); |
299 } | 305 } |
300 } | 306 } |
301 | 307 |
302 | |
303 static inline void EvacuateByteArray(Map* map, HeapObject** slot, | 308 static inline void EvacuateByteArray(Map* map, HeapObject** slot, |
304 HeapObject* object) { | 309 HeapObject* object, |
| 310 PromotionMode promotion_mode) { |
305 int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize(); | 311 int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize(); |
306 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); | 312 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size, |
| 313 promotion_mode); |
307 } | 314 } |
308 | 315 |
309 | |
310 static inline void EvacuateSeqOneByteString(Map* map, HeapObject** slot, | 316 static inline void EvacuateSeqOneByteString(Map* map, HeapObject** slot, |
311 HeapObject* object) { | 317 HeapObject* object, |
| 318 PromotionMode promotion_mode) { |
312 int object_size = SeqOneByteString::cast(object) | 319 int object_size = SeqOneByteString::cast(object) |
313 ->SeqOneByteStringSize(map->instance_type()); | 320 ->SeqOneByteStringSize(map->instance_type()); |
314 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); | 321 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size, |
| 322 promotion_mode); |
315 } | 323 } |
316 | 324 |
317 | |
318 static inline void EvacuateSeqTwoByteString(Map* map, HeapObject** slot, | 325 static inline void EvacuateSeqTwoByteString(Map* map, HeapObject** slot, |
319 HeapObject* object) { | 326 HeapObject* object, |
| 327 PromotionMode promotion_mode) { |
320 int object_size = SeqTwoByteString::cast(object) | 328 int object_size = SeqTwoByteString::cast(object) |
321 ->SeqTwoByteStringSize(map->instance_type()); | 329 ->SeqTwoByteStringSize(map->instance_type()); |
322 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size); | 330 EvacuateObject<DATA_OBJECT, kWordAligned>(map, slot, object, object_size, |
| 331 promotion_mode); |
323 } | 332 } |
324 | 333 |
325 | |
326 static inline void EvacuateShortcutCandidate(Map* map, HeapObject** slot, | 334 static inline void EvacuateShortcutCandidate(Map* map, HeapObject** slot, |
327 HeapObject* object) { | 335 HeapObject* object, |
| 336 PromotionMode promotion_mode) { |
328 DCHECK(IsShortcutCandidate(map->instance_type())); | 337 DCHECK(IsShortcutCandidate(map->instance_type())); |
329 | 338 |
330 Heap* heap = map->GetHeap(); | 339 Heap* heap = map->GetHeap(); |
331 | 340 |
332 if (marks_handling == IGNORE_MARKS && | 341 if (marks_handling == IGNORE_MARKS && |
333 ConsString::cast(object)->unchecked_second() == heap->empty_string()) { | 342 ConsString::cast(object)->unchecked_second() == heap->empty_string()) { |
334 HeapObject* first = | 343 HeapObject* first = |
335 HeapObject::cast(ConsString::cast(object)->unchecked_first()); | 344 HeapObject::cast(ConsString::cast(object)->unchecked_first()); |
336 | 345 |
337 *slot = first; | 346 *slot = first; |
338 | 347 |
339 if (!heap->InNewSpace(first)) { | 348 if (!heap->InNewSpace(first)) { |
340 object->set_map_word(MapWord::FromForwardingAddress(first)); | 349 object->set_map_word(MapWord::FromForwardingAddress(first)); |
341 return; | 350 return; |
342 } | 351 } |
343 | 352 |
344 MapWord first_word = first->map_word(); | 353 MapWord first_word = first->map_word(); |
345 if (first_word.IsForwardingAddress()) { | 354 if (first_word.IsForwardingAddress()) { |
346 HeapObject* target = first_word.ToForwardingAddress(); | 355 HeapObject* target = first_word.ToForwardingAddress(); |
347 | 356 |
348 *slot = target; | 357 *slot = target; |
349 object->set_map_word(MapWord::FromForwardingAddress(target)); | 358 object->set_map_word(MapWord::FromForwardingAddress(target)); |
350 return; | 359 return; |
351 } | 360 } |
352 | 361 |
353 Scavenger::ScavengeObjectSlow(slot, first); | 362 Scavenger::ScavengeObjectSlow(slot, first, promotion_mode); |
354 object->set_map_word(MapWord::FromForwardingAddress(*slot)); | 363 object->set_map_word(MapWord::FromForwardingAddress(*slot)); |
355 return; | 364 return; |
356 } | 365 } |
357 | 366 |
358 int object_size = ConsString::kSize; | 367 int object_size = ConsString::kSize; |
359 EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, | 368 EvacuateObject<POINTER_OBJECT, kWordAligned>(map, slot, object, object_size, |
360 object_size); | 369 promotion_mode); |
361 } | 370 } |
362 | 371 |
363 template <ObjectContents object_contents> | 372 template <ObjectContents object_contents> |
364 class ObjectEvacuationStrategy { | 373 class ObjectEvacuationStrategy { |
365 public: | 374 public: |
366 template <int object_size> | 375 template <int object_size> |
367 static inline void VisitSpecialized(Map* map, HeapObject** slot, | 376 static inline void VisitSpecialized(Map* map, HeapObject** slot, |
368 HeapObject* object) { | 377 HeapObject* object, |
369 EvacuateObject<object_contents, kWordAligned>(map, slot, object, | 378 PromotionMode promotion_mode) { |
370 object_size); | 379 EvacuateObject<object_contents, kWordAligned>( |
| 380 map, slot, object, object_size, promotion_mode); |
371 } | 381 } |
372 | 382 |
373 static inline void Visit(Map* map, HeapObject** slot, HeapObject* object) { | 383 static inline void Visit(Map* map, HeapObject** slot, HeapObject* object, |
| 384 PromotionMode promotion_mode) { |
374 int object_size = map->instance_size(); | 385 int object_size = map->instance_size(); |
375 EvacuateObject<object_contents, kWordAligned>(map, slot, object, | 386 EvacuateObject<object_contents, kWordAligned>( |
376 object_size); | 387 map, slot, object, object_size, promotion_mode); |
377 } | 388 } |
378 }; | 389 }; |
379 | 390 |
380 static VisitorDispatchTable<ScavengingCallback> table_; | 391 static VisitorDispatchTable<ScavengingCallback> table_; |
381 }; | 392 }; |
382 | 393 |
383 | 394 |
384 template <MarksHandling marks_handling, | 395 template <MarksHandling marks_handling, |
385 LoggingAndProfiling logging_and_profiling_mode> | 396 LoggingAndProfiling logging_and_profiling_mode> |
386 VisitorDispatchTable<ScavengingCallback> | 397 VisitorDispatchTable<ScavengingCallback> |
387 ScavengingVisitor<marks_handling, logging_and_profiling_mode>::table_; | 398 ScavengingVisitor<marks_handling, logging_and_profiling_mode>::table_; |
388 | 399 |
389 | 400 |
390 // static | 401 // static |
391 void Scavenger::Initialize() { | 402 void Scavenger::Initialize() { |
392 ScavengingVisitor<TRANSFER_MARKS, | 403 ScavengingVisitor<TRANSFER_MARKS, |
393 LOGGING_AND_PROFILING_DISABLED>::Initialize(); | 404 LOGGING_AND_PROFILING_DISABLED>::Initialize(); |
394 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_DISABLED>::Initialize(); | 405 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_DISABLED>::Initialize(); |
395 ScavengingVisitor<TRANSFER_MARKS, | 406 ScavengingVisitor<TRANSFER_MARKS, |
396 LOGGING_AND_PROFILING_ENABLED>::Initialize(); | 407 LOGGING_AND_PROFILING_ENABLED>::Initialize(); |
397 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::Initialize(); | 408 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::Initialize(); |
398 } | 409 } |
399 | 410 |
400 | 411 |
401 // static | 412 // static |
402 void Scavenger::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { | 413 void Scavenger::ScavengeObjectSlow(HeapObject** p, HeapObject* object, |
| 414 PromotionMode promotion_mode) { |
403 SLOW_DCHECK(object->GetIsolate()->heap()->InFromSpace(object)); | 415 SLOW_DCHECK(object->GetIsolate()->heap()->InFromSpace(object)); |
404 MapWord first_word = object->map_word(); | 416 MapWord first_word = object->map_word(); |
405 SLOW_DCHECK(!first_word.IsForwardingAddress()); | 417 SLOW_DCHECK(!first_word.IsForwardingAddress()); |
406 Map* map = first_word.ToMap(); | 418 Map* map = first_word.ToMap(); |
407 Scavenger* scavenger = map->GetHeap()->scavenge_collector_; | 419 Scavenger* scavenger = map->GetHeap()->scavenge_collector_; |
408 scavenger->scavenging_visitors_table_.GetVisitor(map)(map, p, object); | 420 scavenger->scavenging_visitors_table_.GetVisitor(map)(map, p, object, |
| 421 promotion_mode); |
409 } | 422 } |
410 | 423 |
411 | 424 |
412 void Scavenger::SelectScavengingVisitorsTable() { | 425 void Scavenger::SelectScavengingVisitorsTable() { |
413 bool logging_and_profiling = | 426 bool logging_and_profiling = |
414 FLAG_verify_predictable || isolate()->logger()->is_logging() || | 427 FLAG_verify_predictable || isolate()->logger()->is_logging() || |
415 isolate()->cpu_profiler()->is_profiling() || | 428 isolate()->cpu_profiler()->is_profiling() || |
416 (isolate()->heap_profiler() != NULL && | 429 (isolate()->heap_profiler() != NULL && |
417 isolate()->heap_profiler()->is_tracking_object_moves()); | 430 isolate()->heap_profiler()->is_tracking_object_moves()); |
418 | 431 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 | 478 |
466 void ScavengeVisitor::ScavengePointer(Object** p) { | 479 void ScavengeVisitor::ScavengePointer(Object** p) { |
467 Object* object = *p; | 480 Object* object = *p; |
468 if (!heap_->InNewSpace(object)) return; | 481 if (!heap_->InNewSpace(object)) return; |
469 Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 482 Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
470 reinterpret_cast<HeapObject*>(object)); | 483 reinterpret_cast<HeapObject*>(object)); |
471 } | 484 } |
472 | 485 |
473 } // namespace internal | 486 } // namespace internal |
474 } // namespace v8 | 487 } // namespace v8 |
OLD | NEW |