Revision: 12034
Author:   [email protected]
Date:     Tue Jul 10 06:31:36 2012
Log:      Swap bitfield3 and backpointer.

Bitfield3 now has its own field, while the backpointer shares the field with the descriptor array; which will become the transition array.

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/10692130
http://code.google.com/p/v8/source/detail?r=12034

Modified:
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.h
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
 /branches/bleeding_edge/src/mark-compact.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed Jun 20 01:58:41 2012 +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Tue Jul 10 06:31:36 2012
@@ -1141,7 +1141,7 @@

   // We got a map in register r0. Get the enumeration cache from it.
   __ bind(&use_cache);
-  __ LoadInstanceDescriptors(r0, r1);
+  __ LoadInstanceDescriptors(r0, r1, r2);
__ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset)); __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));

@@ -2737,7 +2737,7 @@
   // Look for valueOf symbol in the descriptor array, and indicate false if
   // found. The type is not checked, so if it is a transition it is a false
   // negative.
-  __ LoadInstanceDescriptors(r1, r4);
+  __ LoadInstanceDescriptors(r1, r4, r3);
   __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset));
   // r4: descriptor array
   // r3: length of descriptor array
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Tue Jun 12 05:16:19 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Tue Jul 10 06:31:36 2012
@@ -2381,8 +2381,9 @@

 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
   LOperand* map = UseRegister(instr->map());
+  LOperand* scratch = TempRegister();
   return AssignEnvironment(DefineAsRegister(
-      new(zone()) LForInCacheArray(map)));
+      new(zone()) LForInCacheArray(map, scratch)));
 }


=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h       Mon Jun 11 05:42:31 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.h       Tue Jul 10 06:31:36 2012
@@ -2177,13 +2177,15 @@
 };


-class LForInCacheArray: public LTemplateInstruction<1, 1, 0> {
+class LForInCacheArray: public LTemplateInstruction<1, 1, 1> {
  public:
-  explicit LForInCacheArray(LOperand* map) {
+  explicit LForInCacheArray(LOperand* map, LOperand* scratch) {
     inputs_[0] = map;
+    temps_[0] = scratch;
   }

   LOperand* map() { return inputs_[0]; }
+  LOperand* scratch() { return temps_[0]; }

   DECLARE_CONCRETE_INSTRUCTION(ForInCacheArray, "for-in-cache-array")

=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Jul 5 06:54:20 2012 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jul 10 06:31:36 2012
@@ -5357,7 +5357,8 @@
 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
   Register map = ToRegister(instr->map());
   Register result = ToRegister(instr->result());
-  __ LoadInstanceDescriptors(map, result);
+  Register scratch = ToRegister(instr->scratch());
+  __ LoadInstanceDescriptors(map, result, scratch);
   __ ldr(result,
FieldMemOperand(result, DescriptorArray::kEnumerationIndexOffset));
   __ ldr(result,
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Fri Jun 15 02:15:57 2012 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue Jul 10 06:31:36 2012
@@ -3673,13 +3673,21 @@


 void MacroAssembler::LoadInstanceDescriptors(Register map,
-                                             Register descriptors) {
+                                             Register descriptors,
+                                             Register scratch) {
   ldr(descriptors,
-      FieldMemOperand(map, Map::kInstanceDescriptorsOrBitField3Offset));
-  Label not_smi;
-  JumpIfNotSmi(descriptors, &not_smi);
+      FieldMemOperand(map, Map::kInstanceDescriptorsOrBackPointerOffset));
+
+  Label ok, fail;
+  CheckMap(descriptors,
+           scratch,
+           isolate()->factory()->fixed_array_map(),
+           &fail,
+           DONT_DO_SMI_CHECK);
+  jmp(&ok);
+  bind(&fail);
   mov(descriptors, Operand(FACTORY->empty_descriptor_array()));
-  bind(&not_smi);
+  bind(&ok);
 }


@@ -3704,8 +3712,13 @@
   // check for an enum cache.  Leave the map in r2 for the subsequent
   // prototype load.
   ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
-  ldr(r3, FieldMemOperand(r2, Map::kInstanceDescriptorsOrBitField3Offset));
-  JumpIfSmi(r3, call_runtime);
+ ldr(r3, FieldMemOperand(r2, Map::kInstanceDescriptorsOrBackPointerOffset));
+
+  CheckMap(r3,
+           r7,
+           isolate()->factory()->fixed_array_map(),
+           call_runtime,
+           DONT_DO_SMI_CHECK);

   // Check that there is an enum cache in the non-empty instance
   // descriptors (r3).  This is the case if the next enumeration
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Tue Jun 12 08:44:12 2012 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Tue Jul 10 06:31:36 2012
@@ -1268,7 +1268,9 @@
                           DoubleRegister temp_double_reg);


-  void LoadInstanceDescriptors(Register map, Register descriptors);
+  void LoadInstanceDescriptors(Register map,
+                               Register descriptors,
+                               Register scratch);

   // Activation support.
   void EnterFrame(StackFrame::Type type);
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Jul 10 05:52:36 2012
+++ /branches/bleeding_edge/src/heap.cc Tue Jul 10 06:31:36 2012
@@ -2058,6 +2058,7 @@
   reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
   reinterpret_cast<Map*>(result)->set_bit_field(0);
   reinterpret_cast<Map*>(result)->set_bit_field2(0);
+  reinterpret_cast<Map*>(result)->set_bit_field3(0);
   return result;
 }

@@ -2080,12 +2081,12 @@
   map->set_instance_size(instance_size);
   map->set_inobject_properties(0);
   map->set_pre_allocated_property_fields(0);
-  map->init_instance_descriptors();
   map->set_code_cache(empty_fixed_array(), SKIP_WRITE_BARRIER);
   map->init_back_pointer(undefined_value());
   map->set_unused_property_fields(0);
   map->set_bit_field(0);
   map->set_bit_field2(1 << Map::kIsExtensible);
+  map->set_bit_field3(0);
   map->set_elements_kind(elements_kind);

   // If the map object is aligned fill the padding area with Smi 0 objects.
@@ -2219,15 +2220,12 @@
   set_empty_descriptor_array(DescriptorArray::cast(obj));

   // Fix the instance_descriptors for the existing maps.
-  meta_map()->init_instance_descriptors();
   meta_map()->set_code_cache(empty_fixed_array());
   meta_map()->init_back_pointer(undefined_value());

-  fixed_array_map()->init_instance_descriptors();
   fixed_array_map()->set_code_cache(empty_fixed_array());
   fixed_array_map()->init_back_pointer(undefined_value());

-  oddball_map()->init_instance_descriptors();
   oddball_map()->set_code_cache(empty_fixed_array());
   oddball_map()->init_back_pointer(undefined_value());

@@ -4191,7 +4189,6 @@

   // Set up the global object as a normalized object.
   global->set_map(new_map);
-  global->map()->clear_instance_descriptors();
   global->set_properties(dictionary);

   // Make sure result is a global object with properties in dictionary.
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Jun 12 05:16:19 2012 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Jul 10 06:31:36 2012
@@ -2518,12 +2518,18 @@

 void MacroAssembler::LoadInstanceDescriptors(Register map,
                                              Register descriptors) {
-  mov(descriptors,
-      FieldOperand(map, Map::kInstanceDescriptorsOrBitField3Offset));
-  Label not_smi;
-  JumpIfNotSmi(descriptors, &not_smi);
+  mov(descriptors, FieldOperand(map,
+ Map::kInstanceDescriptorsOrBackPointerOffset));
+
+  Label ok, fail;
+  CheckMap(descriptors,
+           isolate()->factory()->fixed_array_map(),
+           &fail,
+           DONT_DO_SMI_CHECK);
+  jmp(&ok);
+  bind(&fail);
   mov(descriptors, isolate()->factory()->empty_descriptor_array());
-  bind(&not_smi);
+  bind(&ok);
 }


@@ -2886,8 +2892,11 @@
   // check for an enum cache.  Leave the map in ebx for the subsequent
   // prototype load.
   mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
-  mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOrBitField3Offset));
-  JumpIfSmi(edx, call_runtime);
+ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOrBackPointerOffset));
+  CheckMap(edx,
+           isolate()->factory()->fixed_array_map(),
+           call_runtime,
+           DONT_DO_SMI_CHECK);

   // Check that there is an enum cache in the non-empty instance
   // descriptors (edx).  This is the case if the next enumeration
=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Tue Jul 10 00:53:00 2012
+++ /branches/bleeding_edge/src/mark-compact.cc Tue Jul 10 06:31:36 2012
@@ -1829,20 +1829,23 @@
base_marker()->MarkObjectAndPush(HeapObject::cast(map->GetBackPointer()));

   Object** descriptor_array_slot =
- HeapObject::RawField(map, Map::kInstanceDescriptorsOrBitField3Offset); + HeapObject::RawField(map, Map::kInstanceDescriptorsOrBackPointerOffset);
   Object* descriptor_array = *descriptor_array_slot;
-  if (!descriptor_array->IsSmi()) {
+  if (descriptor_array->IsDescriptorArray()) {
MarkDescriptorArray(reinterpret_cast<DescriptorArray*>(descriptor_array));
+  } else {
+    // Already marked by marking map->GetBackPointer().
+    ASSERT(descriptor_array->IsMap() || descriptor_array->IsUndefined());
   }

// Mark the Object* fields of the Map. Since the descriptor array has been
   // marked already, it is fine that one of these fields contains a pointer
   // to it. But make sure to skip back pointer.
   STATIC_ASSERT(Map::kPointerFieldsEndOffset ==
-                Map::kBackPointerOffset + kPointerSize);
+                Map::kBitField3Offset + kPointerSize);
   Object** start_slot =
       HeapObject::RawField(map, Map::kPointerFieldsBeginOffset);
-  Object** end_slot = HeapObject::RawField(map, Map::kBackPointerOffset);
+  Object** end_slot = HeapObject::RawField(map, Map::kBitField3Offset);
   for (Object** slot = start_slot; slot < end_slot; slot++) {
     Object* obj = *slot;
     if (!obj->NonFailureIsHeapObject()) continue;
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Tue Jul 10 00:53:00 2012
+++ /branches/bleeding_edge/src/objects-inl.h   Tue Jul 10 06:31:36 2012
@@ -1896,14 +1896,17 @@
 }


-int DescriptorArray::bit_field3_storage() {
-  Object* storage = READ_FIELD(this, kBitField3StorageOffset);
-  return Smi::cast(storage)->value();
+Object* DescriptorArray::back_pointer_storage() {
+  return READ_FIELD(this, kBackPointerStorageOffset);
 }

-void DescriptorArray::set_bit_field3_storage(int value) {
-  ASSERT(length() > kBitField3StorageIndex);
-  WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
+
+void DescriptorArray::set_back_pointer_storage(Object* value,
+                                               WriteBarrierMode mode) {
+  ASSERT(length() > kBackPointerStorageIndex);
+  Heap* heap = GetHeap();
+  WRITE_FIELD(this, kBackPointerStorageOffset, value);
+ CONDITIONAL_WRITE_BARRIER(heap, this, kBackPointerStorageOffset, value, mode);
 }


@@ -3437,95 +3440,71 @@


 DescriptorArray* Map::instance_descriptors() {
-  Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
-  if (object->IsSmi()) {
+ Object* object = READ_FIELD(this, kInstanceDescriptorsOrBackPointerOffset);
+  if (!object->IsDescriptorArray()) {
+    ASSERT(object->IsMap() || object->IsUndefined());
     return GetHeap()->empty_descriptor_array();
   } else {
     return DescriptorArray::cast(object);
   }
 }
-
-
-void Map::init_instance_descriptors() {
- WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0));
-}
-
-
-void Map::clear_instance_descriptors() {
-  Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
-  if (!object->IsSmi()) {
-    WRITE_FIELD(
-        this,
-        kInstanceDescriptorsOrBitField3Offset,
-        Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage()));
-  }
-}


 void Map::set_instance_descriptors(DescriptorArray* value,
                                    WriteBarrierMode mode) {
-  Object* object = READ_FIELD(this,
-                              kInstanceDescriptorsOrBitField3Offset);
   Heap* heap = GetHeap();
+
   if (value == heap->empty_descriptor_array()) {
-    clear_instance_descriptors();
+    ClearDescriptorArray(heap, mode);
     return;
+  }
+
+ Object* object = READ_FIELD(this, kInstanceDescriptorsOrBackPointerOffset);
+
+  if (object->IsDescriptorArray()) {
+    value->set_back_pointer_storage(
+        DescriptorArray::cast(object)->back_pointer_storage());
   } else {
-    if (object->IsSmi()) {
-      value->set_bit_field3_storage(Smi::cast(object)->value());
-    } else {
-      value->set_bit_field3_storage(
-          DescriptorArray::cast(object)->bit_field3_storage());
-    }
-  }
+    ASSERT(object->IsMap() || object->IsUndefined());
+    value->set_back_pointer_storage(object);
+  }
+
   ASSERT(!is_shared());
-  WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
+  WRITE_FIELD(this, kInstanceDescriptorsOrBackPointerOffset, value);
   CONDITIONAL_WRITE_BARRIER(
-      heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode);
+      heap, this, kInstanceDescriptorsOrBackPointerOffset, value, mode);
 }


-int Map::bit_field3() {
-  Object* object = READ_FIELD(this,
-                              kInstanceDescriptorsOrBitField3Offset);
-  if (object->IsSmi()) {
-    return Smi::cast(object)->value();
-  } else {
-    return DescriptorArray::cast(object)->bit_field3_storage();
-  }
-}
+SMI_ACCESSORS(Map, bit_field3, kBitField3Offset)


-void Map::ClearDescriptorArray() {
-  int bitfield3 = bit_field3();
+void Map::ClearDescriptorArray(Heap* heap, WriteBarrierMode mode) {
+  Object* back_pointer = GetBackPointer();
 #ifdef DEBUG
-  Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
-  if (!object->IsSmi()) {
+ Object* object = READ_FIELD(this, kInstanceDescriptorsOrBackPointerOffset);
+  if (object->IsDescriptorArray()) {
     ZapTransitions();
+  } else {
+    ASSERT(object->IsMap() || object->IsUndefined());
   }
 #endif
-  WRITE_FIELD(this,
-              kInstanceDescriptorsOrBitField3Offset,
-              Smi::FromInt(bitfield3));
+  WRITE_FIELD(this, kInstanceDescriptorsOrBackPointerOffset, back_pointer);
+  CONDITIONAL_WRITE_BARRIER(
+ heap, this, kInstanceDescriptorsOrBackPointerOffset, back_pointer, mode);
 }


-void Map::set_bit_field3(int value) {
-  ASSERT(Smi::IsValid(value));
-  Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
-  if (object->IsSmi()) {
-    WRITE_FIELD(this,
-                kInstanceDescriptorsOrBitField3Offset,
-                Smi::FromInt(value));
+
+Object* Map::GetBackPointer() {
+ Object* object = READ_FIELD(this, kInstanceDescriptorsOrBackPointerOffset);
+  if (object->IsDescriptorArray()) {
+    return DescriptorArray::cast(object)->back_pointer_storage();
   } else {
-    DescriptorArray::cast(object)->set_bit_field3_storage(value);
+    ASSERT(object->IsMap() || object->IsUndefined());
+    return object;
   }
 }
-
-
-Object* Map::GetBackPointer() {
-  return READ_FIELD(this, kBackPointerOffset);
-}


 bool Map::HasElementsTransition() {
@@ -3549,8 +3528,8 @@
 }


-// If the map does not have a descriptor array, install a new empty
-// descriptor array that has room for a transition array.
+// If the map is using the empty descriptor array, install a new empty
+// descriptor array that will contain an elements transition.
 static MaybeObject* AllowTransitions(Map* map) {
   if (map->instance_descriptors()->MayContainTransitions()) return map;
   DescriptorArray* descriptors;
@@ -3619,13 +3598,13 @@
 }


-void Map::ClearTransitions() {
+void Map::ClearTransitions(Heap* heap, WriteBarrierMode mode) {
 #ifdef DEBUG
   ZapTransitions();
 #endif
   DescriptorArray* descriptors = instance_descriptors();
   if (descriptors->number_of_descriptors() == 0) {
-    ClearDescriptorArray();
+    ClearDescriptorArray(heap, mode);
   } else {
     descriptors->ClearTransitions();
   }
@@ -3648,17 +3627,22 @@

 void Map::init_back_pointer(Object* undefined) {
   ASSERT(undefined->IsUndefined());
-  WRITE_FIELD(this, kBackPointerOffset, undefined);
+  WRITE_FIELD(this, kInstanceDescriptorsOrBackPointerOffset, undefined);
 }


 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
-  Heap* heap = GetHeap();
   ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE);
   ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) ||
          (value->IsMap() && GetBackPointer()->IsUndefined()));
-  WRITE_FIELD(this, kBackPointerOffset, value);
-  CONDITIONAL_WRITE_BARRIER(heap, this, kBackPointerOffset, value, mode);
+ Object* object = READ_FIELD(this, kInstanceDescriptorsOrBackPointerOffset);
+  if (object->IsMap()) {
+    WRITE_FIELD(this, kInstanceDescriptorsOrBackPointerOffset, value);
+    CONDITIONAL_WRITE_BARRIER(
+ GetHeap(), this, kInstanceDescriptorsOrBackPointerOffset, value, mode);
+  } else {
+    DescriptorArray::cast(object)->set_back_pointer_storage(value);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/objects.cc      Tue Jul 10 04:28:33 2012
+++ /branches/bleeding_edge/src/objects.cc      Tue Jul 10 06:31:36 2012
@@ -3410,10 +3410,8 @@
     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
                                                -instance_size_delta);
   }
-

   set_map(new_map);
-  new_map->clear_instance_descriptors();

   set_properties(dictionary);

@@ -4927,12 +4925,7 @@
   }
   Map::cast(result)->set_prototype(prototype());
   Map::cast(result)->set_constructor(constructor());
-  // Don't copy descriptors, so map transitions always remain a forest.
-  // If we retained the same descriptors we would have two maps
-  // pointing to the same transition which is bad because the garbage
-  // collector relies on being able to reverse pointers from transitions
-  // to maps.  If properties need to be retained use CopyDropTransitions.
-  Map::cast(result)->clear_instance_descriptors();
+
   // Please note instance_type and instance_size are set when allocated.
   Map::cast(result)->set_inobject_properties(inobject_properties());
   Map::cast(result)->set_unused_property_fields(unused_property_fields());
@@ -5824,7 +5817,6 @@
     if (!maybe_array->To(&result)) return maybe_array;
   }

-  result->set(kBitField3StorageIndex, Smi::FromInt(0));
   result->set(kEnumerationIndexIndex,
               Smi::FromInt(PropertyDetails::kInitialIndex));
   result->set(kTransitionsIndex, Smi::FromInt(0));
@@ -7413,7 +7405,7 @@
   if (transition_index == 0 &&
       !t->HasElementsTransition() &&
       !t->HasPrototypeTransitions()) {
-    return ClearTransitions();
+    return ClearTransitions(heap);
   }

   int trim = t->number_of_transitions() - transition_index;
=======================================
--- /branches/bleeding_edge/src/objects.h       Tue Jul 10 00:53:00 2012
+++ /branches/bleeding_edge/src/objects.h       Tue Jul 10 06:31:36 2012
@@ -2514,11 +2514,7 @@
                                 kTransitionsOffset);
   }

- // TODO(1399): It should be possible to make room for bit_field3 in the map - // without overloading the instance descriptors field in the map - // (and storing it in the DescriptorArray when the map has one).
-  inline int bit_field3_storage();
-  inline void set_bit_field3_storage(int value);
+  DECL_ACCESSORS(back_pointer_storage, Object)

   // Initialize or change the enum cache,
   // using the supplied storage for the small "bridge".
@@ -2607,7 +2603,7 @@
   // Constant for denoting key was not found.
   static const int kNotFound = -1;

-  static const int kBitField3StorageIndex = 0;
+  static const int kBackPointerStorageIndex = 0;
   static const int kEnumerationIndexIndex = 1;
   static const int kTransitionsIndex = 2;
   static const int kFirstIndex = 3;
@@ -2619,8 +2615,8 @@
   static const int kEnumCacheBridgeIndicesCacheIndex = 2;

   // Layout description.
-  static const int kBitField3StorageOffset = FixedArray::kHeaderSize;
-  static const int kEnumerationIndexOffset = kBitField3StorageOffset +
+  static const int kBackPointerStorageOffset = FixedArray::kHeaderSize;
+  static const int kEnumerationIndexOffset = kBackPointerStorageOffset +
                                              kPointerSize;
static const int kTransitionsOffset = kEnumerationIndexOffset + kPointerSize;
   static const int kFirstOffset = kTransitionsOffset + kPointerSize;
@@ -4676,12 +4672,8 @@
   inline void set_bit_field2(byte value);

   // Bit field 3.
- // TODO(1399): It should be possible to make room for bit_field3 in the map - // without overloading the instance descriptors field (and storing it in the
-  // DescriptorArray when the map has one).
   inline int bit_field3();
   inline void set_bit_field3(int value);
-  inline void SetOwnBitField3(int value);

   // Tells whether the object in the prototype property will be used
   // for instances created from this function.  If the prototype
@@ -4812,7 +4804,8 @@
                                                     Object* value);
   MUST_USE_RESULT inline MaybeObject* set_transitions(
       TransitionArray* transitions);
-  inline void ClearTransitions();
+  inline void ClearTransitions(Heap* heap,
+ WriteBarrierMode mode = UPDATE_WRITE_BARRIER);

   // Tells whether the map is attached to SharedFunctionInfo
   // (for inobject slack tracking).
@@ -4839,20 +4832,12 @@

   inline JSFunction* unchecked_constructor();

- // Should only be called by the code that initializes map to set initial valid
-  // value of the instance descriptor member.
-  inline void init_instance_descriptors();
-
   // [instance descriptors]: describes the object.
   DECL_ACCESSORS(instance_descriptors, DescriptorArray)

// Should only be called to clear a descriptor array that was only used to
   // store transitions and does not contain any live transitions anymore.
-  inline void ClearDescriptorArray();
-
- // Sets the instance descriptor array for the map to be an empty descriptor
-  // array.
-  inline void clear_instance_descriptors();
+  inline void ClearDescriptorArray(Heap* heap, WriteBarrierMode mode);

   // [stub cache]: contains stubs compiled for this map.
   DECL_ACCESSORS(code_cache, Object)
@@ -5047,23 +5032,18 @@
// map flags when unused (bit_field3). When the map has instance descriptors, // the flags are transferred to the instance descriptor array and accessed
   // through an extra indirection.
- // TODO(1399): It should be possible to make room for bit_field3 in the map
-  // without overloading the instance descriptors field, but the map is
-  // currently perfectly aligned to 32 bytes and extending it at all would
- // double its size. After the increment GC work lands, this size restriction
-  // could be loosened and bit_field3 moved directly back in the map.
-  static const int kInstanceDescriptorsOrBitField3Offset =
+  static const int kInstanceDescriptorsOrBackPointerOffset =
       kConstructorOffset + kPointerSize;
   static const int kCodeCacheOffset =
-      kInstanceDescriptorsOrBitField3Offset + kPointerSize;
-  static const int kBackPointerOffset = kCodeCacheOffset + kPointerSize;
-  static const int kPadStart = kBackPointerOffset + kPointerSize;
+      kInstanceDescriptorsOrBackPointerOffset + kPointerSize;
+  static const int kBitField3Offset = kCodeCacheOffset + kPointerSize;
+  static const int kPadStart = kBitField3Offset + kPointerSize;
   static const int kSize = MAP_POINTER_ALIGN(kPadStart);

   // Layout of pointer fields. Heap iteration code relies on them
   // being continuously allocated.
   static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
- static const int kPointerFieldsEndOffset = kBackPointerOffset + kPointerSize; + static const int kPointerFieldsEndOffset = kBitField3Offset + kPointerSize;

   // Byte offsets within kInstanceSizesOffset.
   static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Tue Jul 10 00:53:00 2012 +++ /branches/bleeding_edge/src/profile-generator.cc Tue Jul 10 06:31:36 2012
@@ -2011,7 +2011,7 @@
     TagObject(map->instance_descriptors(), "(map descriptors)");
     SetInternalReference(map, entry,
                          "descriptors", map->instance_descriptors(),
-                         Map::kInstanceDescriptorsOrBitField3Offset);
+                         Map::kInstanceDescriptorsOrBackPointerOffset);
   }
   SetInternalReference(map, entry,
                        "code_cache", map->code_cache(),
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Jul 10 04:28:33 2012
+++ /branches/bleeding_edge/src/runtime.cc      Tue Jul 10 06:31:36 2012
@@ -2190,13 +2190,13 @@
     DescriptorArray* new_descriptors =
         DescriptorArray::cast(descriptors_unchecked);
     // Create a new map featuring the new field descriptors array.
-    Object* map_unchecked;
- { MaybeObject* maybe_map_unchecked = function->map()->CopyDropDescriptors();
-      if (!maybe_map_unchecked->ToObject(&map_unchecked)) {
+    Map* new_map;
+    { MaybeObject* maybe_map_unchecked =
+          function->map()->CopyDropDescriptors();
+      if (!maybe_map_unchecked->To(&new_map)) {
         return maybe_map_unchecked;
       }
     }
-    Map* new_map = Map::cast(map_unchecked);
     new_map->set_instance_descriptors(new_descriptors);
     function->set_map(new_map);
   } else {  // Dictionary properties.
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue Jun 26 06:56:48 2012 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue Jul 10 06:31:36 2012
@@ -2853,11 +2853,17 @@
 void MacroAssembler::LoadInstanceDescriptors(Register map,
                                              Register descriptors) {
   movq(descriptors, FieldOperand(map,
- Map::kInstanceDescriptorsOrBitField3Offset));
-  Label not_smi;
-  JumpIfNotSmi(descriptors, &not_smi, Label::kNear);
+ Map::kInstanceDescriptorsOrBackPointerOffset));
+
+  Label ok, fail;
+  CheckMap(descriptors,
+           isolate()->factory()->fixed_array_map(),
+           &fail,
+           DONT_DO_SMI_CHECK);
+  jmp(&ok);
+  bind(&fail);
   Move(descriptors, isolate()->factory()->empty_descriptor_array());
-  bind(&not_smi);
+  bind(&ok);
 }


@@ -4457,8 +4463,12 @@
   // check for an enum cache.  Leave the map in rbx for the subsequent
   // prototype load.
   movq(rbx, FieldOperand(rcx, HeapObject::kMapOffset));
-  movq(rdx, FieldOperand(rbx, Map::kInstanceDescriptorsOrBitField3Offset));
-  JumpIfSmi(rdx, call_runtime);
+ movq(rdx, FieldOperand(rbx, Map::kInstanceDescriptorsOrBackPointerOffset));
+
+  CheckMap(rdx,
+           isolate()->factory()->fixed_array_map(),
+           call_runtime,
+           DONT_DO_SMI_CHECK);

   // Check that there is an enum cache in the non-empty instance
   // descriptors (rdx).  This is the case if the next enumeration

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to