Revert 21720: "Introduce FieldIndex to unify and abstract property/field offset"
authordanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 10 Jun 2014 09:00:10 +0000 (09:00 +0000)
committerdanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 10 Jun 2014 09:00:10 +0000 (09:00 +0000)
Due to assorted failures

R=mstarzinger@chromium.org
TBR=mstarzginer@chromium.org

Review URL: https://codereview.chromium.org/329463005

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

30 files changed:
src/arm/stub-cache-arm.cc
src/arm64/stub-cache-arm64.cc
src/bootstrapper.cc
src/code-stubs-hydrogen.cc
src/code-stubs.h
src/deoptimizer.cc
src/field-index-inl.h [deleted file]
src/field-index.cc [deleted file]
src/field-index.h [deleted file]
src/heap-snapshot-generator.cc
src/ia32/stub-cache-ia32.cc
src/ic.cc
src/ic.h
src/json-parser.h
src/json-stringifier.h
src/objects-debug.cc
src/objects-inl.h
src/objects-printer.cc
src/objects.cc
src/objects.h
src/property.cc
src/property.h
src/runtime.cc
src/string-stream.cc
src/stub-cache.cc
src/stub-cache.h
src/utils.h
src/x64/stub-cache-x64.cc
test/cctest/test-heap.cc
tools/gyp/v8.gyp

index 5f17c9f2d8461e3f6efd0561c7adf1db4a52d77f..c0be0762504f7df846ea001908d25384e4d6584b 100644 (file)
@@ -573,7 +573,12 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   // checks.
   ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 
-  FieldIndex index = lookup->GetFieldIndex();
+  int index = lookup->GetFieldIndex().field_index();
+
+  // Adjust for the number of properties stored in the object. Even in the
+  // face of a transition we can use the old map here because the size of the
+  // object and the number of in-object properties is not going to change.
+  index -= object->map()->inobject_properties();
 
   Representation representation = lookup->representation();
   ASSERT(!representation.IsNone());
@@ -599,12 +604,14 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
     }
   } else if (representation.IsDouble()) {
     // Load the double storage.
-    if (index.is_inobject()) {
-      __ ldr(scratch1, FieldMemOperand(receiver_reg, index.offset()));
+    if (index < 0) {
+      int offset = object->map()->instance_size() + (index * kPointerSize);
+      __ ldr(scratch1, FieldMemOperand(receiver_reg, offset));
     } else {
       __ ldr(scratch1,
              FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
-      __ ldr(scratch1, FieldMemOperand(scratch1, index.offset()));
+      int offset = index * kPointerSize + FixedArray::kHeaderSize;
+      __ ldr(scratch1, FieldMemOperand(scratch1, offset));
     }
 
     // Store the value into the storage.
@@ -631,9 +638,10 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   // TODO(verwaest): Share this code as a code stub.
   SmiCheck smi_check = representation.IsTagged()
       ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
-  if (index.is_inobject()) {
+  if (index < 0) {
     // Set the property straight into the object.
-    __ str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
+    int offset = object->map()->instance_size() + (index * kPointerSize);
+    __ str(value_reg, FieldMemOperand(receiver_reg, offset));
 
     if (!representation.IsSmi()) {
       // Skip updating write barrier if storing a smi.
@@ -643,7 +651,7 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
       // Pass the now unused name_reg as a scratch register.
       __ mov(name_reg, value_reg);
       __ RecordWriteField(receiver_reg,
-                          index.offset(),
+                          offset,
                           name_reg,
                           scratch1,
                           kLRHasNotBeenSaved,
@@ -653,10 +661,11 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
     }
   } else {
     // Write to the properties array.
+    int offset = index * kPointerSize + FixedArray::kHeaderSize;
     // Get the properties array
     __ ldr(scratch1,
            FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
-    __ str(value_reg, FieldMemOperand(scratch1, index.offset()));
+    __ str(value_reg, FieldMemOperand(scratch1, offset));
 
     if (!representation.IsSmi()) {
       // Skip updating write barrier if storing a smi.
@@ -666,7 +675,7 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
       // Ok to clobber receiver_reg and name_reg, since we return.
       __ mov(name_reg, value_reg);
       __ RecordWriteField(scratch1,
-                          index.offset(),
+                          offset,
                           name_reg,
                           receiver_reg,
                           kLRHasNotBeenSaved,
@@ -997,14 +1006,20 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
 
 void LoadStubCompiler::GenerateLoadField(Register reg,
                                          Handle<JSObject> holder,
-                                         FieldIndex field,
+                                         PropertyIndex field,
                                          Representation representation) {
   if (!reg.is(receiver())) __ mov(receiver(), reg);
   if (kind() == Code::LOAD_IC) {
-    LoadFieldStub stub(isolate(), field);
+    LoadFieldStub stub(isolate(),
+                       field.is_inobject(holder),
+                       field.translate(holder),
+                       representation);
     GenerateTailCall(masm(), stub.GetCode());
   } else {
-    KeyedLoadFieldStub stub(isolate(), field);
+    KeyedLoadFieldStub stub(isolate(),
+                            field.is_inobject(holder),
+                            field.translate(holder),
+                            representation);
     GenerateTailCall(masm(), stub.GetCode());
   }
 }
index b933f65f44a8d5deaefea0002032a95c8245268d..ae597b2a0198584d6f2d953499fcad29520daff1 100644 (file)
@@ -522,7 +522,12 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   // checks.
   ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 
-  FieldIndex index = lookup->GetFieldIndex();
+  int index = lookup->GetFieldIndex().field_index();
+
+  // Adjust for the number of properties stored in the object. Even in the
+  // face of a transition we can use the old map here because the size of the
+  // object and the number of in-object properties is not going to change.
+  index -= object->map()->inobject_properties();
 
   Representation representation = lookup->representation();
   ASSERT(!representation.IsNone());
@@ -553,12 +558,14 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
     __ SmiUntagToDouble(temp_double, value_reg, kSpeculativeUntag);
 
     // Load the double storage.
-    if (index.is_inobject()) {
-      __ Ldr(scratch1, FieldMemOperand(receiver_reg, index.offset()));
+    if (index < 0) {
+      int offset = (index * kPointerSize) + object->map()->instance_size();
+      __ Ldr(scratch1, FieldMemOperand(receiver_reg, offset));
     } else {
+      int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
       __ Ldr(scratch1,
              FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
-      __ Ldr(scratch1, FieldMemOperand(scratch1, index.offset()));
+      __ Ldr(scratch1, FieldMemOperand(scratch1, offset));
     }
 
     // Store the value into the storage.
@@ -582,9 +589,10 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   // TODO(verwaest): Share this code as a code stub.
   SmiCheck smi_check = representation.IsTagged()
       ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
-  if (index.is_inobject()) {
+  if (index < 0) {
     // Set the property straight into the object.
-    __ Str(value_reg, FieldMemOperand(receiver_reg, index.offset()));
+    int offset = object->map()->instance_size() + (index * kPointerSize);
+    __ Str(value_reg, FieldMemOperand(receiver_reg, offset));
 
     if (!representation.IsSmi()) {
       // Skip updating write barrier if storing a smi.
@@ -594,7 +602,7 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
       // Pass the now unused name_reg as a scratch register.
       __ Mov(name_reg, value_reg);
       __ RecordWriteField(receiver_reg,
-                          index.offset(),
+                          offset,
                           name_reg,
                           scratch1,
                           kLRHasNotBeenSaved,
@@ -604,10 +612,11 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
     }
   } else {
     // Write to the properties array.
+    int offset = index * kPointerSize + FixedArray::kHeaderSize;
     // Get the properties array
     __ Ldr(scratch1,
            FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
-    __ Str(value_reg, FieldMemOperand(scratch1, index.offset()));
+    __ Str(value_reg, FieldMemOperand(scratch1, offset));
 
     if (!representation.IsSmi()) {
       // Skip updating write barrier if storing a smi.
@@ -617,7 +626,7 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
       // Ok to clobber receiver_reg and name_reg, since we return.
       __ Mov(name_reg, value_reg);
       __ RecordWriteField(scratch1,
-                          index.offset(),
+                          offset,
                           name_reg,
                           receiver_reg,
                           kLRHasNotBeenSaved,
@@ -958,14 +967,20 @@ Register LoadStubCompiler::CallbackHandlerFrontend(Handle<HeapType> type,
 
 void LoadStubCompiler::GenerateLoadField(Register reg,
                                          Handle<JSObject> holder,
-                                         FieldIndex field,
+                                         PropertyIndex field,
                                          Representation representation) {
   __ Mov(receiver(), reg);
   if (kind() == Code::LOAD_IC) {
-    LoadFieldStub stub(isolate(), field);
+    LoadFieldStub stub(isolate(),
+                       field.is_inobject(holder),
+                       field.translate(holder),
+                       representation);
     GenerateTailCall(masm(), stub.GetCode());
   } else {
-    KeyedLoadFieldStub stub(isolate(), field);
+    KeyedLoadFieldStub stub(isolate(),
+                            field.is_inobject(holder),
+                            field.translate(holder),
+                            representation);
     GenerateTailCall(masm(), stub.GetCode());
   }
 }
index cfef267892e7f7a8970927483dba35016cb52755..69aff083a3787d709261601c3415b922cfe293f3 100644 (file)
@@ -1145,13 +1145,11 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
     LookupResult lookup(isolate);
     result->LookupOwn(factory->callee_string(), &lookup);
     ASSERT(lookup.IsField());
-    ASSERT(lookup.GetFieldIndex().property_index() ==
-           Heap::kArgumentsCalleeIndex);
+    ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsCalleeIndex);
 
     result->LookupOwn(factory->length_string(), &lookup);
     ASSERT(lookup.IsField());
-    ASSERT(lookup.GetFieldIndex().property_index() ==
-           Heap::kArgumentsLengthIndex);
+    ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
 
     ASSERT(result->map()->inobject_properties() > Heap::kArgumentsCalleeIndex);
     ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);
@@ -1247,8 +1245,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
     LookupResult lookup(isolate);
     result->LookupOwn(factory->length_string(), &lookup);
     ASSERT(lookup.IsField());
-    ASSERT(lookup.GetFieldIndex().property_index() ==
-           Heap::kArgumentsLengthIndex);
+    ASSERT(lookup.GetFieldIndex().field_index() == Heap::kArgumentsLengthIndex);
 
     ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex);
 
@@ -2420,7 +2417,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
         case FIELD: {
           HandleScope inner(isolate());
           Handle<Name> key = Handle<Name>(descs->GetKey(i));
-          FieldIndex index = FieldIndex::ForDescriptor(from->map(), i);
+          int index = descs->GetFieldIndex(i);
           ASSERT(!descs->GetDetails(i).representation().IsDouble());
           Handle<Object> value = Handle<Object>(from->RawFastPropertyAt(index),
                                                 isolate());
index 88e71faca9ee9dca4db2991d81117fbb8568a147..9e974138926d711ee4f5033364152d836d3d60a1 100644 (file)
@@ -5,7 +5,6 @@
 #include "src/v8.h"
 
 #include "src/code-stubs.h"
-#include "src/field-index.h"
 #include "src/hydrogen.h"
 #include "src/lithium.h"
 
@@ -60,7 +59,9 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
   Isolate* isolate() { return info_.isolate(); }
 
   HLoadNamedField* BuildLoadNamedField(HValue* object,
-                                       FieldIndex index);
+                                       Representation representation,
+                                       int offset,
+                                       bool is_inobject);
 
   enum ArgumentClass {
     NONE,
@@ -552,15 +553,14 @@ Handle<Code> KeyedLoadFastElementStub::GenerateCode() {
 
 
 HLoadNamedField* CodeStubGraphBuilderBase::BuildLoadNamedField(
-    HValue* object, FieldIndex index) {
-  Representation representation = index.is_double()
-      ? Representation::Double()
-      : Representation::Tagged();
-  int offset = index.offset();
-  HObjectAccess access = index.is_inobject()
+    HValue* object,
+    Representation representation,
+    int offset,
+    bool is_inobject) {
+  HObjectAccess access = is_inobject
       ? HObjectAccess::ForObservableJSObjectOffset(offset, representation)
       : HObjectAccess::ForBackingStoreOffset(offset, representation);
-  if (index.is_double()) {
+  if (representation.IsDouble()) {
     // Load the heap number.
     object = Add<HLoadNamedField>(
         object, static_cast<HValue*>(NULL),
@@ -574,7 +574,10 @@ HLoadNamedField* CodeStubGraphBuilderBase::BuildLoadNamedField(
 
 template<>
 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
-  return BuildLoadNamedField(GetParameter(0), casted_stub()->index());
+  return BuildLoadNamedField(GetParameter(0),
+                             casted_stub()->representation(),
+                             casted_stub()->offset(),
+                             casted_stub()->is_inobject());
 }
 
 
@@ -585,10 +588,10 @@ Handle<Code> LoadFieldStub::GenerateCode() {
 
 template<>
 HValue* CodeStubGraphBuilder<StringLengthStub>::BuildCodeStub() {
-  HValue* string = BuildLoadNamedField(GetParameter(0),
-      FieldIndex::ForInObjectOffset(JSValue::kValueOffset));
-  return BuildLoadNamedField(string,
-      FieldIndex::ForInObjectOffset(String::kLengthOffset));
+  HValue* string = BuildLoadNamedField(
+      GetParameter(0), Representation::Tagged(), JSValue::kValueOffset, true);
+  return BuildLoadNamedField(
+      string, Representation::Tagged(), String::kLengthOffset, true);
 }
 
 
index 55d8b885c842326f219eb816289bb42e3f36c965..4a93f9920ad7409b70448c216a789864264a6ada 100644 (file)
@@ -897,9 +897,11 @@ class HandlerStub: public HICStub {
 
 class LoadFieldStub: public HandlerStub {
  public:
-  LoadFieldStub(Isolate* isolate, FieldIndex index)
-    : HandlerStub(isolate), index_(index) {
-    Initialize(Code::LOAD_IC);
+  LoadFieldStub(Isolate* isolate,
+                bool inobject,
+                int index, Representation representation)
+      : HandlerStub(isolate) {
+    Initialize(Code::LOAD_IC, inobject, index, representation);
   }
 
   virtual Handle<Code> GenerateCode() V8_OVERRIDE;
@@ -916,30 +918,42 @@ class LoadFieldStub: public HandlerStub {
     return KindBits::decode(bit_field_);
   }
 
-  FieldIndex index() const { return index_; }
+  bool is_inobject() {
+    return InobjectBits::decode(bit_field_);
+  }
+
+  int offset() {
+    int index = IndexBits::decode(bit_field_);
+    int offset = index * kPointerSize;
+    if (is_inobject()) return offset;
+    return FixedArray::kHeaderSize + offset;
+  }
 
   bool unboxed_double() {
-    return index_.is_double();
+    return UnboxedDoubleBits::decode(bit_field_);
   }
 
   virtual Code::StubType GetStubType() { return Code::FAST; }
 
  protected:
-  explicit LoadFieldStub(Isolate* isolate);
+  explicit LoadFieldStub(Isolate* isolate) : HandlerStub(isolate) { }
 
-  void Initialize(Code::Kind kind) {
-    int property_index_key = index_.GetLoadFieldStubKey();
-    // Save a copy of the essence of the property index into the bit field to
-    // make sure that hashing of unique stubs works correctly..
-    bit_field_ = KindBits::encode(kind) |
-        EncodedLoadFieldByIndexBits::encode(property_index_key);
+  void Initialize(Code::Kind kind,
+                  bool inobject,
+                  int index,
+                  Representation representation) {
+    bit_field_ = KindBits::encode(kind)
+        | InobjectBits::encode(inobject)
+        | IndexBits::encode(index)
+        | UnboxedDoubleBits::encode(representation.IsDouble());
   }
 
  private:
   STATIC_ASSERT(KindBits::kSize == 4);
-  class EncodedLoadFieldByIndexBits: public BitField<int, 4, 13> {};
+  class InobjectBits: public BitField<bool, 4, 1> {};
+  class IndexBits: public BitField<int, 5, 11> {};
+  class UnboxedDoubleBits: public BitField<bool, 16, 1> {};
   virtual CodeStub::Major MajorKey() { return LoadField; }
-  FieldIndex index_;
 };
 
 
@@ -1084,9 +1098,11 @@ class CallApiGetterStub : public PlatformCodeStub {
 
 class KeyedLoadFieldStub: public LoadFieldStub {
  public:
-  KeyedLoadFieldStub(Isolate* isolate, FieldIndex index)
-      : LoadFieldStub(isolate, index) {
-    Initialize(Code::KEYED_LOAD_IC);
+  KeyedLoadFieldStub(Isolate* isolate,
+                     bool inobject,
+                     int index, Representation representation)
+      : LoadFieldStub(isolate) {
+    Initialize(Code::KEYED_LOAD_IC, inobject, index, representation);
   }
 
   virtual void InitializeInterfaceDescriptor(
index 2b39ff6965e89a1290c03d1af0ea33c20c2c963a..c1df93769ee8f8ad6ec6c939cb9931fc4626073f 100644 (file)
@@ -1841,8 +1841,7 @@ Handle<Object> Deoptimizer::MaterializeNextHeapObject() {
         object->set_elements(FixedArrayBase::cast(*elements));
         for (int i = 0; i < length - 3; ++i) {
           Handle<Object> value = MaterializeNextValue();
-          FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
-          object->FastPropertyAtPut(index, *value);
+          object->FastPropertyAtPut(i, *value);
         }
         break;
       }
@@ -3407,8 +3406,7 @@ Handle<Object> SlotRefValueBuilder::GetNext(Isolate* isolate, int lvl) {
           object->set_elements(FixedArrayBase::cast(*elements));
           for (int i = 0; i < length - 3; ++i) {
             Handle<Object> value = GetNext(isolate, lvl + 1);
-            FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
-            object->FastPropertyAtPut(index, *value);
+            object->FastPropertyAtPut(i, *value);
           }
           return object;
         }
diff --git a/src/field-index-inl.h b/src/field-index-inl.h
deleted file mode 100644 (file)
index dd13709..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_FIELD_INDEX_INL_H_
-#define V8_FIELD_INDEX_INL_H_
-
-#include "src/field-index.h"
-
-namespace v8 {
-namespace internal {
-
-
-inline FieldIndex FieldIndex::ForInObjectOffset(int offset, Map* map) {
-  ASSERT((offset % kPointerSize) == 0);
-  int index = offset / kPointerSize;
-  if (map == NULL) {
-    return FieldIndex(true, index, false, index + 1, 0, true);
-  }
-  int first_inobject_offset = map->GetInObjectPropertyOffset(0);
-  if (offset < first_inobject_offset) {
-    return FieldIndex(true, index, false, 0, 0, true);
-  } else {
-    return FieldIndex::ForPropertyIndex(map, offset / kPointerSize);
-  }
-}
-
-
-inline FieldIndex FieldIndex::ForPropertyIndex(Map* map,
-                                               int property_index,
-                                               bool is_double) {
-  ASSERT(map->instance_type() >= FIRST_NONSTRING_TYPE);
-  int inobject_properties = map->inobject_properties();
-  bool is_inobject = property_index < inobject_properties;
-  int first_inobject_offset;
-  if (is_inobject) {
-    first_inobject_offset = map->GetInObjectPropertyOffset(0);
-  } else {
-    first_inobject_offset = FixedArray::kHeaderSize;
-    property_index -= inobject_properties;
-  }
-  return FieldIndex(is_inobject,
-                    property_index + first_inobject_offset / kPointerSize,
-                    is_double, inobject_properties, first_inobject_offset);
-}
-
-
-inline FieldIndex FieldIndex::ForLoadByFieldIndex(Map* map, int orig_index) {
-  int field_index = orig_index;
-  int is_inobject = true;
-  bool is_double = field_index & 1;
-  int first_inobject_offset = 0;
-  field_index >>= 1;
-  if (field_index < 0) {
-    field_index = -(field_index + 1);
-    is_inobject = false;
-    first_inobject_offset = FixedArray::kHeaderSize;
-    field_index += FixedArray::kHeaderSize / kPointerSize;
-  } else {
-    first_inobject_offset = map->GetInObjectPropertyOffset(0);
-    field_index += JSObject::kHeaderSize / kPointerSize;
-  }
-  return FieldIndex(is_inobject, field_index, is_double,
-                    map->inobject_properties(), first_inobject_offset);
-}
-
-
-inline FieldIndex FieldIndex::ForDescriptor(Map* map, int descriptor_index) {
-  PropertyDetails details =
-      map->instance_descriptors()->GetDetails(descriptor_index);
-  int field_index =
-      map->instance_descriptors()->GetFieldIndex(descriptor_index);
-  return ForPropertyIndex(map, field_index,
-                          details.representation().IsDouble());
-}
-
-
-} }  // namespace v8::internal
-
-#endif
diff --git a/src/field-index.cc b/src/field-index.cc
deleted file mode 100644 (file)
index 5392afc..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "src/field-index.h"
-#include "src/objects.h"
-#include "src/objects-inl.h"
-
-namespace v8 {
-namespace internal {
-
-
-FieldIndex FieldIndex::ForLookupResult(const LookupResult* lookup_result) {
-  Map* map = lookup_result->holder()->map();
-  return ForPropertyIndex(map,
-                          lookup_result->GetFieldIndexFromMap(map),
-                          lookup_result->representation().IsDouble());
-}
-
-
-} }  // namespace v8::internal
diff --git a/src/field-index.h b/src/field-index.h
deleted file mode 100644 (file)
index d770764..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_FIELD_INDEX_H_
-#define V8_FIELD_INDEX_H_
-
-#include "src/utils.h"
-#include "src/property-details.h"
-
-namespace v8 {
-namespace internal {
-
-class Map;
-
-// Wrapper class to hold a field index, usually but not necessarily generated
-// from a property index. When available, the wrapper class captures additional
-// information to allow the field index to be translated back into the property
-// index it was originally generated from.
-class FieldIndex V8_FINAL {
- public:
-  static FieldIndex ForPropertyIndex(Map* map,
-                                     int index,
-                                     bool is_double = false);
-  static FieldIndex ForInObjectOffset(int offset, Map* map = NULL);
-  static FieldIndex ForLookupResult(const LookupResult* result);
-  static FieldIndex ForDescriptor(Map* map, int descriptor_index);
-  static FieldIndex ForLoadByFieldIndex(Map* map, int index);
-  static FieldIndex ForKeyedLookupCacheIndex(Map* map, int index) {
-    return ForPropertyIndex(map, index);
-  }
-
-  bool is_inobject() const {
-    return IsInObjectBits::decode(bit_field_);
-  }
-
-  bool is_double() const {
-    return IsDoubleBits::decode(bit_field_);
-  }
-
-  int offset() const {
-    return index() * kPointerSize;
-  }
-
-  int index() const {
-    return IndexBits::decode(bit_field_);
-  }
-
-  int outobject_array_index() const {
-    ASSERT(!is_inobject());
-    return index() - first_inobject_property_offset() / kPointerSize;
-  }
-
-  int property_index() const {
-    ASSERT(!IsHiddenField::decode(bit_field_));
-    int result = index() - first_inobject_property_offset() / kPointerSize;
-    if (!is_inobject()) {
-      result += InObjectPropertyBits::decode(bit_field_);
-    }
-    return result;
-  }
-
-  int GetLoadByFieldIndex() const {
-    // For efficiency, the LoadByFieldIndex instruction takes an index that is
-    // optimized for quick access. If the property is inline, the index is
-    // positive. If it's out-of-line, the encoded index is -raw_index - 1 to
-    // disambiguate the zero out-of-line index from the zero inobject case.
-    // The index itself is shifted up by one bit, the lower-most bit
-    // signifying if the field is a mutable double box (1) or not (0).
-    int result = index() - first_inobject_property_offset() / kPointerSize;
-    if (!is_inobject()) {
-      result = -result - 1;
-    }
-    result <<= 1;
-    return is_double() ? (result | 1) : result;
-  }
-
-  int GetKeyedLookupCacheIndex() const {
-    return property_index();
-  }
-
-  int GetLoadFieldStubKey() const {
-    return bit_field_ &
-        (IsInObjectBits::kMask | IsDoubleBits::kMask | IndexBits::kMask);
-  }
-
- private:
-  FieldIndex(bool is_inobject, int local_index, bool is_double,
-             int inobject_properties, int first_inobject_property_offset,
-             bool is_hidden = false) {
-    ASSERT((first_inobject_property_offset & (kPointerSize - 1)) == 0);
-    bit_field_ = IsInObjectBits::encode(is_inobject) |
-      IsDoubleBits::encode(is_double) |
-      FirstInobjectPropertyOffsetBits::encode(first_inobject_property_offset) |
-      IsHiddenField::encode(is_hidden) |
-      IndexBits::encode(local_index) |
-      InObjectPropertyBits::encode(inobject_properties);
-  }
-
-  int first_inobject_property_offset() const {
-    ASSERT(!IsHiddenField::decode(bit_field_));
-    return FirstInobjectPropertyOffsetBits::decode(bit_field_);
-  }
-
-  static const int kIndexBitsSize = kDescriptorIndexBitCount + 1;
-
-  class IndexBits: public BitField<int, 0, kIndexBitsSize> {};
-  class IsInObjectBits: public BitField<bool, IndexBits::kNext, 1> {};
-  class IsDoubleBits: public BitField<bool, IsInObjectBits::kNext, 1> {};
-  class InObjectPropertyBits: public BitField<int, IsDoubleBits::kNext,
-                                              kDescriptorIndexBitCount> {};
-  class FirstInobjectPropertyOffsetBits:
-      public BitField<int, InObjectPropertyBits::kNext, 7> {};
-  class IsHiddenField:
-      public BitField<bool, FirstInobjectPropertyOffsetBits::kNext, 1> {};
-  STATIC_ASSERT(IsHiddenField::kNext <= 32);
-
-  int bit_field_;
-};
-
-} }  // namespace v8::internal
-
-#endif
index fbc798d92192de01e924775d59a7d37eaba50611..ae07f6a6ee27ea2307b788afaca2099aa158bfd4 100644 (file)
@@ -1660,9 +1660,7 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
                   js_obj->GetInObjectPropertyOffset(index));
             }
           } else {
-            FieldIndex field_index =
-                FieldIndex::ForDescriptor(js_obj->map(), i);
-            Object* value = js_obj->RawFastPropertyAt(field_index);
+            Object* value = js_obj->RawFastPropertyAt(index);
             if (k != heap_->hidden_string()) {
               SetPropertyReference(js_obj, entry, k, value);
             } else {
index 9eb113cede43253aa7738657f86e8b74e67eb9c6..75533d1259e143cfd47c32f4e4027209d69e6183 100644 (file)
@@ -661,7 +661,12 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   // checks.
   ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 
-  FieldIndex index = lookup->GetFieldIndex();
+  int index = lookup->GetFieldIndex().field_index();
+
+  // Adjust for the number of properties stored in the object. Even in the
+  // face of a transition we can use the old map here because the size of the
+  // object and the number of in-object properties is not going to change.
+  index -= object->map()->inobject_properties();
 
   Representation representation = lookup->representation();
   ASSERT(!representation.IsNone());
@@ -686,11 +691,13 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
     }
   } else if (representation.IsDouble()) {
     // Load the double storage.
-    if (index.is_inobject()) {
-      __ mov(scratch1, FieldOperand(receiver_reg, index.offset()));
+    if (index < 0) {
+      int offset = object->map()->instance_size() + (index * kPointerSize);
+      __ mov(scratch1, FieldOperand(receiver_reg, offset));
     } else {
       __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
-      __ mov(scratch1, FieldOperand(scratch1, index.offset()));
+      int offset = index * kPointerSize + FixedArray::kHeaderSize;
+      __ mov(scratch1, FieldOperand(scratch1, offset));
     }
 
     // Store the value into the storage.
@@ -716,16 +723,17 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   // TODO(verwaest): Share this code as a code stub.
   SmiCheck smi_check = representation.IsTagged()
       ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
-  if (index.is_inobject()) {
+  if (index < 0) {
     // Set the property straight into the object.
-    __ mov(FieldOperand(receiver_reg, index.offset()), value_reg);
+    int offset = object->map()->instance_size() + (index * kPointerSize);
+    __ mov(FieldOperand(receiver_reg, offset), value_reg);
 
     if (!representation.IsSmi()) {
       // Update the write barrier for the array address.
       // Pass the value being stored in the now unused name_reg.
       __ mov(name_reg, value_reg);
       __ RecordWriteField(receiver_reg,
-                          index.offset(),
+                          offset,
                           name_reg,
                           scratch1,
                           kDontSaveFPRegs,
@@ -734,16 +742,17 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
     }
   } else {
     // Write to the properties array.
+    int offset = index * kPointerSize + FixedArray::kHeaderSize;
     // Get the properties array (optimistically).
     __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
-    __ mov(FieldOperand(scratch1, index.offset()), value_reg);
+    __ mov(FieldOperand(scratch1, offset), value_reg);
 
     if (!representation.IsSmi()) {
       // Update the write barrier for the array address.
       // Pass the value being stored in the now unused name_reg.
       __ mov(name_reg, value_reg);
       __ RecordWriteField(scratch1,
-                          index.offset(),
+                          offset,
                           name_reg,
                           receiver_reg,
                           kDontSaveFPRegs,
@@ -963,14 +972,20 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
 
 void LoadStubCompiler::GenerateLoadField(Register reg,
                                          Handle<JSObject> holder,
-                                         FieldIndex field,
+                                         PropertyIndex field,
                                          Representation representation) {
   if (!reg.is(receiver())) __ mov(receiver(), reg);
   if (kind() == Code::LOAD_IC) {
-    LoadFieldStub stub(isolate(), field);
+    LoadFieldStub stub(isolate(),
+                       field.is_inobject(holder),
+                       field.translate(holder),
+                       representation);
     GenerateTailCall(masm(), stub.GetCode());
   } else {
-    KeyedLoadFieldStub stub(isolate(), field);
+    KeyedLoadFieldStub stub(isolate(),
+                            field.is_inobject(holder),
+                            field.translate(holder),
+                            representation);
     GenerateTailCall(masm(), stub.GetCode());
   }
 }
index 1a6ab41e4fdf076da121eb1dca88950540b2246b..0040b1d352f2ac1a43c92a1f1f55c67dd283a50d 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -838,12 +838,14 @@ Handle<Code> LoadIC::megamorphic_stub() {
 }
 
 
-Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
+Handle<Code> LoadIC::SimpleFieldLoad(int offset,
+                                     bool inobject,
+                                     Representation representation) {
   if (kind() == Code::LOAD_IC) {
-    LoadFieldStub stub(isolate(), index);
+    LoadFieldStub stub(isolate(), inobject, offset, representation);
     return stub.GetCode();
   } else {
-    KeyedLoadFieldStub stub(isolate(), index);
+    KeyedLoadFieldStub stub(isolate(), inobject, offset, representation);
     return stub.GetCode();
   }
 }
@@ -922,8 +924,8 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
                                     InlineCacheHolderFlag cache_holder) {
   if (object->IsString() &&
       String::Equals(isolate()->factory()->length_string(), name)) {
-    FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
-    return SimpleFieldLoad(index);
+    int length_index = String::kLengthOffset / kPointerSize;
+    return SimpleFieldLoad(length_index);
   }
 
   if (object->IsStringWrapper() &&
@@ -943,9 +945,11 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
 
   switch (lookup->type()) {
     case FIELD: {
-      FieldIndex field = lookup->GetFieldIndex();
+      PropertyIndex field = lookup->GetFieldIndex();
       if (object.is_identical_to(holder)) {
-        return SimpleFieldLoad(field);
+        return SimpleFieldLoad(field.translate(holder),
+                               field.is_inobject(holder),
+                               lookup->representation());
       }
       return compiler.CompileLoadField(
           type, holder, name, field, lookup->representation());
@@ -981,15 +985,12 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
       // Use simple field loads for some well-known callback properties.
       if (object->IsJSObject()) {
         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
-        Handle<Map> map(receiver->map());
         Handle<HeapType> type = IC::MapToType<HeapType>(
             handle(receiver->map()), isolate());
         int object_offset;
         if (Accessors::IsJSObjectFieldAccessor<HeapType>(
                 type, name, &object_offset)) {
-          FieldIndex index = FieldIndex::ForInObjectOffset(
-              object_offset, receiver->map());
-          return SimpleFieldLoad(index);
+          return SimpleFieldLoad(object_offset / kPointerSize);
         }
       }
 
index f3e2418ee61d2a0ce5286900be19c3dc88b61640..5b4100abaf21cfa2cc14926d5c30dca18527c005 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -481,7 +481,10 @@ class LoadIC: public IC {
     return pre_monomorphic_stub(isolate(), extra_ic_state());
   }
 
-  Handle<Code> SimpleFieldLoad(FieldIndex index);
+  Handle<Code> SimpleFieldLoad(int offset,
+                               bool inobject = true,
+                               Representation representation =
+                                    Representation::Tagged());
 
   static void Clear(Isolate* isolate,
                     Address address,
index 60855a0a801f5c38d683ae442520ed046d79f83f..7f3809d2580c672075d4f98a66b7af4a0eb4387d 100644 (file)
@@ -414,8 +414,7 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
         int length = properties.length();
         for (int i = 0; i < length; i++) {
           Handle<Object> value = properties[i];
-          FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
-          json_object->FastPropertyAtPut(index, *value);
+          json_object->FastPropertyAtPut(i, *value);
         }
       } else {
         key = ParseJsonInternalizedString();
@@ -439,8 +438,7 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
       int length = properties.length();
       for (int i = 0; i < length; i++) {
         Handle<Object> value = properties[i];
-        FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
-        json_object->FastPropertyAtPut(index, *value);
+        json_object->FastPropertyAtPut(i, *value);
       }
     }
   }
index 23927b162edc09514d3cadb77efa3a604ed5fb32..f6149ae36d850fc7f85a5d90c0b07b5dd14e2c77 100644 (file)
@@ -657,8 +657,10 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
       if (details.IsDontEnum()) continue;
       Handle<Object> property;
       if (details.type() == FIELD && *map == object->map()) {
-        property = Handle<Object>(object->RawFastPropertyAt(
-            FieldIndex::ForDescriptor(*map, i)), isolate_);
+        property = Handle<Object>(
+                       object->RawFastPropertyAt(
+                           map->instance_descriptors()->GetFieldIndex(i)),
+                       isolate_);
       } else {
         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
             isolate_, property,
index 877a9d51da7b1057e576ee8f1af398183d9fffd7..762354e184586b41377857b7a16ce2e2efa4555d 100644 (file)
@@ -261,8 +261,8 @@ void JSObject::JSObjectVerify() {
     for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
       if (descriptors->GetDetails(i).type() == FIELD) {
         Representation r = descriptors->GetDetails(i).representation();
-        FieldIndex index = FieldIndex::ForDescriptor(map(), i);
-        Object* value = RawFastPropertyAt(index);
+        int field = descriptors->GetFieldIndex(i);
+        Object* value = RawFastPropertyAt(field);
         if (r.IsDouble()) ASSERT(value->IsHeapNumber());
         if (value->IsUninitialized()) continue;
         if (r.IsSmi()) ASSERT(value->IsSmi());
index cd61ab52b92a657d66eaef1d2b759e3123584d0d..5f58306ec22d41b4dd98ba8303c00b06b6c5a656 100644 (file)
@@ -17,7 +17,6 @@
 #include "src/objects.h"
 #include "src/contexts.h"
 #include "src/conversions-inl.h"
-#include "src/field-index-inl.h"
 #include "src/heap.h"
 #include "src/isolate.h"
 #include "src/heap-inl.h"
@@ -1946,22 +1945,29 @@ void JSObject::SetInternalField(int index, Smi* value) {
 // Access fast-case object properties at index. The use of these routines
 // is needed to correctly distinguish between properties stored in-object and
 // properties stored in the properties array.
-Object* JSObject::RawFastPropertyAt(FieldIndex index) {
-  if (index.is_inobject()) {
-    return READ_FIELD(this, index.offset());
+Object* JSObject::RawFastPropertyAt(int index) {
+  // Adjust for the number of properties stored in the object.
+  index -= map()->inobject_properties();
+  if (index < 0) {
+    int offset = map()->instance_size() + (index * kPointerSize);
+    return READ_FIELD(this, offset);
   } else {
-    return properties()->get(index.outobject_array_index());
+    ASSERT(index < properties()->length());
+    return properties()->get(index);
   }
 }
 
 
-void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) {
-  if (index.is_inobject()) {
-    int offset = index.offset();
+void JSObject::FastPropertyAtPut(int index, Object* value) {
+  // Adjust for the number of properties stored in the object.
+  index -= map()->inobject_properties();
+  if (index < 0) {
+    int offset = map()->instance_size() + (index * kPointerSize);
     WRITE_FIELD(this, offset, value);
     WRITE_BARRIER(GetHeap(), this, offset, value);
   } else {
-    properties()->set(index.outobject_array_index(), value);
+    ASSERT(index < properties()->length());
+    properties()->set(index, value);
   }
 }
 
@@ -4070,7 +4076,7 @@ int Map::pre_allocated_property_fields() {
 int Map::GetInObjectPropertyOffset(int index) {
   // Adjust for the number of properties stored in the object.
   index -= inobject_properties();
-  ASSERT(index <= 0);
+  ASSERT(index < 0);
   return instance_size() + (index * kPointerSize);
 }
 
index 54a7b5532bb31e4129597de1aa916e4dca5a672f..c51c04e3fe223e01367dcb8843405338039e9623 100644 (file)
@@ -232,9 +232,9 @@ void JSObject::PrintProperties(FILE* out) {
       PrintF(out, ": ");
       switch (descs->GetType(i)) {
         case FIELD: {
-          FieldIndex index = FieldIndex::ForDescriptor(map(), i);
+          int index = descs->GetFieldIndex(i);
           RawFastPropertyAt(index)->ShortPrint(out);
-          PrintF(out, " (field at offset %d)\n", index.property_index());
+          PrintF(out, " (field at offset %d)\n", index);
           break;
         }
         case CONSTANT:
index 351fba81455d011fe3fe7df20b8672ba8395ec25..3f9a9ca1f7a4b164d905f17a3f2c5cba8c644ef4 100644 (file)
@@ -17,8 +17,6 @@
 #include "src/date.h"
 #include "src/elements.h"
 #include "src/execution.h"
-#include "src/field-index.h"
-#include "src/field-index-inl.h"
 #include "src/full-codegen.h"
 #include "src/hydrogen.h"
 #include "src/isolate-inl.h"
@@ -849,7 +847,8 @@ MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
     }
     case FIELD:
       value = JSObject::FastPropertyAt(handle(result->holder(), isolate),
-          result->representation(), FieldIndex::ForLookupResult(result));
+                                       result->representation(),
+                                       result->GetFieldIndex().field_index());
       break;
     case CONSTANT:
       return handle(result->GetConstant(), isolate);
@@ -2281,7 +2280,7 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
            old_details.type() == FIELD);
     Object* raw_value = old_details.type() == CONSTANT
         ? old_descriptors->GetValue(i)
-        : object->RawFastPropertyAt(FieldIndex::ForDescriptor(*old_map, i));
+        : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
     Handle<Object> value(raw_value, isolate);
     if (!old_details.representation().IsDouble() &&
         details.representation().IsDouble()) {
@@ -2317,8 +2316,7 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
   // avoid overwriting |one_pointer_filler_map|.
   int limit = Min(inobject, number_of_fields);
   for (int i = 0; i < limit; i++) {
-    FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
-    object->FastPropertyAtPut(index, array->get(external + i));
+    object->FastPropertyAtPut(i, array->get(external + i));
   }
 
   // Create filler object past the new instance size.
@@ -3517,7 +3515,7 @@ void JSObject::LookupOwnRealNamedProperty(Handle<Name> name,
     // occur as fields.
     if (result->IsField() &&
         result->IsReadOnly() &&
-        RawFastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
+        RawFastPropertyAt(result->GetFieldIndex().field_index())->IsTheHole()) {
       result->DisallowCaching();
     }
     return;
@@ -4033,14 +4031,14 @@ void JSObject::WriteToField(int descriptor, Object* value) {
 
   ASSERT(details.type() == FIELD);
 
-  FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor);
+  int field_index = desc->GetFieldIndex(descriptor);
   if (details.representation().IsDouble()) {
     // Nothing more to be done.
     if (value->IsUninitialized()) return;
-    HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
+    HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(field_index));
     box->set_value(value->Number());
   } else {
-    FastPropertyAtPut(index, value);
+    FastPropertyAtPut(field_index, value);
   }
 }
 
@@ -4729,9 +4727,8 @@ void JSObject::NormalizeProperties(Handle<JSObject> object,
       }
       case FIELD: {
         Handle<Name> key(descs->GetKey(i));
-        FieldIndex index = FieldIndex::ForDescriptor(*map, i);
         Handle<Object> value(
-            object->RawFastPropertyAt(index), isolate);
+            object->RawFastPropertyAt(descs->GetFieldIndex(i)), isolate);
         PropertyDetails d =
             PropertyDetails(details.attributes(), NORMAL, i + 1);
         dictionary = NameDictionary::Add(dictionary, key, value, d);
@@ -5238,9 +5235,8 @@ Object* JSObject::GetHiddenPropertiesHashTable() {
         ASSERT(descriptors->GetType(sorted_index) == FIELD);
         ASSERT(descriptors->GetDetails(sorted_index).representation().
                IsCompatibleForLoad(Representation::Tagged()));
-        FieldIndex index = FieldIndex::ForDescriptor(this->map(),
-                                                     sorted_index);
-        return this->RawFastPropertyAt(index);
+        return this->RawFastPropertyAt(
+            descriptors->GetFieldIndex(sorted_index));
       } else {
         return GetHeap()->undefined_value();
       }
@@ -5920,7 +5916,7 @@ void JSObject::SetObserved(Handle<JSObject> object) {
 
 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
                                         Representation representation,
-                                        FieldIndex index) {
+                                        int index) {
   Isolate* isolate = object->GetIsolate();
   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
   return Object::NewStorageFor(isolate, raw_value, representation);
@@ -6011,7 +6007,7 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
       for (int i = 0; i < limit; i++) {
         PropertyDetails details = descriptors->GetDetails(i);
         if (details.type() != FIELD) continue;
-        FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
+        int index = descriptors->GetFieldIndex(i);
         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
         if (value->IsJSObject()) {
           ASSIGN_RETURN_ON_EXCEPTION(
@@ -6178,7 +6174,7 @@ Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
       case FIELD:
         result = FastPropertyAt(Handle<JSObject>(lookup.holder(), isolate),
                                 lookup.representation(),
-                                lookup.GetFieldIndex());
+                                lookup.GetFieldIndex().field_index());
         break;
       case CONSTANT:
         result = Handle<Object>(lookup.GetConstant(), isolate);
@@ -6412,9 +6408,15 @@ static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
           if (details.type() != FIELD) {
             indices = Handle<FixedArray>();
           } else {
-            FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
-            int load_by_field_index = field_index.GetLoadByFieldIndex();
-            indices->set(index, Smi::FromInt(load_by_field_index));
+            int field_index = descs->GetFieldIndex(i);
+            if (field_index >= map->inobject_properties()) {
+              field_index = -(field_index - map->inobject_properties() + 1);
+            }
+            field_index = field_index << 1;
+            if (details.representation().IsDouble()) {
+              field_index |= 1;
+            }
+            indices->set(index, Smi::FromInt(field_index));
           }
         }
         index++;
@@ -7118,8 +7120,7 @@ Object* JSObject::SlowReverseLookup(Object* value) {
     DescriptorArray* descs = map()->instance_descriptors();
     for (int i = 0; i < number_of_own_descriptors; i++) {
       if (descs->GetType(i) == FIELD) {
-        Object* property =
-            RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i));
+        Object* property = RawFastPropertyAt(descs->GetFieldIndex(i));
         if (descs->GetDetails(i).representation().IsDouble()) {
           ASSERT(property->IsHeapNumber());
           if (value->IsNumber() && property->Number() == value->Number()) {
index 8c67765774e5be0f99a0cc112422a1a70b04aa97..0ba12ba2ce49e95910328071c266615300b34ecc 100644 (file)
@@ -9,7 +9,6 @@
 #include "src/assert-scope.h"
 #include "src/builtins.h"
 #include "src/elements-kind.h"
-#include "src/field-index.h"
 #include "src/flags.h"
 #include "src/list.h"
 #include "src/property-details.h"
@@ -2500,9 +2499,9 @@ class JSObject: public JSReceiver {
   // Access fast-case object properties at index.
   static Handle<Object> FastPropertyAt(Handle<JSObject> object,
                                        Representation representation,
-                                       FieldIndex index);
-  inline Object* RawFastPropertyAt(FieldIndex index);
-  inline void FastPropertyAtPut(FieldIndex index, Object* value);
+                                       int index);
+  inline Object* RawFastPropertyAt(int index);
+  inline void FastPropertyAtPut(int index, Object* value);
   void WriteToField(int descriptor, Object* value);
 
   // Access to in object properties.
index 24b39a959215e0eac9dc7760f3c7b482a5ac3918..fa5046de5b1a3c67411a8576b11537a1b4f53653 100644 (file)
@@ -47,8 +47,7 @@ void LookupResult::Print(FILE* out) {
       break;
     case FIELD:
       PrintF(out, " -type = field\n");
-      PrintF(out, " -index = %d\n",
-             GetFieldIndex().property_index());
+      PrintF(out, " -index = %d\n", GetFieldIndex().field_index());
       PrintF(out, " -field type:\n");
       GetFieldType()->TypePrint(out);
       break;
index ebb43430a04b6920f8aec27ae35f9f64f4cb470a..093285c94e77c7c5df7b2eeed336abd038652ede 100644 (file)
@@ -7,8 +7,6 @@
 
 #include "src/isolate.h"
 #include "src/factory.h"
-#include "src/field-index.h"
-#include "src/field-index-inl.h"
 #include "src/types.h"
 
 namespace v8 {
@@ -110,6 +108,56 @@ class CallbacksDescriptor V8_FINAL : public Descriptor {
 };
 
 
+// Holds a property index value distinguishing if it is a field index or an
+// index inside the object header.
+class PropertyIndex V8_FINAL {
+ 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();
+  }
+
+  bool is_inobject(Handle<JSObject> holder) {
+    if (is_header_index()) return true;
+    return field_index() < holder->map()->inobject_properties();
+  }
+
+  int translate(Handle<JSObject> holder) {
+    if (is_header_index()) return header_index();
+    int index = field_index() - holder->map()->inobject_properties();
+    if (index >= 0) return index;
+    return index + holder->map()->instance_size() / kPointerSize;
+  }
+
+ 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 V8_FINAL BASE_EMBEDDED {
  public:
   explicit LookupResult(Isolate* isolate)
@@ -326,7 +374,7 @@ class LookupResult V8_FINAL BASE_EMBEDDED {
       case DICTIONARY_TYPE:
         switch (type()) {
           case FIELD:
-            return holder()->RawFastPropertyAt(GetFieldIndex());
+            return holder()->RawFastPropertyAt(GetFieldIndex().field_index());
           case NORMAL: {
             Object* value = holder()->property_dictionary()->ValueAt(
                 GetDictionaryEntry());
@@ -368,10 +416,10 @@ class LookupResult V8_FINAL BASE_EMBEDDED {
     return number_;
   }
 
-  FieldIndex GetFieldIndex() const {
+  PropertyIndex GetFieldIndex() const {
     ASSERT(lookup_type_ == DESCRIPTOR_TYPE ||
            lookup_type_ == TRANSITION_TYPE);
-    return FieldIndex::ForLookupResult(this);
+    return PropertyIndex::NewFieldIndex(GetFieldIndexFromMap(holder()->map()));
   }
 
   int GetLocalFieldIndexFromMap(Map* map) const {
index a824d6a7977c34fbd0f6508c3dd4779193a56fa5..e5966efd8fec8c087442df54573470e218af212e 100644 (file)
@@ -2555,7 +2555,7 @@ RUNTIME_FUNCTION(RuntimeHidden_InitializeConstGlobal) {
   // Strict mode handling not needed (const is disallowed in strict mode).
   if (lookup.IsField()) {
     FixedArray* properties = global->properties();
-    int index = lookup.GetFieldIndex().outobject_array_index();
+    int index = lookup.GetFieldIndex().field_index();
     if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
       properties->set(index, *value);
     }
@@ -2644,10 +2644,9 @@ RUNTIME_FUNCTION(RuntimeHidden_InitializeConstContextSlot) {
 
     if (lookup.IsField()) {
       FixedArray* properties = object->properties();
-      FieldIndex index = lookup.GetFieldIndex();
-      ASSERT(!index.is_inobject());
-      if (properties->get(index.outobject_array_index())->IsTheHole()) {
-        properties->set(index.outobject_array_index(), *value);
+      int index = lookup.GetFieldIndex().field_index();
+      if (properties->get(index)->IsTheHole()) {
+        properties->set(index, *value);
       }
     } else if (lookup.IsNormal()) {
       if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
@@ -5054,11 +5053,10 @@ RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
         // Attempt to use lookup cache.
         Handle<Map> receiver_map(receiver->map(), isolate);
         KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
-        int index = keyed_lookup_cache->Lookup(receiver_map, key);
-        if (index != -1) {
+        int offset = keyed_lookup_cache->Lookup(receiver_map, key);
+        if (offset != -1) {
           // Doubles are not cached, so raw read the value.
-          Object* value = receiver->RawFastPropertyAt(
-              FieldIndex::ForKeyedLookupCacheIndex(*receiver_map, index));
+          Object* value = receiver->RawFastPropertyAt(offset);
           return value->IsTheHole()
               ? isolate->heap()->undefined_value()
               : value;
@@ -5068,16 +5066,15 @@ RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
         LookupResult result(isolate);
         receiver->LookupOwn(key, &result);
         if (result.IsField()) {
-          FieldIndex field_index = result.GetFieldIndex();
+          int offset = result.GetFieldIndex().field_index();
           // Do not track double fields in the keyed lookup cache. Reading
           // double values requires boxing.
           if (!result.representation().IsDouble()) {
-            keyed_lookup_cache->Update(receiver_map, key,
-                field_index.GetKeyedLookupCacheIndex());
+            keyed_lookup_cache->Update(receiver_map, key, offset);
           }
           AllowHeapAllocation allow_allocation;
-          return *JSObject::FastPropertyAt(receiver, result.representation(),
-                                           field_index);
+          return *JSObject::FastPropertyAt(
+              receiver, result.representation(), offset);
         }
       } else {
         // Attempt dictionary lookup.
@@ -10779,7 +10776,7 @@ static Handle<Object> DebugLookupResultValue(Isolate* isolate,
     case FIELD:
       value = JSObject::FastPropertyAt(handle(result->holder(), isolate),
                                        result->representation(),
-                                       result->GetFieldIndex());
+                                       result->GetFieldIndex().field_index());
       break;
     case CONSTANT:
       return handle(result->GetConstant(), isolate);
@@ -14548,17 +14545,14 @@ RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
   ASSERT(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
-  RUNTIME_ASSERT((index->value() & 1) == 1);
-  FieldIndex field_index =
-      FieldIndex::ForLoadByFieldIndex(object->map(), index->value() >> 1);
-  if (field_index.is_inobject()) {
-    RUNTIME_ASSERT(field_index.property_index() <
-                   object->map()->inobject_properties());
-  } else {
-    RUNTIME_ASSERT(field_index.outobject_array_index() <
-                   object->properties()->length());
-  }
-  Handle<Object> raw_value(object->RawFastPropertyAt(field_index), isolate);
+  int idx = index->value() >> 1;
+  int inobject_properties = object->map()->inobject_properties();
+  if (idx < 0) {
+    idx = -idx + inobject_properties - 1;
+  }
+  int max_idx = object->properties()->length() + inobject_properties;
+  RUNTIME_ASSERT(idx < max_idx);
+  Handle<Object> raw_value(object->RawFastPropertyAt(idx), isolate);
   RUNTIME_ASSERT(raw_value->IsNumber() || raw_value->IsUninitialized());
   return *Object::NewStorageFor(isolate, raw_value, Representation::Double());
 }
index fb73719492597880bf57091a04918156a6e350ea..480b788adcb9cd65d5c5fec1b32a8cc8452ce9e9 100644 (file)
@@ -348,8 +348,7 @@ void StringStream::PrintUsingMap(JSObject* js_object) {
           key->ShortPrint();
         }
         Add(": ");
-        FieldIndex index = FieldIndex::ForDescriptor(map, i);
-        Object* value = js_object->RawFastPropertyAt(index);
+        Object* value = js_object->RawFastPropertyAt(descs->GetFieldIndex(i));
         Add("%o\n", value);
       }
     }
index ef9270fb49f0709e3921ad62d046cfa5ffc6c229..b42f7489f4f1f7b88527101b6ee7dba31c5f3355 100644 (file)
@@ -888,7 +888,7 @@ Handle<Code> LoadStubCompiler::CompileLoadField(
     Handle<HeapType> type,
     Handle<JSObject> holder,
     Handle<Name> name,
-    FieldIndex field,
+    PropertyIndex field,
     Representation representation) {
   Register reg = HandlerFrontend(type, receiver(), holder, name);
   GenerateLoadField(reg, holder, field, representation);
@@ -966,7 +966,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor(
     LookupResult* lookup) {
   Handle<JSObject> holder(lookup->holder());
   if (lookup->IsField()) {
-    FieldIndex field = lookup->GetFieldIndex();
+    PropertyIndex field = lookup->GetFieldIndex();
     if (interceptor_holder.is_identical_to(holder)) {
       GenerateLoadField(
           interceptor_reg, holder, field, lookup->representation());
index 7ab7bed115742e82c739509dbc163059288e4004..e2de10144750cf1f2a05db8a1d6adf6b746b01ce 100644 (file)
@@ -518,7 +518,7 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler {
   Handle<Code> CompileLoadField(Handle<HeapType> type,
                                 Handle<JSObject> holder,
                                 Handle<Name> name,
-                                FieldIndex index,
+                                PropertyIndex index,
                                 Representation representation);
 
   Handle<Code> CompileLoadCallback(Handle<HeapType> type,
@@ -589,7 +589,7 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler {
 
   void GenerateLoadField(Register reg,
                          Handle<JSObject> holder,
-                         FieldIndex field,
+                         PropertyIndex field,
                          Representation representation);
   void GenerateLoadConstant(Handle<Object> value);
   void GenerateLoadCallback(Register reg,
index 8f07ab3f2b520c325be4397d4ff9e6cae66ce0a6..d30db9bdb659491b3618b074bbcca0eb8da0aab8 100644 (file)
@@ -248,7 +248,6 @@ class BitFieldBase {
   static const U kMask = ((kOne << shift) << size) - (kOne << shift);
   static const U kShift = shift;
   static const U kSize = size;
-  static const U kNext = kShift + kSize;
 
   // Value for the field with all bits set.
   static const T kMax = static_cast<T>((1U << size) - 1);
index b0aa310b7419d90d5aaaa5fba1c7182b9c7c97c2..c8be271cf969f2818214eabf041f0263bd99b6b2 100644 (file)
@@ -618,7 +618,12 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   // checks.
   ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
 
-  FieldIndex index = lookup->GetFieldIndex();
+  int index = lookup->GetFieldIndex().field_index();
+
+  // Adjust for the number of properties stored in the object. Even in the
+  // face of a transition we can use the old map here because the size of the
+  // object and the number of in-object properties is not going to change.
+  index -= object->map()->inobject_properties();
 
   Representation representation = lookup->representation();
   ASSERT(!representation.IsNone());
@@ -643,12 +648,14 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
     }
   } else if (representation.IsDouble()) {
     // Load the double storage.
-    if (index.is_inobject()) {
-      __ movp(scratch1, FieldOperand(receiver_reg, index.offset()));
+    if (index < 0) {
+      int offset = object->map()->instance_size() + (index * kPointerSize);
+      __ movp(scratch1, FieldOperand(receiver_reg, offset));
     } else {
       __ movp(scratch1,
               FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
-      __ movp(scratch1, FieldOperand(scratch1, index.offset()));
+      int offset = index * kPointerSize + FixedArray::kHeaderSize;
+      __ movp(scratch1, FieldOperand(scratch1, offset));
     }
 
     // Store the value into the storage.
@@ -673,30 +680,32 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   // TODO(verwaest): Share this code as a code stub.
   SmiCheck smi_check = representation.IsTagged()
       ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
-  if (index.is_inobject()) {
+  if (index < 0) {
     // Set the property straight into the object.
-    __ movp(FieldOperand(receiver_reg, index.offset()), value_reg);
+    int offset = object->map()->instance_size() + (index * kPointerSize);
+    __ movp(FieldOperand(receiver_reg, offset), value_reg);
 
     if (!representation.IsSmi()) {
       // Update the write barrier for the array address.
       // Pass the value being stored in the now unused name_reg.
       __ movp(name_reg, value_reg);
       __ RecordWriteField(
-          receiver_reg, index.offset(), name_reg, scratch1, kDontSaveFPRegs,
+          receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs,
           EMIT_REMEMBERED_SET, smi_check);
     }
   } else {
     // Write to the properties array.
+    int offset = index * kPointerSize + FixedArray::kHeaderSize;
     // Get the properties array (optimistically).
     __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
-    __ movp(FieldOperand(scratch1, index.offset()), value_reg);
+    __ movp(FieldOperand(scratch1, offset), value_reg);
 
     if (!representation.IsSmi()) {
       // Update the write barrier for the array address.
       // Pass the value being stored in the now unused name_reg.
       __ movp(name_reg, value_reg);
       __ RecordWriteField(
-          scratch1, index.offset(), name_reg, receiver_reg, kDontSaveFPRegs,
+          scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs,
           EMIT_REMEMBERED_SET, smi_check);
     }
   }
@@ -904,14 +913,20 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
 
 void LoadStubCompiler::GenerateLoadField(Register reg,
                                          Handle<JSObject> holder,
-                                         FieldIndex field,
+                                         PropertyIndex field,
                                          Representation representation) {
   if (!reg.is(receiver())) __ movp(receiver(), reg);
   if (kind() == Code::LOAD_IC) {
-    LoadFieldStub stub(isolate(), field);
+    LoadFieldStub stub(isolate(),
+                       field.is_inobject(holder),
+                       field.translate(holder),
+                       representation);
     GenerateTailCall(masm(), stub.GetCode());
   } else {
-    KeyedLoadFieldStub stub(isolate(), field);
+    KeyedLoadFieldStub stub(isolate(),
+                            field.is_inobject(holder),
+                            field.translate(holder),
+                            representation);
     GenerateTailCall(masm(), stub.GetCode());
   }
 }
index b86b96db009cade488d690739f39329fc47eb20e..158e146967ce067485272c37ca6df11976066004 100644 (file)
@@ -1018,9 +1018,7 @@ TEST(Regression39128) {
   CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
   CHECK_EQ(0, jsobject->properties()->length());
   // Create a reference to object in new space in jsobject.
-  FieldIndex index = FieldIndex::ForInObjectOffset(
-      JSObject::kHeaderSize - kPointerSize);
-  jsobject->FastPropertyAtPut(index, array);
+  jsobject->FastPropertyAtPut(-1, array);
 
   CHECK_EQ(0, static_cast<int>(*limit_addr - *top_addr));
 
@@ -2320,17 +2318,13 @@ TEST(OptimizedPretenuringMixedInObjectProperties) {
       v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
 
   CHECK(CcTest::heap()->InOldPointerSpace(*o));
-  FieldIndex idx1 = FieldIndex::ForPropertyIndex(o->map(), 0);
-  FieldIndex idx2 = FieldIndex::ForPropertyIndex(o->map(), 1);
-  CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(idx1)));
-  CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(idx2)));
+  CHECK(CcTest::heap()->InOldPointerSpace(o->RawFastPropertyAt(0)));
+  CHECK(CcTest::heap()->InOldDataSpace(o->RawFastPropertyAt(1)));
 
-  JSObject* inner_object =
-      reinterpret_cast<JSObject*>(o->RawFastPropertyAt(idx1));
+  JSObject* inner_object = reinterpret_cast<JSObject*>(o->RawFastPropertyAt(0));
   CHECK(CcTest::heap()->InOldPointerSpace(inner_object));
-  CHECK(CcTest::heap()->InOldDataSpace(inner_object->RawFastPropertyAt(idx1)));
-  CHECK(CcTest::heap()->InOldPointerSpace(
-      inner_object->RawFastPropertyAt(idx2)));
+  CHECK(CcTest::heap()->InOldDataSpace(inner_object->RawFastPropertyAt(0)));
+  CHECK(CcTest::heap()->InOldPointerSpace(inner_object->RawFastPropertyAt(1)));
 }
 
 
@@ -3087,9 +3081,9 @@ TEST(Regress2211) {
     CHECK(value->Equals(obj->GetHiddenValue(v8_str("key string"))));
 
     // Check size.
-    FieldIndex index = FieldIndex::ForDescriptor(internal_obj->map(), 0);
+    DescriptorArray* descriptors = internal_obj->map()->instance_descriptors();
     ObjectHashTable* hashtable = ObjectHashTable::cast(
-        internal_obj->RawFastPropertyAt(index));
+        internal_obj->RawFastPropertyAt(descriptors->GetFieldIndex(0)));
     // HashTable header (5) and 4 initial entries (8).
     CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize);
   }
index f88771e457062fbcfe97e5d7a8eef2668735c5e3..8368d81d93a1a2a86ff07c39a30be7f2ae36e041 100644 (file)
         '../../src/fast-dtoa.cc',
         '../../src/fast-dtoa.h',
         '../../src/feedback-slots.h',
-        '../../src/field-index.cc',
-        '../../src/field-index.h',
-        '../../src/field-index-inl.h',
         '../../src/fixed-dtoa.cc',
         '../../src/fixed-dtoa.h',
         '../../src/flag-definitions.h',