OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
254 void StaticMarkingVisitor<StaticVisitor>::VisitMap( | 254 void StaticMarkingVisitor<StaticVisitor>::VisitMap( |
255 Map* map, HeapObject* object) { | 255 Map* map, HeapObject* object) { |
256 Heap* heap = map->GetHeap(); | 256 Heap* heap = map->GetHeap(); |
257 Map* map_object = Map::cast(object); | 257 Map* map_object = Map::cast(object); |
258 | 258 |
259 // Clears the cache of ICs related to this map. | 259 // Clears the cache of ICs related to this map. |
260 if (FLAG_cleanup_code_caches_at_gc) { | 260 if (FLAG_cleanup_code_caches_at_gc) { |
261 map_object->ClearCodeCache(heap); | 261 map_object->ClearCodeCache(heap); |
262 } | 262 } |
263 | 263 |
264 // When map collection is enabled we have to mark through map's | 264 // When map collection is enabled we have to mark through map's transitions |
265 // transitions and back pointers in a special way to make these links | 265 // and back pointers in a special way to make these links weak. |
266 // weak. Only maps for subclasses of JSReceiver can have transitions. | 266 if (FLAG_collect_maps && map_object->CanTransition()) { |
267 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | |
268 if (FLAG_collect_maps && | |
269 map_object->instance_type() >= FIRST_JS_RECEIVER_TYPE) { | |
270 MarkMapContents(heap, map_object); | 267 MarkMapContents(heap, map_object); |
271 } else { | 268 } else { |
272 StaticVisitor::VisitPointers(heap, | 269 StaticVisitor::VisitPointers(heap, |
273 HeapObject::RawField(object, Map::kPointerFieldsBeginOffset), | 270 HeapObject::RawField(object, Map::kPointerFieldsBeginOffset), |
274 HeapObject::RawField(object, Map::kPointerFieldsEndOffset)); | 271 HeapObject::RawField(object, Map::kPointerFieldsEndOffset)); |
275 } | 272 } |
276 } | 273 } |
277 | 274 |
278 | 275 |
279 template<typename StaticVisitor> | 276 template<typename StaticVisitor> |
280 void StaticMarkingVisitor<StaticVisitor>::VisitCode( | 277 void StaticMarkingVisitor<StaticVisitor>::VisitCode( |
281 Map* map, HeapObject* object) { | 278 Map* map, HeapObject* object) { |
282 Heap* heap = map->GetHeap(); | 279 Heap* heap = map->GetHeap(); |
283 Code* code = Code::cast(object); | 280 Code* code = Code::cast(object); |
284 if (FLAG_cleanup_code_caches_at_gc) { | 281 if (FLAG_cleanup_code_caches_at_gc) { |
285 code->ClearTypeFeedbackCells(heap); | 282 code->ClearTypeFeedbackCells(heap); |
286 } | 283 } |
287 if (FLAG_age_code && !Serializer::enabled()) { | 284 if (FLAG_age_code && !Serializer::enabled()) { |
288 code->MakeOlder(heap->mark_compact_collector()->marking_parity()); | 285 code->MakeOlder(heap->mark_compact_collector()->marking_parity()); |
289 } | 286 } |
290 code->CodeIterateBody<StaticVisitor>(heap); | 287 code->CodeIterateBody<StaticVisitor, Code::SKIP_EMBEDDED_MAPS>(heap); |
291 } | 288 } |
292 | 289 |
293 | 290 |
294 template<typename StaticVisitor> | 291 template<typename StaticVisitor> |
295 void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo( | 292 void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo( |
296 Map* map, HeapObject* object) { | 293 Map* map, HeapObject* object) { |
297 Heap* heap = map->GetHeap(); | 294 Heap* heap = map->GetHeap(); |
298 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); | 295 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); |
299 if (shared->ic_age() != heap->global_ic_age()) { | 296 if (shared->ic_age() != heap->global_ic_age()) { |
300 shared->ResetForNewContext(heap->global_ic_age()); | 297 shared->ResetForNewContext(heap->global_ic_age()); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 // array slot, since it will be implicitly recorded when the pointer | 384 // array slot, since it will be implicitly recorded when the pointer |
388 // fields of this map are visited. | 385 // fields of this map are visited. |
389 TransitionArray* transitions = map->unchecked_transition_array(); | 386 TransitionArray* transitions = map->unchecked_transition_array(); |
390 if (transitions->IsTransitionArray()) { | 387 if (transitions->IsTransitionArray()) { |
391 MarkTransitionArray(heap, transitions); | 388 MarkTransitionArray(heap, transitions); |
392 } else { | 389 } else { |
393 // Already marked by marking map->GetBackPointer() above. | 390 // Already marked by marking map->GetBackPointer() above. |
394 ASSERT(transitions->IsMap() || transitions->IsUndefined()); | 391 ASSERT(transitions->IsMap() || transitions->IsUndefined()); |
395 } | 392 } |
396 | 393 |
394 // Mark prototype dependent codes array but do not push it onto marking | |
395 // stack, this will make references from it weak. We will clean dead | |
Michael Starzinger
2013/01/21 10:31:48
One "dead" oughta be enough. :)
ulan
2013/01/21 13:11:57
Done.
| |
396 // dead codes when we iterate over maps in ClearNonLiveTransitions. | |
397 Object** slot = HeapObject::RawField(reinterpret_cast<HeapObject*>(map), | |
Michael Starzinger
2013/01/21 10:31:48
The reinterpret_cast shouldn't be necessary, a Map
ulan
2013/01/21 13:11:57
Done.
| |
398 Map::kDependentCodesOffset); | |
399 HeapObject* obj = HeapObject::cast(*slot); | |
400 heap->mark_compact_collector()->RecordSlot(slot, slot, obj); | |
401 StaticVisitor::MarkObjectWithoutPush(heap, obj); | |
402 | |
397 // Mark the pointer fields of the Map. Since the transitions array has | 403 // Mark the pointer fields of the Map. Since the transitions array has |
398 // been marked already, it is fine that one of these fields contains a | 404 // been marked already, it is fine that one of these fields contains a |
399 // pointer to it. | 405 // pointer to it. |
400 StaticVisitor::VisitPointers(heap, | 406 StaticVisitor::VisitPointers(heap, |
401 HeapObject::RawField(map, Map::kPointerFieldsBeginOffset), | 407 HeapObject::RawField(map, Map::kPointerFieldsBeginOffset), |
402 HeapObject::RawField(map, Map::kPointerFieldsEndOffset)); | 408 HeapObject::RawField(map, Map::kPointerFieldsEndOffset)); |
403 } | 409 } |
404 | 410 |
405 | 411 |
406 template<typename StaticVisitor> | 412 template<typename StaticVisitor> |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 | 636 |
631 void Code::CodeIterateBody(ObjectVisitor* v) { | 637 void Code::CodeIterateBody(ObjectVisitor* v) { |
632 int mode_mask = RelocInfo::kCodeTargetMask | | 638 int mode_mask = RelocInfo::kCodeTargetMask | |
633 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 639 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
634 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | | 640 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | |
635 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 641 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
636 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | | 642 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | |
637 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | | 643 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | |
638 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | 644 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
639 | 645 |
640 // There are two places where we iterate code bodies: here and the | 646 // There are two places where we iterate code bodies: here and the non- |
641 // templated CodeIterateBody (below). They should be kept in sync. | 647 // templated CodeIterateBody (above). They should be kept in sync. The only |
648 // difference between the two versions is in handling of embedded maps. | |
649 // Static marking visitors do not visit embedded maps, but most of the non- | |
650 // static visitors need to visit embedded maps. Non-static visitor can skip | |
651 // embedded maps by overriding VisitEmbeddedPointer, like | |
652 // VerifyMarkingVisitor does. | |
642 IteratePointer(v, kRelocationInfoOffset); | 653 IteratePointer(v, kRelocationInfoOffset); |
643 IteratePointer(v, kHandlerTableOffset); | 654 IteratePointer(v, kHandlerTableOffset); |
644 IteratePointer(v, kDeoptimizationDataOffset); | 655 IteratePointer(v, kDeoptimizationDataOffset); |
645 IteratePointer(v, kTypeFeedbackInfoOffset); | 656 IteratePointer(v, kTypeFeedbackInfoOffset); |
646 | 657 |
647 RelocIterator it(this, mode_mask); | 658 RelocIterator it(this, mode_mask); |
648 for (; !it.done(); it.next()) { | 659 for (; !it.done(); it.next()) { |
649 it.rinfo()->Visit(v); | 660 it.rinfo()->Visit(v); |
650 } | 661 } |
651 } | 662 } |
652 | 663 |
653 | 664 |
654 template<typename StaticVisitor> | 665 template<typename StaticVisitor, Code::EmbeddedMapVisitMode map_visit_mode> |
655 void Code::CodeIterateBody(Heap* heap) { | 666 void Code::CodeIterateBody(Heap* heap) { |
656 int mode_mask = RelocInfo::kCodeTargetMask | | 667 int mode_mask = RelocInfo::kCodeTargetMask | |
657 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 668 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
658 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | | 669 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | |
659 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 670 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
660 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | | 671 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | |
661 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | | 672 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | |
662 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); | 673 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
663 | 674 |
664 // There are two places where we iterate code bodies: here and the | 675 // There are two places where we iterate code bodies: here and the non- |
665 // non-templated CodeIterateBody (above). They should be kept in sync. | 676 // templated CodeIterateBody (above). They should be kept in sync. The only |
677 // difference between the two versions is in handling of embedded maps. | |
678 // Static marking visitors do not visit embedded maps, but most of the non- | |
679 // static visitors need to visit embedded maps. Non-static visitor can skip | |
680 // embedded maps by overriding VisitEmbeddedPointer, like | |
681 // VerifyMarkingVisitor does. | |
666 StaticVisitor::VisitPointer( | 682 StaticVisitor::VisitPointer( |
667 heap, | 683 heap, |
668 reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset)); | 684 reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset)); |
669 StaticVisitor::VisitPointer( | 685 StaticVisitor::VisitPointer( |
670 heap, | 686 heap, |
671 reinterpret_cast<Object**>(this->address() + kHandlerTableOffset)); | 687 reinterpret_cast<Object**>(this->address() + kHandlerTableOffset)); |
672 StaticVisitor::VisitPointer( | 688 StaticVisitor::VisitPointer( |
673 heap, | 689 heap, |
674 reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset)); | 690 reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset)); |
675 StaticVisitor::VisitPointer( | 691 StaticVisitor::VisitPointer( |
676 heap, | 692 heap, |
677 reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset)); | 693 reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset)); |
678 | 694 |
679 RelocIterator it(this, mode_mask); | 695 RelocIterator it(this, mode_mask); |
680 for (; !it.done(); it.next()) { | 696 if (map_visit_mode == SKIP_EMBEDDED_MAPS && kind() == OPTIMIZED_FUNCTION) { |
ulan
2013/01/17 09:35:10
Maybe I should just move this to VisitEmbeddedPoin
Michael Starzinger
2013/01/21 10:31:48
Yes, good idea, I am very much in favor of this su
ulan
2013/01/21 13:11:57
Done.
| |
681 it.rinfo()->template Visit<StaticVisitor>(heap); | 697 // Treat embedded maps in optimized code as weak. |
698 for (; !it.done(); it.next()) { | |
699 RelocInfo* info = it.rinfo(); | |
700 if (!RelocInfo::IsEmbeddedObject(info->rmode()) || | |
701 !info->target_object()->IsMap() || | |
702 !Map::cast(info->target_object())->CanTransition()) { | |
703 it.rinfo()->template Visit<StaticVisitor>(heap); | |
704 } | |
705 } | |
706 } else { | |
707 for (; !it.done(); it.next()) { | |
708 it.rinfo()->template Visit<StaticVisitor>(heap); | |
709 } | |
682 } | 710 } |
683 } | 711 } |
684 | 712 |
685 | 713 |
686 } } // namespace v8::internal | 714 } } // namespace v8::internal |
687 | 715 |
688 #endif // V8_OBJECTS_VISITING_INL_H_ | 716 #endif // V8_OBJECTS_VISITING_INL_H_ |
OLD | NEW |