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

Side by Side Diff: src/objects-visiting-inl.h

Issue 11575007: Make embedded maps in optimized code weak. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add test that reproduces memleak and rebase. Created 7 years, 11 months 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
OLDNEW
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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 void StaticMarkingVisitor<StaticVisitor>::VisitMap( 255 void StaticMarkingVisitor<StaticVisitor>::VisitMap(
256 Map* map, HeapObject* object) { 256 Map* map, HeapObject* object) {
257 Heap* heap = map->GetHeap(); 257 Heap* heap = map->GetHeap();
258 Map* map_object = Map::cast(object); 258 Map* map_object = Map::cast(object);
259 259
260 // Clears the cache of ICs related to this map. 260 // Clears the cache of ICs related to this map.
261 if (FLAG_cleanup_code_caches_at_gc) { 261 if (FLAG_cleanup_code_caches_at_gc) {
262 map_object->ClearCodeCache(heap); 262 map_object->ClearCodeCache(heap);
263 } 263 }
264 264
265 // When map collection is enabled we have to mark through map's 265 // When map collection is enabled we have to mark through map's transitions
266 // transitions and back pointers in a special way to make these links 266 // and back pointers in a special way to make these links weak.
267 // weak. Only maps for subclasses of JSReceiver can have transitions. 267 if (FLAG_collect_maps && map_object->CanTransition()) {
268 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
269 if (FLAG_collect_maps &&
270 map_object->instance_type() >= FIRST_JS_RECEIVER_TYPE) {
271 MarkMapContents(heap, map_object); 268 MarkMapContents(heap, map_object);
272 } else { 269 } else {
273 StaticVisitor::VisitPointers(heap, 270 StaticVisitor::VisitPointers(heap,
274 HeapObject::RawField(object, Map::kPointerFieldsBeginOffset), 271 HeapObject::RawField(object, Map::kPointerFieldsBeginOffset),
275 HeapObject::RawField(object, Map::kPointerFieldsEndOffset)); 272 HeapObject::RawField(object, Map::kPointerFieldsEndOffset));
276 } 273 }
277 } 274 }
278 275
279 276
280 template<typename StaticVisitor> 277 template<typename StaticVisitor>
281 void StaticMarkingVisitor<StaticVisitor>::VisitCode( 278 void StaticMarkingVisitor<StaticVisitor>::VisitCode(
282 Map* map, HeapObject* object) { 279 Map* map, HeapObject* object) {
283 Heap* heap = map->GetHeap(); 280 Heap* heap = map->GetHeap();
284 Code* code = Code::cast(object); 281 Code* code = Code::cast(object);
285 if (FLAG_cleanup_code_caches_at_gc) { 282 if (FLAG_cleanup_code_caches_at_gc) {
286 code->ClearTypeFeedbackCells(heap); 283 code->ClearTypeFeedbackCells(heap);
287 } 284 }
288 if (FLAG_age_code && !Serializer::enabled()) { 285 if (FLAG_age_code && !Serializer::enabled()) {
289 code->MakeOlder(heap->mark_compact_collector()->marking_parity()); 286 code->MakeOlder(heap->mark_compact_collector()->marking_parity());
290 } 287 }
291 code->CodeIterateBody<StaticVisitor>(heap); 288 code->CodeIterateBody<StaticVisitor, Code::SKIP_EMBEDDED_MAPS>(heap);
292 } 289 }
293 290
294 291
295 template<typename StaticVisitor> 292 template<typename StaticVisitor>
296 void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo( 293 void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo(
297 Map* map, HeapObject* object) { 294 Map* map, HeapObject* object) {
298 Heap* heap = map->GetHeap(); 295 Heap* heap = map->GetHeap();
299 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); 296 SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
300 if (shared->ic_age() != heap->global_ic_age()) { 297 if (shared->ic_age() != heap->global_ic_age()) {
301 shared->ResetForNewContext(heap->global_ic_age()); 298 shared->ResetForNewContext(heap->global_ic_age());
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 // array slot, since it will be implicitly recorded when the pointer 385 // array slot, since it will be implicitly recorded when the pointer
389 // fields of this map are visited. 386 // fields of this map are visited.
390 TransitionArray* transitions = map->unchecked_transition_array(); 387 TransitionArray* transitions = map->unchecked_transition_array();
391 if (transitions->IsTransitionArray()) { 388 if (transitions->IsTransitionArray()) {
392 MarkTransitionArray(heap, transitions); 389 MarkTransitionArray(heap, transitions);
393 } else { 390 } else {
394 // Already marked by marking map->GetBackPointer() above. 391 // Already marked by marking map->GetBackPointer() above.
395 ASSERT(transitions->IsMap() || transitions->IsUndefined()); 392 ASSERT(transitions->IsMap() || transitions->IsUndefined());
396 } 393 }
397 394
395 // Mark prototype dependent codes array but do not push it onto marking
396 // stack, this will make references from it weak. We will clean dead
397 // dead codes when we iterate over maps in ClearNonLiveTransitions.
398 Object** slot = HeapObject::RawField(reinterpret_cast<HeapObject*>(map),
399 Map::kDependentCodesOffset);
400 HeapObject* obj = HeapObject::cast(*slot);
401 heap->mark_compact_collector()->RecordSlot(slot, slot, obj);
402 StaticVisitor::MarkObjectWithoutPush(heap, obj);
403
398 // Mark the pointer fields of the Map. Since the transitions array has 404 // Mark the pointer fields of the Map. Since the transitions array has
399 // been marked already, it is fine that one of these fields contains a 405 // been marked already, it is fine that one of these fields contains a
400 // pointer to it. 406 // pointer to it.
401 StaticVisitor::VisitPointers(heap, 407 StaticVisitor::VisitPointers(heap,
402 HeapObject::RawField(map, Map::kPointerFieldsBeginOffset), 408 HeapObject::RawField(map, Map::kPointerFieldsBeginOffset),
403 HeapObject::RawField(map, Map::kPointerFieldsEndOffset)); 409 HeapObject::RawField(map, Map::kPointerFieldsEndOffset));
404 } 410 }
405 411
406 412
407 template<typename StaticVisitor> 413 template<typename StaticVisitor>
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 637
632 void Code::CodeIterateBody(ObjectVisitor* v) { 638 void Code::CodeIterateBody(ObjectVisitor* v) {
633 int mode_mask = RelocInfo::kCodeTargetMask | 639 int mode_mask = RelocInfo::kCodeTargetMask |
634 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | 640 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
635 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | 641 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
636 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | 642 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
637 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | 643 RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
638 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | 644 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
639 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); 645 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
640 646
641 // There are two places where we iterate code bodies: here and the 647 // There are two places where we iterate code bodies: here and the non-
642 // templated CodeIterateBody (below). They should be kept in sync. 648 // templated CodeIterateBody (above). They should be kept in sync. The only
649 // difference between the two versions is in handling of embedded maps.
650 // Static marking visitors do not visit embedded maps, but most of the non-
651 // static visitors need to visit embedded maps. Non-static visitor can skip
652 // embedded maps by overriding VisitEmbeddedPointer, like
653 // VerifyMarkingVisitor does.
643 IteratePointer(v, kRelocationInfoOffset); 654 IteratePointer(v, kRelocationInfoOffset);
644 IteratePointer(v, kHandlerTableOffset); 655 IteratePointer(v, kHandlerTableOffset);
645 IteratePointer(v, kDeoptimizationDataOffset); 656 IteratePointer(v, kDeoptimizationDataOffset);
646 IteratePointer(v, kTypeFeedbackInfoOffset); 657 IteratePointer(v, kTypeFeedbackInfoOffset);
647 658
648 RelocIterator it(this, mode_mask); 659 RelocIterator it(this, mode_mask);
649 for (; !it.done(); it.next()) { 660 for (; !it.done(); it.next()) {
650 it.rinfo()->Visit(v); 661 it.rinfo()->Visit(v);
651 } 662 }
652 } 663 }
653 664
654 665
655 template<typename StaticVisitor> 666 template<typename StaticVisitor, Code::EmbeddedMapVisitMode map_visit_mode>
656 void Code::CodeIterateBody(Heap* heap) { 667 void Code::CodeIterateBody(Heap* heap) {
657 int mode_mask = RelocInfo::kCodeTargetMask | 668 int mode_mask = RelocInfo::kCodeTargetMask |
658 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | 669 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
659 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | 670 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
660 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | 671 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
661 RelocInfo::ModeMask(RelocInfo::JS_RETURN) | 672 RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
662 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | 673 RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
663 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); 674 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
664 675
665 // There are two places where we iterate code bodies: here and the 676 // There are two places where we iterate code bodies: here and the non-
666 // non-templated CodeIterateBody (above). They should be kept in sync. 677 // templated CodeIterateBody (above). They should be kept in sync. The only
678 // difference between the two versions is in handling of embedded maps.
679 // Static marking visitors do not visit embedded maps, but most of the non-
680 // static visitors need to visit embedded maps. Non-static visitor can skip
681 // embedded maps by overriding VisitEmbeddedPointer, like
682 // VerifyMarkingVisitor does.
667 StaticVisitor::VisitPointer( 683 StaticVisitor::VisitPointer(
668 heap, 684 heap,
669 reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset)); 685 reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset));
670 StaticVisitor::VisitPointer( 686 StaticVisitor::VisitPointer(
671 heap, 687 heap,
672 reinterpret_cast<Object**>(this->address() + kHandlerTableOffset)); 688 reinterpret_cast<Object**>(this->address() + kHandlerTableOffset));
673 StaticVisitor::VisitPointer( 689 StaticVisitor::VisitPointer(
674 heap, 690 heap,
675 reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset)); 691 reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset));
676 StaticVisitor::VisitPointer( 692 StaticVisitor::VisitPointer(
677 heap, 693 heap,
678 reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset)); 694 reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset));
679 695
680 RelocIterator it(this, mode_mask); 696 RelocIterator it(this, mode_mask);
681 for (; !it.done(); it.next()) { 697 if (map_visit_mode == SKIP_EMBEDDED_MAPS && kind() == OPTIMIZED_FUNCTION) {
682 it.rinfo()->template Visit<StaticVisitor>(heap); 698 // Treat embedded maps in optimized code as weak.
699 for (; !it.done(); it.next()) {
700 RelocInfo* info = it.rinfo();
701 if (!RelocInfo::IsEmbeddedObject(info->rmode()) ||
702 !info->target_object()->IsMap() ||
703 !Map::cast(info->target_object())->CanTransition()) {
704 it.rinfo()->template Visit<StaticVisitor>(heap);
705 }
706 }
707 } else {
708 for (; !it.done(); it.next()) {
709 it.rinfo()->template Visit<StaticVisitor>(heap);
710 }
683 } 711 }
684 } 712 }
685 713
686 714
687 } } // namespace v8::internal 715 } } // namespace v8::internal
688 716
689 #endif // V8_OBJECTS_VISITING_INL_H_ 717 #endif // V8_OBJECTS_VISITING_INL_H_
OLDNEW
« src/mark-compact.cc ('K') | « src/objects-inl.h ('k') | test/mjsunit/mjsunit.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698