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