| Index: src/heap.cc
 | 
| diff --git a/src/heap.cc b/src/heap.cc
 | 
| index c4d0439e0d0b5dc940dca636b49635d7929757c7..dcc0cc6a9ba4a89389a5686d583f6a35bf18cd5d 100644
 | 
| --- a/src/heap.cc
 | 
| +++ b/src/heap.cc
 | 
| @@ -37,6 +37,7 @@
 | 
|  #include "global-handles.h"
 | 
|  #include "mark-compact.h"
 | 
|  #include "natives.h"
 | 
| +#include "objects-visiting.h"
 | 
|  #include "scanner.h"
 | 
|  #include "scopeinfo.h"
 | 
|  #include "snapshot.h"
 | 
| @@ -1032,6 +1033,17 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable(
 | 
|  }
 | 
|  
 | 
|  
 | 
| +class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> {
 | 
| + public:
 | 
| +  static inline void VisitPointer(Object** p) {
 | 
| +    Object* object = *p;
 | 
| +    if (!Heap::InNewSpace(object)) return;
 | 
| +    Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p),
 | 
| +                         reinterpret_cast<HeapObject*>(object));
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +
 | 
|  Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
 | 
|                           Address new_space_front) {
 | 
|    do {
 | 
| @@ -1042,10 +1054,7 @@ Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
 | 
|      // queue is empty.
 | 
|      while (new_space_front < new_space_.top()) {
 | 
|        HeapObject* object = HeapObject::FromAddress(new_space_front);
 | 
| -      Map* map = object->map();
 | 
| -      int size = object->SizeFromMap(map);
 | 
| -      object->IterateBody(map->instance_type(), size, scavenge_visitor);
 | 
| -      new_space_front += size;
 | 
| +      new_space_front += NewSpaceScavenger::IterateBody(object->map(), object);
 | 
|      }
 | 
|  
 | 
|      // Promote and process all the to-be-promoted objects.
 | 
| @@ -1072,315 +1081,231 @@ Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor,
 | 
|  }
 | 
|  
 | 
|  
 | 
| -#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
 | 
| -static void RecordCopiedObject(HeapObject* obj) {
 | 
| -  bool should_record = false;
 | 
| -#ifdef DEBUG
 | 
| -  should_record = FLAG_heap_stats;
 | 
| -#endif
 | 
| -#ifdef ENABLE_LOGGING_AND_PROFILING
 | 
| -  should_record = should_record || FLAG_log_gc;
 | 
| -#endif
 | 
| -  if (should_record) {
 | 
| -    if (Heap::new_space()->Contains(obj)) {
 | 
| -      Heap::new_space()->RecordAllocation(obj);
 | 
| -    } else {
 | 
| -      Heap::new_space()->RecordPromotion(obj);
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -#endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
 | 
| +class ScavengingVisitor : public StaticVisitorBase {
 | 
| + public:
 | 
| +  static void Initialize() {
 | 
| +    table_.Register(kVisitSeqAsciiString, &EvacuateSeqAsciiString);
 | 
| +    table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString);
 | 
| +    table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate);
 | 
| +    table_.Register(kVisitByteArray, &EvacuateByteArray);
 | 
| +    table_.Register(kVisitFixedArray, &EvacuateFixedArray);
 | 
|  
 | 
| +    typedef ObjectEvacuationStrategy<POINTER_OBJECT> PointerObject;
 | 
|  
 | 
| -// Helper function used by CopyObject to copy a source object to an
 | 
| -// allocated target object and update the forwarding pointer in the source
 | 
| -// object.  Returns the target object.
 | 
| -inline static HeapObject* MigrateObject(HeapObject* source,
 | 
| -                                        HeapObject* target,
 | 
| -                                        int size) {
 | 
| -  // Copy the content of source to target.
 | 
| -  Heap::CopyBlock(target->address(), source->address(), size);
 | 
| +    table_.Register(kVisitConsString,
 | 
| +                    &ObjectEvacuationStrategy<POINTER_OBJECT>::
 | 
| +                        VisitSpecialized<ConsString::kSize>);
 | 
|  
 | 
| -  // Set the forwarding address.
 | 
| -  source->set_map_word(MapWord::FromForwardingAddress(target));
 | 
| +    table_.Register(kVisitSharedFunctionInfo,
 | 
| +                    &ObjectEvacuationStrategy<POINTER_OBJECT>::
 | 
| +                        VisitSpecialized<SharedFunctionInfo::kSize>);
 | 
|  
 | 
| -#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
 | 
| -  // Update NewSpace stats if necessary.
 | 
| -  RecordCopiedObject(target);
 | 
| -#endif
 | 
| -  HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address()));
 | 
| +    table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>,
 | 
| +                                   kVisitDataObject,
 | 
| +                                   kVisitDataObjectGeneric>();
 | 
|  
 | 
| -  return target;
 | 
| -}
 | 
| +    table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
 | 
| +                                   kVisitJSObject,
 | 
| +                                   kVisitJSObjectGeneric>();
 | 
|  
 | 
| +    table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>,
 | 
| +                                   kVisitStruct,
 | 
| +                                   kVisitStructGeneric>();
 | 
| +  }
 | 
|  
 | 
| -enum ObjectContents  { DATA_OBJECT, POINTER_OBJECT };
 | 
| -enum SizeRestriction { SMALL, UNKNOWN_SIZE };
 | 
|  
 | 
| +  static inline void Scavenge(Map* map, HeapObject** slot, HeapObject* obj) {
 | 
| +    table_.GetVisitor(map)(map, slot, obj);
 | 
| +  }
 | 
|  
 | 
| -template<ObjectContents object_contents, SizeRestriction size_restriction>
 | 
| -static inline void EvacuateObject(Map* map,
 | 
| -                                  HeapObject** slot,
 | 
| -                                  HeapObject* object,
 | 
| -                                  int object_size) {
 | 
| -  ASSERT((size_restriction != SMALL) ||
 | 
| -         (object_size <= Page::kMaxHeapObjectSize));
 | 
| -  ASSERT(object->Size() == object_size);
 | 
|  
 | 
| -  if (Heap::ShouldBePromoted(object->address(), object_size)) {
 | 
| -    Object* result;
 | 
| + private:
 | 
| +  enum ObjectContents  { DATA_OBJECT, POINTER_OBJECT };
 | 
| +  enum SizeRestriction { SMALL, UNKNOWN_SIZE };
 | 
|  
 | 
| -    if ((size_restriction != SMALL) &&
 | 
| -        (object_size > Page::kMaxHeapObjectSize)) {
 | 
| -      result = Heap::lo_space()->AllocateRawFixedArray(object_size);
 | 
| -    } else {
 | 
| -      if (object_contents == DATA_OBJECT) {
 | 
| -        result = Heap::old_data_space()->AllocateRaw(object_size);
 | 
| +#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
 | 
| +  static void RecordCopiedObject(HeapObject* obj) {
 | 
| +    bool should_record = false;
 | 
| +#ifdef DEBUG
 | 
| +    should_record = FLAG_heap_stats;
 | 
| +#endif
 | 
| +#ifdef ENABLE_LOGGING_AND_PROFILING
 | 
| +    should_record = should_record || FLAG_log_gc;
 | 
| +#endif
 | 
| +    if (should_record) {
 | 
| +      if (Heap::new_space()->Contains(obj)) {
 | 
| +        Heap::new_space()->RecordAllocation(obj);
 | 
|        } else {
 | 
| -        result = Heap::old_pointer_space()->AllocateRaw(object_size);
 | 
| +        Heap::new_space()->RecordPromotion(obj);
 | 
|        }
 | 
|      }
 | 
| -
 | 
| -    if (!result->IsFailure()) {
 | 
| -      HeapObject* target = HeapObject::cast(result);
 | 
| -      *slot = MigrateObject(object, target, object_size);
 | 
| -
 | 
| -      if (object_contents == POINTER_OBJECT) {
 | 
| -        promotion_queue.insert(target, object_size);
 | 
| -      }
 | 
| -
 | 
| -      Heap::tracer()->increment_promoted_objects_size(object_size);
 | 
| -      return;
 | 
| -    }
 | 
|    }
 | 
| -  Object* result = Heap::new_space()->AllocateRaw(object_size);
 | 
| -  ASSERT(!result->IsFailure());
 | 
| -  *slot = MigrateObject(object, HeapObject::cast(result), object_size);
 | 
| -  return;
 | 
| -}
 | 
| +#endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
 | 
|  
 | 
| +  // Helper function used by CopyObject to copy a source object to an
 | 
| +  // allocated target object and update the forwarding pointer in the source
 | 
| +  // object.  Returns the target object.
 | 
| +  INLINE(static HeapObject* MigrateObject(HeapObject* source,
 | 
| +                                          HeapObject* target,
 | 
| +                                          int size)) {
 | 
| +    // Copy the content of source to target.
 | 
| +    Heap::CopyBlock(target->address(), source->address(), size);
 | 
|  
 | 
| -template<int object_size_in_words, ObjectContents object_contents>
 | 
| -static inline void EvacuateObjectOfFixedSize(Map* map,
 | 
| -                                             HeapObject** slot,
 | 
| -                                             HeapObject* object) {
 | 
| -  const int object_size = object_size_in_words << kPointerSizeLog2;
 | 
| -  EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
 | 
| -}
 | 
| +    // Set the forwarding address.
 | 
| +    source->set_map_word(MapWord::FromForwardingAddress(target));
 | 
|  
 | 
| +#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
 | 
| +    // Update NewSpace stats if necessary.
 | 
| +    RecordCopiedObject(target);
 | 
| +#endif
 | 
| +    HEAP_PROFILE(ObjectMoveEvent(source->address(), target->address()));
 | 
|  
 | 
| -template<ObjectContents object_contents>
 | 
| -static inline void EvacuateObjectOfFixedSize(Map* map,
 | 
| -                                             HeapObject** slot,
 | 
| -                                             HeapObject* object) {
 | 
| -  int object_size = map->instance_size();
 | 
| -  EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
 | 
| -}
 | 
| +    return target;
 | 
| +  }
 | 
|  
 | 
|  
 | 
| -static inline void EvacuateFixedArray(Map* map,
 | 
| -                                      HeapObject** slot,
 | 
| -                                      HeapObject* object) {
 | 
| -  int object_size = FixedArray::cast(object)->FixedArraySize();
 | 
| -  EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
 | 
| -}
 | 
| +  template<ObjectContents object_contents, SizeRestriction size_restriction>
 | 
| +  static inline void EvacuateObject(Map* map,
 | 
| +                                    HeapObject** slot,
 | 
| +                                    HeapObject* object,
 | 
| +                                    int object_size) {
 | 
| +    ASSERT((size_restriction != SMALL) ||
 | 
| +           (object_size <= Page::kMaxHeapObjectSize));
 | 
| +    ASSERT(object->Size() == object_size);
 | 
|  
 | 
| +    if (Heap::ShouldBePromoted(object->address(), object_size)) {
 | 
| +      Object* result;
 | 
|  
 | 
| -static inline void EvacuateByteArray(Map* map,
 | 
| -                                     HeapObject** slot,
 | 
| -                                     HeapObject* object) {
 | 
| -  int object_size = ByteArray::cast(object)->ByteArraySize();
 | 
| -  EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
 | 
| -}
 | 
| +      if ((size_restriction != SMALL) &&
 | 
| +          (object_size > Page::kMaxHeapObjectSize)) {
 | 
| +        result = Heap::lo_space()->AllocateRawFixedArray(object_size);
 | 
| +      } else {
 | 
| +        if (object_contents == DATA_OBJECT) {
 | 
| +          result = Heap::old_data_space()->AllocateRaw(object_size);
 | 
| +        } else {
 | 
| +          result = Heap::old_pointer_space()->AllocateRaw(object_size);
 | 
| +        }
 | 
| +      }
 | 
|  
 | 
| +      if (!result->IsFailure()) {
 | 
| +        HeapObject* target = HeapObject::cast(result);
 | 
| +        *slot = MigrateObject(object, target, object_size);
 | 
|  
 | 
| -static Scavenger GetScavengerForSize(int object_size,
 | 
| -                                     ObjectContents object_contents) {
 | 
| -  ASSERT(IsAligned(object_size, kPointerSize));
 | 
| -  ASSERT(object_size < Page::kMaxHeapObjectSize);
 | 
| +        if (object_contents == POINTER_OBJECT) {
 | 
| +          promotion_queue.insert(target, object_size);
 | 
| +        }
 | 
|  
 | 
| -  switch (object_size >> kPointerSizeLog2) {
 | 
| -#define CASE(n)                                           \
 | 
| -    case n:                                               \
 | 
| -      if (object_contents == DATA_OBJECT) {               \
 | 
| -        return static_cast<Scavenger>(                    \
 | 
| -          &EvacuateObjectOfFixedSize<n, DATA_OBJECT>);    \
 | 
| -      } else {                                            \
 | 
| -        return static_cast<Scavenger>(                    \
 | 
| -          &EvacuateObjectOfFixedSize<n, POINTER_OBJECT>); \
 | 
| +        Heap::tracer()->increment_promoted_objects_size(object_size);
 | 
| +        return;
 | 
|        }
 | 
| +    }
 | 
| +    Object* result = Heap::new_space()->AllocateRaw(object_size);
 | 
| +    ASSERT(!result->IsFailure());
 | 
| +    *slot = MigrateObject(object, HeapObject::cast(result), object_size);
 | 
| +    return;
 | 
| +  }
 | 
|  
 | 
| -    CASE(1);
 | 
| -    CASE(2);
 | 
| -    CASE(3);
 | 
| -    CASE(4);
 | 
| -    CASE(5);
 | 
| -    CASE(6);
 | 
| -    CASE(7);
 | 
| -    CASE(8);
 | 
| -    CASE(9);
 | 
| -    CASE(10);
 | 
| -    CASE(11);
 | 
| -    CASE(12);
 | 
| -    CASE(13);
 | 
| -    CASE(14);
 | 
| -    CASE(15);
 | 
| -    CASE(16);
 | 
| -    default:
 | 
| -      if (object_contents == DATA_OBJECT) {
 | 
| -        return static_cast<Scavenger>(&EvacuateObjectOfFixedSize<DATA_OBJECT>);
 | 
| -      } else {
 | 
| -        return static_cast<Scavenger>(
 | 
| -            &EvacuateObjectOfFixedSize<POINTER_OBJECT>);
 | 
| -      }
 | 
|  
 | 
| -#undef CASE
 | 
| +  static inline void EvacuateFixedArray(Map* map,
 | 
| +                                        HeapObject** slot,
 | 
| +                                        HeapObject* object) {
 | 
| +    int object_size = FixedArray::BodyDescriptor::SizeOf(map, object);
 | 
| +    EvacuateObject<POINTER_OBJECT, UNKNOWN_SIZE>(map,
 | 
| +                                                 slot,
 | 
| +                                                 object,
 | 
| +                                                 object_size);
 | 
|    }
 | 
| -}
 | 
|  
 | 
|  
 | 
| -static inline void EvacuateSeqAsciiString(Map* map,
 | 
| -                                          HeapObject** slot,
 | 
| -                                          HeapObject* object) {
 | 
| -  int object_size = SeqAsciiString::cast(object)->
 | 
| -      SeqAsciiStringSize(map->instance_type());
 | 
| -  EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
 | 
| -}
 | 
| +  static inline void EvacuateByteArray(Map* map,
 | 
| +                                       HeapObject** slot,
 | 
| +                                       HeapObject* object) {
 | 
| +    int object_size = reinterpret_cast<ByteArray*>(object)->ByteArraySize();
 | 
| +    EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
 | 
| +  }
 | 
|  
 | 
|  
 | 
| -static inline void EvacuateSeqTwoByteString(Map* map,
 | 
| +  static inline void EvacuateSeqAsciiString(Map* map,
 | 
|                                              HeapObject** slot,
 | 
|                                              HeapObject* object) {
 | 
| -  int object_size = SeqTwoByteString::cast(object)->
 | 
| -      SeqTwoByteStringSize(map->instance_type());
 | 
| -  EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
 | 
| -}
 | 
| +    int object_size = SeqAsciiString::cast(object)->
 | 
| +        SeqAsciiStringSize(map->instance_type());
 | 
| +    EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
 | 
| +  }
 | 
|  
 | 
|  
 | 
| -static inline bool IsShortcutCandidate(int type) {
 | 
| -  return ((type & kShortcutTypeMask) == kShortcutTypeTag);
 | 
| -}
 | 
| +  static inline void EvacuateSeqTwoByteString(Map* map,
 | 
| +                                              HeapObject** slot,
 | 
| +                                              HeapObject* object) {
 | 
| +    int object_size = SeqTwoByteString::cast(object)->
 | 
| +        SeqTwoByteStringSize(map->instance_type());
 | 
| +    EvacuateObject<DATA_OBJECT, UNKNOWN_SIZE>(map, slot, object, object_size);
 | 
| +  }
 | 
|  
 | 
|  
 | 
| -static inline void EvacuateShortcutCandidate(Map* map,
 | 
| -                                             HeapObject** slot,
 | 
| -                                             HeapObject* object) {
 | 
| -  ASSERT(IsShortcutCandidate(map->instance_type()));
 | 
| +  static inline bool IsShortcutCandidate(int type) {
 | 
| +    return ((type & kShortcutTypeMask) == kShortcutTypeTag);
 | 
| +  }
 | 
|  
 | 
| -  if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) {
 | 
| -    HeapObject* first =
 | 
| -        HeapObject::cast(ConsString::cast(object)->unchecked_first());
 | 
| +  static inline void EvacuateShortcutCandidate(Map* map,
 | 
| +                                               HeapObject** slot,
 | 
| +                                               HeapObject* object) {
 | 
| +    ASSERT(IsShortcutCandidate(map->instance_type()));
 | 
|  
 | 
| -    *slot = first;
 | 
| +    if (ConsString::cast(object)->unchecked_second() == Heap::empty_string()) {
 | 
| +      HeapObject* first =
 | 
| +          HeapObject::cast(ConsString::cast(object)->unchecked_first());
 | 
|  
 | 
| -    if (!Heap::InNewSpace(first)) {
 | 
| -      object->set_map_word(MapWord::FromForwardingAddress(first));
 | 
| -      return;
 | 
| -    }
 | 
| +      *slot = first;
 | 
|  
 | 
| -    MapWord first_word = first->map_word();
 | 
| -    if (first_word.IsForwardingAddress()) {
 | 
| -      HeapObject* target = first_word.ToForwardingAddress();
 | 
| +      if (!Heap::InNewSpace(first)) {
 | 
| +        object->set_map_word(MapWord::FromForwardingAddress(first));
 | 
| +        return;
 | 
| +      }
 | 
|  
 | 
| -      *slot = target;
 | 
| -      object->set_map_word(MapWord::FromForwardingAddress(target));
 | 
| +      MapWord first_word = first->map_word();
 | 
| +      if (first_word.IsForwardingAddress()) {
 | 
| +        HeapObject* target = first_word.ToForwardingAddress();
 | 
| +
 | 
| +        *slot = target;
 | 
| +        object->set_map_word(MapWord::FromForwardingAddress(target));
 | 
| +        return;
 | 
| +      }
 | 
| +
 | 
| +      Scavenge(first->map(), slot, first);
 | 
| +      object->set_map_word(MapWord::FromForwardingAddress(*slot));
 | 
|        return;
 | 
|      }
 | 
|  
 | 
| -    first->map()->Scavenge(slot, first);
 | 
| -    object->set_map_word(MapWord::FromForwardingAddress(*slot));
 | 
| -    return;
 | 
| +    int object_size = ConsString::kSize;
 | 
| +    EvacuateObject<POINTER_OBJECT, SMALL>(map, slot, object, object_size);
 | 
|    }
 | 
|  
 | 
| -  int object_size = ConsString::kSize;
 | 
| -  EvacuateObject<POINTER_OBJECT, SMALL>(map, slot, object, object_size);
 | 
| -}
 | 
| -
 | 
| -
 | 
| -Scavenger Heap::GetScavenger(int instance_type, int instance_size) {
 | 
| -  if (instance_type < FIRST_NONSTRING_TYPE) {
 | 
| -    switch (instance_type & kStringRepresentationMask) {
 | 
| -      case kSeqStringTag:
 | 
| -        if ((instance_type & kStringEncodingMask) == kAsciiStringTag) {
 | 
| -          return &EvacuateSeqAsciiString;
 | 
| -        } else {
 | 
| -          return &EvacuateSeqTwoByteString;
 | 
| -        }
 | 
| -
 | 
| -      case kConsStringTag:
 | 
| -        if (IsShortcutCandidate(instance_type)) {
 | 
| -          return &EvacuateShortcutCandidate;
 | 
| -        } else {
 | 
| -          ASSERT(instance_size == ConsString::kSize);
 | 
| -          return GetScavengerForSize(ConsString::kSize, POINTER_OBJECT);
 | 
| -        }
 | 
| -
 | 
| -      case kExternalStringTag:
 | 
| -        ASSERT(instance_size == ExternalString::kSize);
 | 
| -        return GetScavengerForSize(ExternalString::kSize, DATA_OBJECT);
 | 
| +  template<ObjectContents object_contents>
 | 
| +  class ObjectEvacuationStrategy {
 | 
| +   public:
 | 
| +    template<int object_size>
 | 
| +    static inline void VisitSpecialized(Map* map,
 | 
| +                                        HeapObject** slot,
 | 
| +                                        HeapObject* object) {
 | 
| +      EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
 | 
|      }
 | 
| -    UNREACHABLE();
 | 
| -  }
 | 
| -
 | 
| -  switch (instance_type) {
 | 
| -    case BYTE_ARRAY_TYPE:
 | 
| -      return reinterpret_cast<Scavenger>(&EvacuateByteArray);
 | 
|  
 | 
| -    case FIXED_ARRAY_TYPE:
 | 
| -      return reinterpret_cast<Scavenger>(&EvacuateFixedArray);
 | 
| -
 | 
| -    case JS_OBJECT_TYPE:
 | 
| -    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
 | 
| -    case JS_VALUE_TYPE:
 | 
| -    case JS_ARRAY_TYPE:
 | 
| -    case JS_REGEXP_TYPE:
 | 
| -    case JS_FUNCTION_TYPE:
 | 
| -    case JS_GLOBAL_PROXY_TYPE:
 | 
| -    case JS_GLOBAL_OBJECT_TYPE:
 | 
| -    case JS_BUILTINS_OBJECT_TYPE:
 | 
| -      return GetScavengerForSize(instance_size, POINTER_OBJECT);
 | 
| -
 | 
| -    case ODDBALL_TYPE:
 | 
| -      return NULL;
 | 
| -
 | 
| -    case PROXY_TYPE:
 | 
| -      return GetScavengerForSize(Proxy::kSize, DATA_OBJECT);
 | 
| +    static inline void Visit(Map* map,
 | 
| +                             HeapObject** slot,
 | 
| +                             HeapObject* object) {
 | 
| +      int object_size = map->instance_size();
 | 
| +      EvacuateObject<object_contents, SMALL>(map, slot, object, object_size);
 | 
| +    }
 | 
| +  };
 | 
|  
 | 
| -    case MAP_TYPE:
 | 
| -      return NULL;
 | 
| +  typedef void (*Callback)(Map* map, HeapObject** slot, HeapObject* object);
 | 
|  
 | 
| -    case CODE_TYPE:
 | 
| -      return NULL;
 | 
| +  static VisitorDispatchTable<Callback> table_;
 | 
| +};
 | 
|  
 | 
| -    case JS_GLOBAL_PROPERTY_CELL_TYPE:
 | 
| -      return NULL;
 | 
|  
 | 
| -    case HEAP_NUMBER_TYPE:
 | 
| -    case FILLER_TYPE:
 | 
| -    case PIXEL_ARRAY_TYPE:
 | 
| -    case EXTERNAL_BYTE_ARRAY_TYPE:
 | 
| -    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
 | 
| -    case EXTERNAL_SHORT_ARRAY_TYPE:
 | 
| -    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
 | 
| -    case EXTERNAL_INT_ARRAY_TYPE:
 | 
| -    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
 | 
| -    case EXTERNAL_FLOAT_ARRAY_TYPE:
 | 
| -      return GetScavengerForSize(instance_size, DATA_OBJECT);
 | 
| -
 | 
| -    case SHARED_FUNCTION_INFO_TYPE:
 | 
| -      return GetScavengerForSize(SharedFunctionInfo::kAlignedSize,
 | 
| -                                 POINTER_OBJECT);
 | 
| -
 | 
| -#define MAKE_STRUCT_CASE(NAME, Name, name) \
 | 
| -        case NAME##_TYPE:
 | 
| -      STRUCT_LIST(MAKE_STRUCT_CASE)
 | 
| -#undef MAKE_STRUCT_CASE
 | 
| -          return GetScavengerForSize(instance_size, POINTER_OBJECT);
 | 
| -    default:
 | 
| -      UNREACHABLE();
 | 
| -      return NULL;
 | 
| -  }
 | 
| -}
 | 
| +VisitorDispatchTable<ScavengingVisitor::Callback> ScavengingVisitor::table_;
 | 
|  
 | 
|  
 | 
|  void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
 | 
| @@ -1388,7 +1313,7 @@ void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
 | 
|    MapWord first_word = object->map_word();
 | 
|    ASSERT(!first_word.IsForwardingAddress());
 | 
|    Map* map = first_word.ToMap();
 | 
| -  map->Scavenge(p, object);
 | 
| +  ScavengingVisitor::Scavenge(map, p, object);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -1407,7 +1332,8 @@ Object* Heap::AllocatePartialMap(InstanceType instance_type,
 | 
|    reinterpret_cast<Map*>(result)->set_instance_type(instance_type);
 | 
|    reinterpret_cast<Map*>(result)->set_instance_size(instance_size);
 | 
|    reinterpret_cast<Map*>(result)->
 | 
| -      set_scavenger(GetScavenger(instance_type, instance_size));
 | 
| +      set_visitor_id(
 | 
| +          StaticVisitorBase::GetVisitorId(instance_type, instance_size));
 | 
|    reinterpret_cast<Map*>(result)->set_inobject_properties(0);
 | 
|    reinterpret_cast<Map*>(result)->set_pre_allocated_property_fields(0);
 | 
|    reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
 | 
| @@ -1424,7 +1350,8 @@ Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) {
 | 
|    Map* map = reinterpret_cast<Map*>(result);
 | 
|    map->set_map(meta_map());
 | 
|    map->set_instance_type(instance_type);
 | 
| -  map->set_scavenger(GetScavenger(instance_type, instance_size));
 | 
| +  map->set_visitor_id(
 | 
| +      StaticVisitorBase::GetVisitorId(instance_type, instance_size));
 | 
|    map->set_prototype(null_value());
 | 
|    map->set_constructor(null_value());
 | 
|    map->set_instance_size(instance_size);
 | 
| @@ -4174,6 +4101,10 @@ bool Heap::Setup(bool create_heap_objects) {
 | 
|      if (!ConfigureHeapDefault()) return false;
 | 
|    }
 | 
|  
 | 
| +  ScavengingVisitor::Initialize();
 | 
| +  NewSpaceScavenger::Initialize();
 | 
| +  MarkCompactCollector::Initialize();
 | 
| +
 | 
|    // Setup memory allocator and reserve a chunk of memory for new
 | 
|    // space.  The chunk is double the size of the requested reserved
 | 
|    // new space size to ensure that we can find a pair of semispaces that
 | 
| @@ -4858,6 +4789,7 @@ GCTracer::~GCTracer() {
 | 
|      PrintF("external=%d ", static_cast<int>(scopes_[Scope::EXTERNAL]));
 | 
|      PrintF("mark=%d ", static_cast<int>(scopes_[Scope::MC_MARK]));
 | 
|      PrintF("sweep=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP]));
 | 
| +    PrintF("sweepns=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP_NEWSPACE]));
 | 
|      PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT]));
 | 
|      PrintF("flushcode=%d ", static_cast<int>(scopes_[Scope::MC_FLUSH_CODE]));
 | 
|  
 | 
| 
 |