| Index: src/mark-compact.cc
 | 
| diff --git a/src/mark-compact.cc b/src/mark-compact.cc
 | 
| index 554b5795de92e49ed29734e949768c12ff4cf625..0dc3e0f0196abf4e32fe405ac68e68958cf97572 100644
 | 
| --- a/src/mark-compact.cc
 | 
| +++ b/src/mark-compact.cc
 | 
| @@ -84,9 +84,6 @@ void MarkCompactCollector::CollectGarbage() {
 | 
|      UpdatePointers();
 | 
|  
 | 
|      RelocateObjects();
 | 
| -
 | 
| -    RebuildRSets();
 | 
| -
 | 
|    } else {
 | 
|      SweepSpaces();
 | 
|    }
 | 
| @@ -121,14 +118,6 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
 | 
|        compacting_collection_ = false;
 | 
|    if (FLAG_collect_maps) CreateBackPointers();
 | 
|  
 | 
| -#ifdef DEBUG
 | 
| -  if (compacting_collection_) {
 | 
| -    // We will write bookkeeping information to the remembered set area
 | 
| -    // starting now.
 | 
| -    Page::set_rset_state(Page::NOT_IN_USE);
 | 
| -  }
 | 
| -#endif
 | 
| -
 | 
|    PagedSpaces spaces;
 | 
|    for (PagedSpace* space = spaces.next();
 | 
|         space != NULL; space = spaces.next()) {
 | 
| @@ -150,7 +139,7 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
 | 
|  
 | 
|  void MarkCompactCollector::Finish() {
 | 
|  #ifdef DEBUG
 | 
| -  ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS);
 | 
| +  ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS);
 | 
|    state_ = IDLE;
 | 
|  #endif
 | 
|    // The stub cache is not traversed during GC; clear the cache to
 | 
| @@ -244,8 +233,8 @@ static inline HeapObject* ShortCircuitConsString(Object** p) {
 | 
|    }
 | 
|  
 | 
|    // Since we don't have the object's start, it is impossible to update the
 | 
| -  // remembered set.  Therefore, we only replace the string with its left
 | 
| -  // substring when the remembered set does not change.
 | 
| +  // page dirty marks. Therefore, we only replace the string with its left
 | 
| +  // substring when page dirty marks do not change.
 | 
|    Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first();
 | 
|    if (!Heap::InNewSpace(object) && Heap::InNewSpace(first)) return object;
 | 
|  
 | 
| @@ -776,6 +765,7 @@ void MarkCompactCollector::SweepLargeObjectSpace() {
 | 
|    Heap::lo_space()->FreeUnmarkedObjects();
 | 
|  }
 | 
|  
 | 
| +
 | 
|  // Safe to use during marking phase only.
 | 
|  bool MarkCompactCollector::SafeIsMap(HeapObject* object) {
 | 
|    MapWord metamap = object->map_word();
 | 
| @@ -783,6 +773,7 @@ bool MarkCompactCollector::SafeIsMap(HeapObject* object) {
 | 
|    return metamap.ToMap()->instance_type() == MAP_TYPE;
 | 
|  }
 | 
|  
 | 
| +
 | 
|  void MarkCompactCollector::ClearNonLiveTransitions() {
 | 
|    HeapObjectIterator map_iterator(Heap::map_space(), &CountMarkedCallback);
 | 
|    // Iterate over the map space, setting map transitions that go from
 | 
| @@ -1078,13 +1069,18 @@ void MarkCompactCollector::EncodeForwardingAddressesInPagedSpace(
 | 
|  // first word of object without any encoding. If object is dead we are writing
 | 
|  // NULL as a forwarding address.
 | 
|  // The second pass updates pointers to new space in all spaces. It is possible
 | 
| -// to encounter pointers to dead objects during traversal of remembered set for
 | 
| -// map space because remembered set bits corresponding to dead maps are cleared
 | 
| -// later during map space sweeping.
 | 
| -static void MigrateObject(Address dst, Address src, int size) {
 | 
| -  Heap::CopyBlock(reinterpret_cast<Object**>(dst),
 | 
| -                  reinterpret_cast<Object**>(src),
 | 
| -                  size);
 | 
| +// to encounter pointers to dead objects during traversal of dirty regions we
 | 
| +// should clear them to avoid encountering them during next dirty regions
 | 
| +// iteration.
 | 
| +static void MigrateObject(Address dst,
 | 
| +                          Address src,
 | 
| +                          int size,
 | 
| +                          bool to_old_space) {
 | 
| +  if (to_old_space) {
 | 
| +    Heap::CopyBlockToOldSpaceAndUpdateRegionMarks(dst, src, size);
 | 
| +  } else {
 | 
| +    Heap::CopyBlock(dst, src, size);
 | 
| +  }
 | 
|  
 | 
|    Memory::Address_at(src) = dst;
 | 
|  }
 | 
| @@ -1131,6 +1127,7 @@ class PointersToNewGenUpdatingVisitor: public ObjectVisitor {
 | 
|    }
 | 
|  };
 | 
|  
 | 
| +
 | 
|  // Visitor for updating pointers from live objects in old spaces to new space.
 | 
|  // It can encounter pointers to dead objects in new space when traversing map
 | 
|  // space (see comment for MigrateObject).
 | 
| @@ -1142,10 +1139,13 @@ static void UpdatePointerToNewGen(HeapObject** p) {
 | 
|  
 | 
|    Address new_addr = Memory::Address_at(old_addr);
 | 
|  
 | 
| -  // Object pointed by *p is dead. Update is not required.
 | 
| -  if (new_addr == NULL) return;
 | 
| -
 | 
| -  *p = HeapObject::FromAddress(new_addr);
 | 
| +  if (new_addr == NULL) {
 | 
| +    // We encountered pointer to a dead object. Clear it so we will
 | 
| +    // not visit it again during next iteration of dirty regions.
 | 
| +    *p = NULL;
 | 
| +  } else {
 | 
| +    *p = HeapObject::FromAddress(new_addr);
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1163,8 +1163,7 @@ static bool TryPromoteObject(HeapObject* object, int object_size) {
 | 
|      result = Heap::lo_space()->AllocateRawFixedArray(object_size);
 | 
|      if (!result->IsFailure()) {
 | 
|        HeapObject* target = HeapObject::cast(result);
 | 
| -      MigrateObject(target->address(), object->address(), object_size);
 | 
| -      Heap::UpdateRSet(target);
 | 
| +      MigrateObject(target->address(), object->address(), object_size, true);
 | 
|        MarkCompactCollector::tracer()->
 | 
|            increment_promoted_objects_size(object_size);
 | 
|        return true;
 | 
| @@ -1177,10 +1176,10 @@ static bool TryPromoteObject(HeapObject* object, int object_size) {
 | 
|      result = target_space->AllocateRaw(object_size);
 | 
|      if (!result->IsFailure()) {
 | 
|        HeapObject* target = HeapObject::cast(result);
 | 
| -      MigrateObject(target->address(), object->address(), object_size);
 | 
| -      if (target_space == Heap::old_pointer_space()) {
 | 
| -        Heap::UpdateRSet(target);
 | 
| -      }
 | 
| +      MigrateObject(target->address(),
 | 
| +                    object->address(),
 | 
| +                    object_size,
 | 
| +                    target_space == Heap::old_pointer_space());
 | 
|        MarkCompactCollector::tracer()->
 | 
|            increment_promoted_objects_size(object_size);
 | 
|        return true;
 | 
| @@ -1222,14 +1221,16 @@ static void SweepNewSpace(NewSpace* space) {
 | 
|          continue;
 | 
|        }
 | 
|  
 | 
| -      // Promotion either failed or not required.
 | 
| -      // Copy the content of the object.
 | 
| +      // Promotion failed. Just migrate object to another semispace.
 | 
|        Object* target = space->AllocateRaw(size);
 | 
|  
 | 
|        // Allocation cannot fail at this point: semispaces are of equal size.
 | 
|        ASSERT(!target->IsFailure());
 | 
|  
 | 
| -      MigrateObject(HeapObject::cast(target)->address(), current, size);
 | 
| +      MigrateObject(HeapObject::cast(target)->address(),
 | 
| +                    current,
 | 
| +                    size,
 | 
| +                    false);
 | 
|      } else {
 | 
|        size = object->Size();
 | 
|        Memory::Address_at(current) = NULL;
 | 
| @@ -1255,9 +1256,12 @@ static void SweepNewSpace(NewSpace* space) {
 | 
|    Heap::IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE);
 | 
|  
 | 
|    // Update pointers in old spaces.
 | 
| -  Heap::IterateRSet(Heap::old_pointer_space(), &UpdatePointerToNewGen);
 | 
| -  Heap::IterateRSet(Heap::map_space(), &UpdatePointerToNewGen);
 | 
| -  Heap::lo_space()->IterateRSet(&UpdatePointerToNewGen);
 | 
| +  Heap::IterateDirtyRegions(Heap::old_pointer_space(),
 | 
| +                            &Heap::IteratePointersInDirtyRegion,
 | 
| +                            &UpdatePointerToNewGen,
 | 
| +                            Heap::WATERMARK_SHOULD_BE_VALID);
 | 
| +
 | 
| +  Heap::lo_space()->IterateDirtyRegions(&UpdatePointerToNewGen);
 | 
|  
 | 
|    // Update pointers from cells.
 | 
|    HeapObjectIterator cell_iterator(Heap::cell_space());
 | 
| @@ -1323,7 +1327,10 @@ static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) {
 | 
|          MarkCompactCollector::tracer()->decrement_marked_count();
 | 
|  
 | 
|          if (!is_previous_alive) {  // Transition from free to live.
 | 
| -          dealloc(free_start, static_cast<int>(current - free_start), true);
 | 
| +          dealloc(free_start,
 | 
| +                  static_cast<int>(current - free_start),
 | 
| +                  true,
 | 
| +                  false);
 | 
|            is_previous_alive = true;
 | 
|          }
 | 
|        } else {
 | 
| @@ -1353,7 +1360,7 @@ static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) {
 | 
|          // without putting anything into free list.
 | 
|          int size_in_bytes = static_cast<int>(p->AllocationTop() - free_start);
 | 
|          if (size_in_bytes > 0) {
 | 
| -          dealloc(free_start, size_in_bytes, false);
 | 
| +          dealloc(free_start, size_in_bytes, false, true);
 | 
|          }
 | 
|        }
 | 
|      } else {
 | 
| @@ -1367,7 +1374,9 @@ static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) {
 | 
|        // If there is a free ending area on one of the previous pages we have
 | 
|        // deallocate that area and put it on the free list.
 | 
|        if (last_free_size > 0) {
 | 
| -        dealloc(last_free_start, last_free_size, true);
 | 
| +        Page::FromAddress(last_free_start)->
 | 
| +            SetAllocationWatermark(last_free_start);
 | 
| +        dealloc(last_free_start, last_free_size, true, true);
 | 
|          last_free_start = NULL;
 | 
|          last_free_size  = 0;
 | 
|        }
 | 
| @@ -1398,7 +1407,7 @@ static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) {
 | 
|      // There was a free ending area on the previous page.
 | 
|      // Deallocate it without putting it into freelist and move allocation
 | 
|      // top to the beginning of this free area.
 | 
| -    dealloc(last_free_start, last_free_size, false);
 | 
| +    dealloc(last_free_start, last_free_size, false, true);
 | 
|      new_allocation_top = last_free_start;
 | 
|    }
 | 
|  
 | 
| @@ -1421,34 +1430,36 @@ static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) {
 | 
|  
 | 
|  void MarkCompactCollector::DeallocateOldPointerBlock(Address start,
 | 
|                                                       int size_in_bytes,
 | 
| -                                                     bool add_to_freelist) {
 | 
| -  Heap::ClearRSetRange(start, size_in_bytes);
 | 
| +                                                     bool add_to_freelist,
 | 
| +                                                     bool last_on_page) {
 | 
|    Heap::old_pointer_space()->Free(start, size_in_bytes, add_to_freelist);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void MarkCompactCollector::DeallocateOldDataBlock(Address start,
 | 
|                                                    int size_in_bytes,
 | 
| -                                                  bool add_to_freelist) {
 | 
| +                                                  bool add_to_freelist,
 | 
| +                                                  bool last_on_page) {
 | 
|    Heap::old_data_space()->Free(start, size_in_bytes, add_to_freelist);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void MarkCompactCollector::DeallocateCodeBlock(Address start,
 | 
|                                                 int size_in_bytes,
 | 
| -                                               bool add_to_freelist) {
 | 
| +                                               bool add_to_freelist,
 | 
| +                                               bool last_on_page) {
 | 
|    Heap::code_space()->Free(start, size_in_bytes, add_to_freelist);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  void MarkCompactCollector::DeallocateMapBlock(Address start,
 | 
|                                                int size_in_bytes,
 | 
| -                                              bool add_to_freelist) {
 | 
| +                                              bool add_to_freelist,
 | 
| +                                              bool last_on_page) {
 | 
|    // Objects in map space are assumed to have size Map::kSize and a
 | 
|    // valid map in their first word.  Thus, we break the free block up into
 | 
|    // chunks and free them separately.
 | 
|    ASSERT(size_in_bytes % Map::kSize == 0);
 | 
| -  Heap::ClearRSetRange(start, size_in_bytes);
 | 
|    Address end = start + size_in_bytes;
 | 
|    for (Address a = start; a < end; a += Map::kSize) {
 | 
|      Heap::map_space()->Free(a, add_to_freelist);
 | 
| @@ -1458,13 +1469,13 @@ void MarkCompactCollector::DeallocateMapBlock(Address start,
 | 
|  
 | 
|  void MarkCompactCollector::DeallocateCellBlock(Address start,
 | 
|                                                 int size_in_bytes,
 | 
| -                                               bool add_to_freelist) {
 | 
| +                                               bool add_to_freelist,
 | 
| +                                               bool last_on_page) {
 | 
|    // Free-list elements in cell space are assumed to have a fixed size.
 | 
|    // We break the free block into chunks and add them to the free list
 | 
|    // individually.
 | 
|    int size = Heap::cell_space()->object_size_in_bytes();
 | 
|    ASSERT(size_in_bytes % size == 0);
 | 
| -  Heap::ClearRSetRange(start, size_in_bytes);
 | 
|    Address end = start + size_in_bytes;
 | 
|    for (Address a = start; a < end; a += size) {
 | 
|      Heap::cell_space()->Free(a, add_to_freelist);
 | 
| @@ -1563,20 +1574,6 @@ class MapCompact {
 | 
|      GlobalHandles::IterateWeakRoots(&map_updating_visitor_);
 | 
|    }
 | 
|  
 | 
| -  void FinishMapSpace() {
 | 
| -    // Iterate through to space and finish move.
 | 
| -    MapIterator it;
 | 
| -    HeapObject* o = it.next();
 | 
| -    for (; o != first_map_to_evacuate_; o = it.next()) {
 | 
| -      ASSERT(o != NULL);
 | 
| -      Map* map = reinterpret_cast<Map*>(o);
 | 
| -      ASSERT(!map->IsMarked());
 | 
| -      ASSERT(!map->IsOverflowed());
 | 
| -      ASSERT(map->IsMap());
 | 
| -      Heap::UpdateRSet(map);
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
|    void UpdateMapPointersInPagedSpace(PagedSpace* space) {
 | 
|      ASSERT(space != Heap::map_space());
 | 
|  
 | 
| @@ -1669,9 +1666,9 @@ class MapCompact {
 | 
|  
 | 
|      ASSERT(Map::kSize % 4 == 0);
 | 
|  
 | 
| -    Heap::CopyBlock(reinterpret_cast<Object**>(vacant_map->address()),
 | 
| -                    reinterpret_cast<Object**>(map_to_evacuate->address()),
 | 
| -                    Map::kSize);
 | 
| +    Heap::CopyBlockToOldSpaceAndUpdateRegionMarks(vacant_map->address(),
 | 
| +                                                  map_to_evacuate->address(),
 | 
| +                                                  Map::kSize);
 | 
|  
 | 
|      ASSERT(vacant_map->IsMap());  // Due to memcpy above.
 | 
|  
 | 
| @@ -1756,6 +1753,12 @@ void MarkCompactCollector::SweepSpaces() {
 | 
|    SweepSpace(Heap::cell_space(), &DeallocateCellBlock);
 | 
|    SweepNewSpace(Heap::new_space());
 | 
|    SweepSpace(Heap::map_space(), &DeallocateMapBlock);
 | 
| +
 | 
| +  Heap::IterateDirtyRegions(Heap::map_space(),
 | 
| +                            &Heap::IteratePointersInDirtyMapsRegion,
 | 
| +                            &UpdatePointerToNewGen,
 | 
| +                            Heap::WATERMARK_SHOULD_BE_VALID);
 | 
| +
 | 
|    int live_maps_size = Heap::map_space()->Size();
 | 
|    int live_maps = live_maps_size / Map::kSize;
 | 
|    ASSERT(live_map_objects_size_ == live_maps_size);
 | 
| @@ -1766,7 +1769,6 @@ void MarkCompactCollector::SweepSpaces() {
 | 
|      map_compact.CompactMaps();
 | 
|      map_compact.UpdateMapPointersInRoots();
 | 
|  
 | 
| -    map_compact.FinishMapSpace();
 | 
|      PagedSpaces spaces;
 | 
|      for (PagedSpace* space = spaces.next();
 | 
|           space != NULL; space = spaces.next()) {
 | 
| @@ -2039,9 +2041,8 @@ Address MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) {
 | 
|    Page* forwarded_page = Page::FromAddress(first_forwarded);
 | 
|    int forwarded_offset = forwarded_page->Offset(first_forwarded);
 | 
|  
 | 
| -  // Find end of allocation of in the page of first_forwarded.
 | 
| -  Address mc_top = forwarded_page->mc_relocation_top;
 | 
| -  int mc_top_offset = forwarded_page->Offset(mc_top);
 | 
| +  // Find end of allocation in the page of first_forwarded.
 | 
| +  int mc_top_offset = forwarded_page->AllocationWatermarkOffset();
 | 
|  
 | 
|    // Check if current object's forward pointer is in the same page
 | 
|    // as the first live object's forwarding pointer
 | 
| @@ -2058,7 +2059,7 @@ Address MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) {
 | 
|    offset += Page::kObjectStartOffset;
 | 
|  
 | 
|    ASSERT_PAGE_OFFSET(offset);
 | 
| -  ASSERT(next_page->OffsetToAddress(offset) < next_page->mc_relocation_top);
 | 
| +  ASSERT(next_page->OffsetToAddress(offset) < next_page->AllocationTop());
 | 
|  
 | 
|    return next_page->OffsetToAddress(offset);
 | 
|  }
 | 
| @@ -2103,16 +2104,12 @@ void MarkCompactCollector::RelocateObjects() {
 | 
|    // Flip from and to spaces
 | 
|    Heap::new_space()->Flip();
 | 
|  
 | 
| +  Heap::new_space()->MCCommitRelocationInfo();
 | 
| +
 | 
|    // Set age_mark to bottom in to space
 | 
|    Address mark = Heap::new_space()->bottom();
 | 
|    Heap::new_space()->set_age_mark(mark);
 | 
|  
 | 
| -  Heap::new_space()->MCCommitRelocationInfo();
 | 
| -#ifdef DEBUG
 | 
| -  // It is safe to write to the remembered sets as remembered sets on a
 | 
| -  // page-by-page basis after committing the m-c forwarding pointer.
 | 
| -  Page::set_rset_state(Page::IN_USE);
 | 
| -#endif
 | 
|    PagedSpaces spaces;
 | 
|    for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next())
 | 
|      space->MCCommitRelocationInfo();
 | 
| @@ -2139,9 +2136,9 @@ int MarkCompactCollector::RelocateMapObject(HeapObject* obj) {
 | 
|  
 | 
|    if (new_addr != old_addr) {
 | 
|      // Move contents.
 | 
| -    Heap::MoveBlock(reinterpret_cast<Object**>(new_addr),
 | 
| -                    reinterpret_cast<Object**>(old_addr),
 | 
| -                    Map::kSize);
 | 
| +    Heap::MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
 | 
| +                                                  old_addr,
 | 
| +                                                  Map::kSize);
 | 
|    }
 | 
|  
 | 
|  #ifdef DEBUG
 | 
| @@ -2198,9 +2195,13 @@ int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
 | 
|  
 | 
|    if (new_addr != old_addr) {
 | 
|      // Move contents.
 | 
| -    Heap::MoveBlock(reinterpret_cast<Object**>(new_addr),
 | 
| -                    reinterpret_cast<Object**>(old_addr),
 | 
| -                    obj_size);
 | 
| +    if (space == Heap::old_data_space()) {
 | 
| +      Heap::MoveBlock(new_addr, old_addr, obj_size);
 | 
| +    } else {
 | 
| +      Heap::MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
 | 
| +                                                    old_addr,
 | 
| +                                                    obj_size);
 | 
| +    }
 | 
|    }
 | 
|  
 | 
|    ASSERT(!HeapObject::FromAddress(new_addr)->IsCode());
 | 
| @@ -2245,9 +2246,7 @@ int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
 | 
|  
 | 
|    if (new_addr != old_addr) {
 | 
|      // Move contents.
 | 
| -    Heap::MoveBlock(reinterpret_cast<Object**>(new_addr),
 | 
| -                    reinterpret_cast<Object**>(old_addr),
 | 
| -                    obj_size);
 | 
| +    Heap::MoveBlock(new_addr, old_addr, obj_size);
 | 
|    }
 | 
|  
 | 
|    HeapObject* copied_to = HeapObject::FromAddress(new_addr);
 | 
| @@ -2283,9 +2282,13 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
 | 
|  #endif
 | 
|  
 | 
|    // New and old addresses cannot overlap.
 | 
| -  Heap::CopyBlock(reinterpret_cast<Object**>(new_addr),
 | 
| -                  reinterpret_cast<Object**>(old_addr),
 | 
| -                  obj_size);
 | 
| +  if (Heap::InNewSpace(HeapObject::FromAddress(new_addr))) {
 | 
| +    Heap::CopyBlock(new_addr, old_addr, obj_size);
 | 
| +  } else {
 | 
| +    Heap::CopyBlockToOldSpaceAndUpdateRegionMarks(new_addr,
 | 
| +                                                  old_addr,
 | 
| +                                                  obj_size);
 | 
| +  }
 | 
|  
 | 
|  #ifdef DEBUG
 | 
|    if (FLAG_gc_verbose) {
 | 
| @@ -2302,18 +2305,6 @@ int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -// -------------------------------------------------------------------------
 | 
| -// Phase 5: rebuild remembered sets
 | 
| -
 | 
| -void MarkCompactCollector::RebuildRSets() {
 | 
| -#ifdef DEBUG
 | 
| -  ASSERT(state_ == RELOCATE_OBJECTS);
 | 
| -  state_ = REBUILD_RSETS;
 | 
| -#endif
 | 
| -  Heap::RebuildRSets();
 | 
| -}
 | 
| -
 | 
| -
 | 
|  void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) {
 | 
|  #ifdef ENABLE_LOGGING_AND_PROFILING
 | 
|    if (obj->IsCode()) {
 | 
| 
 |