Allow property indexes to refer to slots inside the object header.
authormmassi@chromium.org <mmassi@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 13 Nov 2012 11:07:04 +0000 (11:07 +0000)
committermmassi@chromium.org <mmassi@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 13 Nov 2012 11:07:04 +0000 (11:07 +0000)
BUG=

Review URL: https://chromiumcodereview.appspot.com/11365221

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12944 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

13 files changed:
src/arm/stub-cache-arm.cc
src/bootstrapper.cc
src/ia32/stub-cache-ia32.cc
src/ic.cc
src/json-stringifier.h
src/mips/stub-cache-mips.cc
src/objects.cc
src/property.cc
src/property.h
src/runtime.cc
src/stub-cache.cc
src/stub-cache.h
src/x64/stub-cache-x64.cc

index 9fc39d4..b039b3d 100644 (file)
@@ -327,18 +327,23 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
                                             Register dst,
                                             Register src,
                                             Handle<JSObject> holder,
-                                            int index) {
-  // Adjust for the number of properties stored in the holder.
-  index -= holder->map()->inobject_properties();
-  if (index < 0) {
-    // Get the property straight out of the holder.
-    int offset = holder->map()->instance_size() + (index * kPointerSize);
+                                            PropertyIndex index) {
+  if (index.is_header_index()) {
+    int offset = index.header_index() * kPointerSize;
     __ ldr(dst, FieldMemOperand(src, offset));
   } else {
-    // Calculate the offset into the properties array.
-    int offset = index * kPointerSize + FixedArray::kHeaderSize;
-    __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
-    __ ldr(dst, FieldMemOperand(dst, offset));
+    // Adjust for the number of properties stored in the holder.
+    int slot = index.field_index() - holder->map()->inobject_properties();
+    if (slot < 0) {
+      // Get the property straight out of the holder.
+      int offset = holder->map()->instance_size() + (slot * kPointerSize);
+      __ ldr(dst, FieldMemOperand(src, offset));
+    } else {
+      // Calculate the offset into the properties array.
+      int offset = slot * kPointerSize + FixedArray::kHeaderSize;
+      __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
+      __ ldr(dst, FieldMemOperand(dst, offset));
+    }
   }
 }
 
@@ -1196,7 +1201,7 @@ void StubCompiler::GenerateLoadField(Handle<JSObject> object,
                                      Register scratch1,
                                      Register scratch2,
                                      Register scratch3,
-                                     int index,
+                                     PropertyIndex index,
                                      Handle<String> name,
                                      Label* miss) {
   // Check that the receiver isn't a smi.
@@ -1545,7 +1550,7 @@ void CallStubCompiler::GenerateMissBranch() {
 
 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
-                                                int index,
+                                                PropertyIndex index,
                                                 Handle<String> name) {
   // ----------- S t a t e -------------
   //  -- r2    : name
@@ -2912,7 +2917,7 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
 
 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
-                                                int index,
+                                                PropertyIndex index,
                                                 Handle<String> name) {
   // ----------- S t a t e -------------
   //  -- r0    : receiver
@@ -3101,7 +3106,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
                                                      Handle<JSObject> receiver,
                                                      Handle<JSObject> holder,
-                                                     int index) {
+                                                     PropertyIndex index) {
   // ----------- S t a t e -------------
   //  -- lr    : return address
   //  -- r0    : key
index ffa5283..0466e31 100644 (file)
@@ -1084,11 +1084,11 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
     LookupResult lookup(isolate);
     result->LocalLookup(heap->callee_symbol(), &lookup);
     ASSERT(lookup.IsField());
-    ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsCalleeIndex);
+    ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsCalleeIndex);
 
     result->LocalLookup(heap->length_symbol(), &lookup);
     ASSERT(lookup.IsField());
-    ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex);
+    ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
 
     ASSERT(result->map()->inobject_properties() > Heap::kArgumentsCalleeIndex);
     ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);
@@ -1186,7 +1186,7 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
     LookupResult lookup(isolate);
     result->LocalLookup(heap->length_symbol(), &lookup);
     ASSERT(lookup.IsField());
-    ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex);
+    ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
 
     ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);
 
index 11efb72..127d16a 100644 (file)
@@ -376,18 +376,23 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
                                             Register dst,
                                             Register src,
                                             Handle<JSObject> holder,
-                                            int index) {
-  // Adjust for the number of properties stored in the holder.
-  index -= holder->map()->inobject_properties();
-  if (index < 0) {
-    // Get the property straight out of the holder.
-    int offset = holder->map()->instance_size() + (index * kPointerSize);
+                                            PropertyIndex index) {
+  if (index.is_header_index()) {
+    int offset = index.header_index() * kPointerSize;
     __ mov(dst, FieldOperand(src, offset));
   } else {
-    // Calculate the offset into the properties array.
-    int offset = index * kPointerSize + FixedArray::kHeaderSize;
-    __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
-    __ mov(dst, FieldOperand(dst, offset));
+    // Adjust for the number of properties stored in the holder.
+    int slot = index.field_index() - holder->map()->inobject_properties();
+    if (slot < 0) {
+      // Get the property straight out of the holder.
+      int offset = holder->map()->instance_size() + (slot * kPointerSize);
+      __ mov(dst, FieldOperand(src, offset));
+    } else {
+      // Calculate the offset into the properties array.
+      int offset = slot * kPointerSize + FixedArray::kHeaderSize;
+      __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset));
+      __ mov(dst, FieldOperand(dst, offset));
+    }
   }
 }
 
@@ -1036,7 +1041,7 @@ void StubCompiler::GenerateLoadField(Handle<JSObject> object,
                                      Register scratch1,
                                      Register scratch2,
                                      Register scratch3,
-                                     int index,
+                                     PropertyIndex index,
                                      Handle<String> name,
                                      Label* miss) {
   // Check that the receiver isn't a smi.
@@ -1423,7 +1428,7 @@ void CallStubCompiler::GenerateMissBranch() {
 
 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
-                                                int index,
+                                                PropertyIndex index,
                                                 Handle<String> name) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
@@ -2956,7 +2961,7 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
 
 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
-                                                int index,
+                                                PropertyIndex index,
                                                 Handle<String> name) {
   // ----------- S t a t e -------------
   //  -- ecx    : name
@@ -3156,7 +3161,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
                                                      Handle<JSObject> receiver,
                                                      Handle<JSObject> holder,
-                                                     int index) {
+                                                     PropertyIndex index) {
   // ----------- S t a t e -------------
   //  -- ecx    : key
   //  -- edx    : receiver
index 5cc213f..1418f02 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -646,7 +646,7 @@ Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
   Handle<JSObject> holder(lookup->holder());
   switch (lookup->type()) {
     case FIELD: {
-      int index = lookup->GetFieldIndex();
+      PropertyIndex index = lookup->GetFieldIndex();
       return isolate()->stub_cache()->ComputeCallField(
           argc, kind_, extra_state, name, object, holder, index);
     }
@@ -1467,11 +1467,9 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
   Handle<Code> code;
   switch (type) {
     case FIELD:
-      code = isolate()->stub_cache()->ComputeStoreField(name,
-                                                        receiver,
-                                                        lookup->GetFieldIndex(),
-                                                        Handle<Map>::null(),
-                                                        strict_mode);
+      code = isolate()->stub_cache()->ComputeStoreField(
+          name, receiver, lookup->GetFieldIndex().field_index(),
+          Handle<Map>::null(), strict_mode);
       break;
     case NORMAL:
       if (receiver->IsGlobalObject()) {
@@ -1981,7 +1979,7 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
   switch (type) {
     case FIELD:
       code = isolate()->stub_cache()->ComputeKeyedStoreField(
-          name, receiver, lookup->GetFieldIndex(),
+          name, receiver, lookup->GetFieldIndex().field_index(),
           Handle<Map>::null(), strict_mode);
       break;
     case TRANSITION: {
index cdb724f..68dc82a 100644 (file)
@@ -274,7 +274,8 @@ Handle<Object> BasicJsonStringifier::GetProperty(Handle<JSObject> object,
       return Handle<Object>(value, isolate_);
     }
     case FIELD: {
-      Object* value = lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
+      Object* value = lookup.holder()->FastPropertyAt(
+          lookup.GetFieldIndex().field_index());
       ASSERT(!value->IsTheHole());
       return Handle<Object>(value, isolate_);
     }
index bd15775..22e6174 100644 (file)
@@ -314,18 +314,23 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
                                             Register dst,
                                             Register src,
                                             Handle<JSObject> holder,
-                                            int index) {
-  // Adjust for the number of properties stored in the holder.
-  index -= holder->map()->inobject_properties();
-  if (index < 0) {
-    // Get the property straight out of the holder.
-    int offset = holder->map()->instance_size() + (index * kPointerSize);
+                                            PropertyIndex index) {
+  if (index.is_header_index()) {
+    int offset = index.header_index() * kPointerSize;
     __ lw(dst, FieldMemOperand(src, offset));
   } else {
-    // Calculate the offset into the properties array.
-    int offset = index * kPointerSize + FixedArray::kHeaderSize;
-    __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
-    __ lw(dst, FieldMemOperand(dst, offset));
+    // Adjust for the number of properties stored in the holder.
+    int slot = index.field_index() - holder->map()->inobject_properties();
+    if (slot < 0) {
+      // Get the property straight out of the holder.
+      int offset = holder->map()->instance_size() + (slot * kPointerSize);
+      __ lw(dst, FieldMemOperand(src, offset));
+    } else {
+      // Calculate the offset into the properties array.
+      int offset = slot * kPointerSize + FixedArray::kHeaderSize;
+      __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
+      __ lw(dst, FieldMemOperand(dst, offset));
+    }
   }
 }
 
@@ -1200,7 +1205,7 @@ void StubCompiler::GenerateLoadField(Handle<JSObject> object,
                                      Register scratch1,
                                      Register scratch2,
                                      Register scratch3,
-                                     int index,
+                                     PropertyIndex index,
                                      Handle<String> name,
                                      Label* miss) {
   // Check that the receiver isn't a smi.
index fa5bfed..f8d080d 100644 (file)
@@ -641,7 +641,8 @@ MaybeObject* Object::GetProperty(Object* receiver,
       ASSERT(!value->IsTheHole() || result->IsReadOnly());
       return value->IsTheHole() ? heap->undefined_value() : value;
     case FIELD:
-      value = result->holder()->FastPropertyAt(result->GetFieldIndex());
+      value = result->holder()->FastPropertyAt(
+          result->GetFieldIndex().field_index());
       ASSERT(!value->IsTheHole() || result->IsReadOnly());
       return value->IsTheHole() ? heap->undefined_value() : value;
     case CONSTANT_FUNCTION:
@@ -2436,7 +2437,7 @@ void JSObject::LocalLookupRealNamedProperty(String* name,
     // occur as fields.
     if (result->IsField() &&
         result->IsReadOnly() &&
-        FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
+        FastPropertyAt(result->GetFieldIndex().field_index())->IsTheHole()) {
       result->DisallowCaching();
     }
     return;
@@ -2929,7 +2930,8 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
       result = self->SetNormalizedProperty(lookup, *value);
       break;
     case FIELD:
-      result = self->FastPropertyAtPut(lookup->GetFieldIndex(), *value);
+      result = self->FastPropertyAtPut(
+          lookup->GetFieldIndex().field_index(), *value);
       break;
     case CONSTANT_FUNCTION:
       // Only replace the function if necessary.
@@ -3095,7 +3097,8 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
       break;
     }
     case FIELD:
-      result = self->FastPropertyAtPut(lookup.GetFieldIndex(), *value);
+      result = self->FastPropertyAtPut(
+          lookup.GetFieldIndex().field_index(), *value);
       break;
     case CONSTANT_FUNCTION:
       // Only replace the function if necessary.
index 05342ee..cbf2fc8 100644 (file)
@@ -63,7 +63,7 @@ void LookupResult::Print(FILE* out) {
       break;
     case FIELD:
       PrintF(out, " -type = field\n");
-      PrintF(out, " -index = %d", GetFieldIndex());
+      PrintF(out, " -index = %d", GetFieldIndex().field_index());
       PrintF(out, "\n");
       break;
     case CALLBACKS:
index 3faa28b..c41c6dc 100644 (file)
@@ -132,6 +132,44 @@ class CallbacksDescriptor:  public Descriptor {
 };
 
 
+// Holds a property index value distinguishing if it is a field index or an
+// index inside the object header.
+class PropertyIndex {
+ public:
+  static PropertyIndex NewFieldIndex(int index) {
+    return PropertyIndex(index, false);
+  }
+  static PropertyIndex NewHeaderIndex(int index) {
+    return PropertyIndex(index, true);
+  }
+
+  bool is_field_index() { return (index_ & kHeaderIndexBit) == 0; }
+  bool is_header_index() { return (index_ & kHeaderIndexBit) != 0; }
+
+  int field_index() {
+    ASSERT(is_field_index());
+    return value();
+  }
+  int header_index() {
+    ASSERT(is_header_index());
+    return value();
+  }
+
+ private:
+  static const int kHeaderIndexBit = 1 << 31;
+  static const int kIndexMask = ~kHeaderIndexBit;
+
+  int value() { return index_ & kIndexMask; }
+
+  PropertyIndex(int index, bool is_header_based)
+      : index_(index | (is_header_based ? kHeaderIndexBit : 0)) {
+    ASSERT(index <= kIndexMask);
+  }
+
+  int index_;
+};
+
+
 class LookupResult BASE_EMBEDDED {
  public:
   explicit LookupResult(Isolate* isolate)
@@ -278,7 +316,7 @@ class LookupResult BASE_EMBEDDED {
   Object* GetLazyValue() {
     switch (type()) {
       case FIELD:
-        return holder()->FastPropertyAt(GetFieldIndex());
+        return holder()->FastPropertyAt(GetFieldIndex().field_index());
       case NORMAL: {
         Object* value;
         value = holder()->property_dictionary()->ValueAt(GetDictionaryEntry());
@@ -334,10 +372,11 @@ class LookupResult BASE_EMBEDDED {
     return number_;
   }
 
-  int GetFieldIndex() {
+  PropertyIndex GetFieldIndex() {
     ASSERT(lookup_type_ == DESCRIPTOR_TYPE);
     ASSERT(IsField());
-    return Descriptor::IndexFromValue(GetValue());
+    return PropertyIndex::NewFieldIndex(
+        Descriptor::IndexFromValue(GetValue()));
   }
 
   int GetLocalFieldIndexFromMap(Map* map) {
index 71c48bc..de74f2c 100644 (file)
@@ -1679,7 +1679,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
   // Strict mode handling not needed (const is disallowed in strict mode).
   if (lookup.IsField()) {
     FixedArray* properties = global->properties();
-    int index = lookup.GetFieldIndex();
+    int index = lookup.GetFieldIndex().field_index();
     if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
       properties->set(index, *value);
     }
@@ -1769,7 +1769,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
 
     if (lookup.IsField()) {
       FixedArray* properties = object->properties();
-      int index = lookup.GetFieldIndex();
+      int index = lookup.GetFieldIndex().field_index();
       if (properties->get(index)->IsTheHole()) {
         properties->set(index, *value);
       }
@@ -4076,7 +4076,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
         LookupResult result(isolate);
         receiver->LocalLookup(key, &result);
         if (result.IsField()) {
-          int offset = result.GetFieldIndex();
+          int offset = result.GetFieldIndex().field_index();
           keyed_lookup_cache->Update(receiver_map, key, offset);
           return receiver->FastPropertyAt(offset);
         }
@@ -4250,7 +4250,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
     case NORMAL:
       return lookup.holder()->GetNormalizedProperty(&lookup);
     case FIELD:
-      return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
+      return lookup.holder()->FastPropertyAt(
+          lookup.GetFieldIndex().field_index());
     case CONSTANT_FUNCTION:
       return lookup.GetConstantFunction();
     case CALLBACKS:
@@ -10010,8 +10011,8 @@ static MaybeObject* DebugLookupResultValue(Heap* heap,
       return value;
     case FIELD:
       value =
-          JSObject::cast(
-              result->holder())->FastPropertyAt(result->GetFieldIndex());
+          JSObject::cast(result->holder())->FastPropertyAt(
+              result->GetFieldIndex().field_index());
       if (value->IsTheHole()) {
         return heap->undefined_value();
       }
index 5eb0cba..fcb8a4e 100644 (file)
@@ -136,7 +136,7 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
 Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
                                          Handle<JSObject> receiver,
                                          Handle<JSObject> holder,
-                                         int field_index) {
+                                         PropertyIndex field_index) {
   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, Code::FIELD);
   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
@@ -261,7 +261,7 @@ Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
 Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
                                               Handle<JSObject> receiver,
                                               Handle<JSObject> holder,
-                                              int field_index) {
+                                              PropertyIndex field_index) {
   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
   Code::Flags flags =
       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::FIELD);
@@ -632,7 +632,7 @@ Handle<Code> StubCache::ComputeCallField(int argc,
                                          Handle<String> name,
                                          Handle<Object> object,
                                          Handle<JSObject> holder,
-                                         int index) {
+                                         PropertyIndex index) {
   // Compute the check type and the map.
   InlineCacheHolderFlag cache_holder =
       IC::GetCodeCacheForObject(*object, *holder);
index 005c537..f858e47 100644 (file)
@@ -83,7 +83,7 @@ class StubCache {
   Handle<Code> ComputeLoadField(Handle<String> name,
                                 Handle<JSObject> receiver,
                                 Handle<JSObject> holder,
-                                int field_index);
+                                PropertyIndex field_index);
 
   Handle<Code> ComputeLoadCallback(Handle<String> name,
                                    Handle<JSObject> receiver,
@@ -117,7 +117,7 @@ class StubCache {
   Handle<Code> ComputeKeyedLoadField(Handle<String> name,
                                      Handle<JSObject> receiver,
                                      Handle<JSObject> holder,
-                                     int field_index);
+                                     PropertyIndex field_index);
 
   Handle<Code> ComputeKeyedLoadCallback(Handle<String> name,
                                         Handle<JSObject> receiver,
@@ -193,7 +193,7 @@ class StubCache {
                                 Handle<String> name,
                                 Handle<Object> object,
                                 Handle<JSObject> holder,
-                                int index);
+                                PropertyIndex index);
 
   Handle<Code> ComputeCallConstant(int argc,
                                    Code::Kind,
@@ -453,7 +453,7 @@ class StubCompiler BASE_EMBEDDED {
                                        Register dst,
                                        Register src,
                                        Handle<JSObject> holder,
-                                       int index);
+                                       PropertyIndex index);
 
   static void GenerateLoadArrayLength(MacroAssembler* masm,
                                       Register receiver,
@@ -540,7 +540,7 @@ class StubCompiler BASE_EMBEDDED {
                          Register scratch1,
                          Register scratch2,
                          Register scratch3,
-                         int index,
+                         PropertyIndex index,
                          Handle<String> name,
                          Label* miss);
 
@@ -611,7 +611,7 @@ class LoadStubCompiler: public StubCompiler {
 
   Handle<Code> CompileLoadField(Handle<JSObject> object,
                                 Handle<JSObject> holder,
-                                int index,
+                                PropertyIndex index,
                                 Handle<String> name);
 
   Handle<Code> CompileLoadCallback(Handle<String> name,
@@ -654,7 +654,7 @@ class KeyedLoadStubCompiler: public StubCompiler {
   Handle<Code> CompileLoadField(Handle<String> name,
                                 Handle<JSObject> object,
                                 Handle<JSObject> holder,
-                                int index);
+                                PropertyIndex index);
 
   Handle<Code> CompileLoadCallback(Handle<String> name,
                                    Handle<JSObject> object,
@@ -803,7 +803,7 @@ class CallStubCompiler: public StubCompiler {
 
   Handle<Code> CompileCallField(Handle<JSObject> object,
                                 Handle<JSObject> holder,
-                                int index,
+                                PropertyIndex index,
                                 Handle<String> name);
 
   Handle<Code> CompileCallConstant(Handle<Object> object,
index b120efb..3495e8d 100644 (file)
@@ -350,18 +350,23 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
                                             Register dst,
                                             Register src,
                                             Handle<JSObject> holder,
-                                            int index) {
-  // Adjust for the number of properties stored in the holder.
-  index -= holder->map()->inobject_properties();
-  if (index < 0) {
-    // Get the property straight out of the holder.
-    int offset = holder->map()->instance_size() + (index * kPointerSize);
+                                            PropertyIndex index) {
+  if (index.is_header_index()) {
+    int offset = index.header_index() * kPointerSize;
     __ movq(dst, FieldOperand(src, offset));
   } else {
-    // Calculate the offset into the properties array.
-    int offset = index * kPointerSize + FixedArray::kHeaderSize;
-    __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
-    __ movq(dst, FieldOperand(dst, offset));
+    // Adjust for the number of properties stored in the holder.
+    int slot = index.field_index() - holder->map()->inobject_properties();
+    if (slot < 0) {
+      // Get the property straight out of the holder.
+      int offset = holder->map()->instance_size() + (slot * kPointerSize);
+      __ movq(dst, FieldOperand(src, offset));
+    } else {
+      // Calculate the offset into the properties array.
+      int offset = slot * kPointerSize + FixedArray::kHeaderSize;
+      __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
+      __ movq(dst, FieldOperand(dst, offset));
+    }
   }
 }
 
@@ -1013,7 +1018,7 @@ void StubCompiler::GenerateLoadField(Handle<JSObject> object,
                                      Register scratch1,
                                      Register scratch2,
                                      Register scratch3,
-                                     int index,
+                                     PropertyIndex index,
                                      Handle<String> name,
                                      Label* miss) {
   // Check that the receiver isn't a smi.
@@ -1388,7 +1393,7 @@ void CallStubCompiler::GenerateMissBranch() {
 
 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
-                                                int index,
+                                                PropertyIndex index,
                                                 Handle<String> name) {
   // ----------- S t a t e -------------
   // rcx                 : function name
@@ -2780,7 +2785,7 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name,
 
 Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
-                                                int index,
+                                                PropertyIndex index,
                                                 Handle<String> name) {
   // ----------- S t a t e -------------
   //  -- rax    : receiver
@@ -2973,7 +2978,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
 Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
                                                      Handle<JSObject> receiver,
                                                      Handle<JSObject> holder,
-                                                     int index) {
+                                                     PropertyIndex index) {
   // ----------- S t a t e -------------
   //  -- rax     : key
   //  -- rdx     : receiver