| Index: src/heap/objects-visiting.h
 | 
| diff --git a/src/heap/objects-visiting.h b/src/heap/objects-visiting.h
 | 
| index db6b892ada05de2ec30dfbdf1b3ffdc1c20c1209..b25b44963627e29d20bbef280b4187b02023b6e8 100644
 | 
| --- a/src/heap/objects-visiting.h
 | 
| +++ b/src/heap/objects-visiting.h
 | 
| @@ -6,6 +6,7 @@
 | 
|  #define V8_OBJECTS_VISITING_H_
 | 
|  
 | 
|  #include "src/allocation.h"
 | 
| +#include "src/layout-descriptor.h"
 | 
|  
 | 
|  // This file provides base classes and auxiliary methods for defining
 | 
|  // static object visitors used during GC.
 | 
| @@ -105,21 +106,29 @@ class StaticVisitorBase : public AllStatic {
 | 
|  
 | 
|    // Determine which specialized visitor should be used for given instance type
 | 
|    // and instance type.
 | 
| -  static VisitorId GetVisitorId(int instance_type, int instance_size);
 | 
| +  static VisitorId GetVisitorId(int instance_type, int instance_size,
 | 
| +                                bool has_unboxed_fields);
 | 
|  
 | 
| +  // Determine which specialized visitor should be used for given map.
 | 
|    static VisitorId GetVisitorId(Map* map) {
 | 
| -    return GetVisitorId(map->instance_type(), map->instance_size());
 | 
| +    return GetVisitorId(map->instance_type(), map->instance_size(),
 | 
| +                        FLAG_unbox_double_fields &&
 | 
| +                            !map->layout_descriptor()->IsFastPointerLayout());
 | 
|    }
 | 
|  
 | 
|    // For visitors that allow specialization by size calculate VisitorId based
 | 
|    // on size, base visitor id and generic visitor id.
 | 
|    static VisitorId GetVisitorIdForSize(VisitorId base, VisitorId generic,
 | 
| -                                       int object_size) {
 | 
| +                                       int object_size,
 | 
| +                                       bool has_unboxed_fields) {
 | 
|      DCHECK((base == kVisitDataObject) || (base == kVisitStruct) ||
 | 
|             (base == kVisitJSObject));
 | 
|      DCHECK(IsAligned(object_size, kPointerSize));
 | 
|      DCHECK(kMinObjectSizeInWords * kPointerSize <= object_size);
 | 
|      DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
 | 
| +    DCHECK(!has_unboxed_fields || (base == kVisitJSObject));
 | 
| +
 | 
| +    if (has_unboxed_fields) return generic;
 | 
|  
 | 
|      const VisitorId specialization = static_cast<VisitorId>(
 | 
|          base + (object_size >> kPointerSizeLog2) - kMinObjectSizeInWords);
 | 
| @@ -158,7 +167,7 @@ class VisitorDispatchTable {
 | 
|              StaticVisitorBase::VisitorId generic, int object_size_in_words>
 | 
|    void RegisterSpecialization() {
 | 
|      static const int size = object_size_in_words * kPointerSize;
 | 
| -    Register(StaticVisitorBase::GetVisitorIdForSize(base, generic, size),
 | 
| +    Register(StaticVisitorBase::GetVisitorIdForSize(base, generic, size, false),
 | 
|               &Visitor::template VisitSpecialized<size>);
 | 
|    }
 | 
|  
 | 
| @@ -189,11 +198,47 @@ class BodyVisitorBase : public AllStatic {
 | 
|   public:
 | 
|    INLINE(static void IteratePointers(Heap* heap, HeapObject* object,
 | 
|                                       int start_offset, int end_offset)) {
 | 
| -    Object** start_slot =
 | 
| -        reinterpret_cast<Object**>(object->address() + start_offset);
 | 
| -    Object** end_slot =
 | 
| -        reinterpret_cast<Object**>(object->address() + end_offset);
 | 
| -    StaticVisitor::VisitPointers(heap, start_slot, end_slot);
 | 
| +    DCHECK(!FLAG_unbox_double_fields ||
 | 
| +           object->map()->layout_descriptor()->IsFastPointerLayout());
 | 
| +    IterateRawPointers(heap, object, start_offset, end_offset);
 | 
| +  }
 | 
| +
 | 
| +  INLINE(static void IterateBody(Heap* heap, HeapObject* object,
 | 
| +                                 int start_offset, int end_offset)) {
 | 
| +    if (!FLAG_unbox_double_fields ||
 | 
| +        object->map()->layout_descriptor()->IsFastPointerLayout()) {
 | 
| +      IterateRawPointers(heap, object, start_offset, end_offset);
 | 
| +    } else {
 | 
| +      IterateBodyUsingLayoutDescriptor(heap, object, start_offset, end_offset);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| + private:
 | 
| +  INLINE(static void IterateRawPointers(Heap* heap, HeapObject* object,
 | 
| +                                        int start_offset, int end_offset)) {
 | 
| +    StaticVisitor::VisitPointers(heap,
 | 
| +                                 HeapObject::RawField(object, start_offset),
 | 
| +                                 HeapObject::RawField(object, end_offset));
 | 
| +  }
 | 
| +
 | 
| +  static void IterateBodyUsingLayoutDescriptor(Heap* heap, HeapObject* object,
 | 
| +                                               int start_offset,
 | 
| +                                               int end_offset) {
 | 
| +    DCHECK(FLAG_unbox_double_fields);
 | 
| +    DCHECK(IsAligned(start_offset, kPointerSize) &&
 | 
| +           IsAligned(end_offset, kPointerSize));
 | 
| +
 | 
| +    InobjectPropertiesHelper helper(object->map());
 | 
| +    DCHECK(!helper.all_fields_tagged());
 | 
| +
 | 
| +    for (int offset = start_offset; offset < end_offset;
 | 
| +         offset += kPointerSize) {
 | 
| +      // Visit tagged fields only.
 | 
| +      if (helper.IsTagged(offset)) {
 | 
| +        // TODO(ishell): call this once for contiguous region of tagged fields.
 | 
| +        IterateRawPointers(heap, object, offset, offset + kPointerSize);
 | 
| +      }
 | 
| +    }
 | 
|    }
 | 
|  };
 | 
|  
 | 
| @@ -203,7 +248,7 @@ class FlexibleBodyVisitor : public BodyVisitorBase<StaticVisitor> {
 | 
|   public:
 | 
|    INLINE(static ReturnType Visit(Map* map, HeapObject* object)) {
 | 
|      int object_size = BodyDescriptor::SizeOf(map, object);
 | 
| -    BodyVisitorBase<StaticVisitor>::IteratePointers(
 | 
| +    BodyVisitorBase<StaticVisitor>::IterateBody(
 | 
|          map->GetHeap(), object, BodyDescriptor::kStartOffset, object_size);
 | 
|      return static_cast<ReturnType>(object_size);
 | 
|    }
 | 
| @@ -222,9 +267,9 @@ template <typename StaticVisitor, typename BodyDescriptor, typename ReturnType>
 | 
|  class FixedBodyVisitor : public BodyVisitorBase<StaticVisitor> {
 | 
|   public:
 | 
|    INLINE(static ReturnType Visit(Map* map, HeapObject* object)) {
 | 
| -    BodyVisitorBase<StaticVisitor>::IteratePointers(
 | 
| -        map->GetHeap(), object, BodyDescriptor::kStartOffset,
 | 
| -        BodyDescriptor::kEndOffset);
 | 
| +    BodyVisitorBase<StaticVisitor>::IterateBody(map->GetHeap(), object,
 | 
| +                                                BodyDescriptor::kStartOffset,
 | 
| +                                                BodyDescriptor::kEndOffset);
 | 
|      return static_cast<ReturnType>(BodyDescriptor::kSize);
 | 
|    }
 | 
|  };
 | 
| 
 |