Version 3.12.11

Renamed "mips" arch to "mipsel" in the GYP build.

Fixed computation of call targets on prototypes in Crankshaft. (Chromium issue 125148)

Removed use of __lookupGetter__ when generating stack trace. (issue 1591)

Turned on ES 5.2 globals semantics by default. (issue 1991, Chromium issue 80591)

Synced preparser and parser wrt syntax error in switch..case. (issue 2210)

Fixed reporting of octal literals in strict mode when preparsing. (issue 2220)

Fixed inline constructors for Harmony Proxy prototypes. (issue 2225)

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@12057 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.h b/src/api.h
index 2341c4c..6be4474 100644
--- a/src/api.h
+++ b/src/api.h
@@ -399,8 +399,12 @@
  private:
   DeferredHandles(DeferredHandles* next, Object** first_block_limit,
                   HandleScopeImplementer* impl)
-      : next_(next), previous_(NULL), first_block_limit_(first_block_limit),
-        impl_(impl) {}
+      : next_(next),
+        previous_(NULL),
+        first_block_limit_(first_block_limit),
+        impl_(impl) {
+    if (next != NULL) next->previous_ = this;
+  }
 
   void Iterate(ObjectVisitor* v);
 
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 68fcc28..d875796 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -80,8 +80,8 @@
 
 
 void CpuFeatures::Probe() {
-  unsigned standard_features = (OS::CpuFeaturesImpliedByPlatform() |
-                                CpuFeaturesImpliedByCompiler());
+  unsigned standard_features = static_cast<unsigned>(
+      OS::CpuFeaturesImpliedByPlatform() | CpuFeaturesImpliedByCompiler());
   ASSERT(supported_ == 0 || supported_ == standard_features);
 #ifdef DEBUG
   initialized_ = true;
@@ -746,7 +746,7 @@
         }
       }
     } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) {
-      if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
+      if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) {
         *instr ^= kCmpCmnFlip;
         return true;
       }
@@ -754,7 +754,7 @@
       Instr alu_insn = (*instr & kALUMask);
       if (alu_insn == ADD ||
           alu_insn == SUB) {
-        if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
+        if (fits_shifter(-static_cast<int>(imm32), rotate_imm, immed_8, NULL)) {
           *instr ^= kAddSubFlip;
           return true;
         }
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index e00afb9..57fe24b 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -121,15 +121,34 @@
   // r5: number of elements (smi-tagged)
 
   // Allocate new FixedDoubleArray.
-  __ mov(lr, Operand(FixedDoubleArray::kHeaderSize));
-  __ add(lr, lr, Operand(r5, LSL, 2));
+  // Use lr as a temporary register.
+  __ mov(lr, Operand(r5, LSL, 2));
+  __ add(lr, lr, Operand(FixedDoubleArray::kHeaderSize + kPointerSize));
   __ AllocateInNewSpace(lr, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
-  // r6: destination FixedDoubleArray, not tagged as heap object
+  // r6: destination FixedDoubleArray, not tagged as heap object.
+
+  // Align the array conveniently for doubles.
+  // Store a filler value in the unused memory.
+  Label aligned, aligned_done;
+  __ tst(r6, Operand(kDoubleAlignmentMask));
+  __ mov(ip, Operand(masm->isolate()->factory()->one_pointer_filler_map()));
+  __ b(eq, &aligned);
+  // Store at the beginning of the allocated memory and update the base pointer.
+  __ str(ip, MemOperand(r6, kPointerSize, PostIndex));
+  __ b(&aligned_done);
+
+  __ bind(&aligned);
+  // Store the filler at the end of the allocated memory.
+  __ sub(lr, lr, Operand(kPointerSize));
+  __ str(ip, MemOperand(r6, lr));
+
+  __ bind(&aligned_done);
+
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex);
   __ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset));
-  __ str(r9, MemOperand(r6, HeapObject::kMapOffset));
   // Update receiver's map.
+  __ str(r9, MemOperand(r6, HeapObject::kMapOffset));
 
   __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
   __ RecordWriteField(r2,
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 33a22f1..aadff7a 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1141,8 +1141,8 @@
 
   // We got a map in register r0. Get the enumeration cache from it.
   __ bind(&use_cache);
-  __ LoadInstanceDescriptors(r0, r1);
-  __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset));
+  __ LoadInstanceDescriptors(r0, r1, r2);
+  __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kLastAddedOffset));
   __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
 
   // Set up the four remaining stack slots.
@@ -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
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 283862c..c789eac 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -407,16 +407,6 @@
 }
 
 
-LChunk::LChunk(CompilationInfo* info, HGraph* graph)
-    : spill_slot_count_(0),
-      info_(info),
-      graph_(graph),
-      instructions_(32, graph->zone()),
-      pointer_maps_(8, graph->zone()),
-      inlined_closures_(1, graph->zone()) {
-}
-
-
 int LChunk::GetNextSpillIndex(bool is_double) {
   // Skip a slot if for a double-width slot.
   if (is_double) spill_slot_count_++;
@@ -434,117 +424,6 @@
 }
 
 
-void LChunk::MarkEmptyBlocks() {
-  HPhase phase("L_Mark empty blocks", this);
-  for (int i = 0; i < graph()->blocks()->length(); ++i) {
-    HBasicBlock* block = graph()->blocks()->at(i);
-    int first = block->first_instruction_index();
-    int last = block->last_instruction_index();
-    LInstruction* first_instr = instructions()->at(first);
-    LInstruction* last_instr = instructions()->at(last);
-
-    LLabel* label = LLabel::cast(first_instr);
-    if (last_instr->IsGoto()) {
-      LGoto* goto_instr = LGoto::cast(last_instr);
-      if (label->IsRedundant() &&
-          !label->is_loop_header()) {
-        bool can_eliminate = true;
-        for (int i = first + 1; i < last && can_eliminate; ++i) {
-          LInstruction* cur = instructions()->at(i);
-          if (cur->IsGap()) {
-            LGap* gap = LGap::cast(cur);
-            if (!gap->IsRedundant()) {
-              can_eliminate = false;
-            }
-          } else {
-            can_eliminate = false;
-          }
-        }
-
-        if (can_eliminate) {
-          label->set_replacement(GetLabel(goto_instr->block_id()));
-        }
-      }
-    }
-  }
-}
-
-
-void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
-  LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
-  int index = -1;
-  if (instr->IsControl()) {
-    instructions_.Add(gap, zone());
-    index = instructions_.length();
-    instructions_.Add(instr, zone());
-  } else {
-    index = instructions_.length();
-    instructions_.Add(instr, zone());
-    instructions_.Add(gap, zone());
-  }
-  if (instr->HasPointerMap()) {
-    pointer_maps_.Add(instr->pointer_map(), zone());
-    instr->pointer_map()->set_lithium_position(index);
-  }
-}
-
-
-LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
-  return LConstantOperand::Create(constant->id(), zone());
-}
-
-
-int LChunk::GetParameterStackSlot(int index) const {
-  // The receiver is at index 0, the first parameter at index 1, so we
-  // shift all parameter indexes down by the number of parameters, and
-  // make sure they end up negative so they are distinguishable from
-  // spill slots.
-  int result = index - info()->scope()->num_parameters() - 1;
-  ASSERT(result < 0);
-  return result;
-}
-
-// A parameter relative to ebp in the arguments stub.
-int LChunk::ParameterAt(int index) {
-  ASSERT(-1 <= index);  // -1 is the receiver.
-  return (1 + info()->scope()->num_parameters() - index) *
-      kPointerSize;
-}
-
-
-LGap* LChunk::GetGapAt(int index) const {
-  return LGap::cast(instructions_[index]);
-}
-
-
-bool LChunk::IsGapAt(int index) const {
-  return instructions_[index]->IsGap();
-}
-
-
-int LChunk::NearestGapPos(int index) const {
-  while (!IsGapAt(index)) index--;
-  return index;
-}
-
-
-void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
-  GetGapAt(index)->GetOrCreateParallelMove(
-      LGap::START, zone())->AddMove(from, to, zone());
-}
-
-
-Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
-  return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
-}
-
-
-Representation LChunk::LookupLiteralRepresentation(
-    LConstantOperand* operand) const {
-  return graph_->LookupValue(operand->index())->representation();
-}
-
-
 LChunk* LChunkBuilder::Build() {
   ASSERT(is_unused());
   chunk_ = new(zone()) LChunk(info(), graph());
@@ -2381,8 +2260,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)));
 }
 
 
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 869a80a..5b1a76f 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -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")
 
@@ -2222,65 +2224,13 @@
 
 
 class LChunkBuilder;
-class LChunk: public ZoneObject {
+class LChunk: public LChunkBase {
  public:
-  explicit LChunk(CompilationInfo* info, HGraph* graph);
-
-  void AddInstruction(LInstruction* instruction, HBasicBlock* block);
-  LConstantOperand* DefineConstantOperand(HConstant* constant);
-  Handle<Object> LookupLiteral(LConstantOperand* operand) const;
-  Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
+  explicit LChunk(CompilationInfo* info, HGraph* graph)
+      : LChunkBase(info, graph) { }
 
   int GetNextSpillIndex(bool is_double);
   LOperand* GetNextSpillSlot(bool is_double);
-
-  int ParameterAt(int index);
-  int GetParameterStackSlot(int index) const;
-  int spill_slot_count() const { return spill_slot_count_; }
-  CompilationInfo* info() const { return info_; }
-  HGraph* graph() const { return graph_; }
-  const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
-  void AddGapMove(int index, LOperand* from, LOperand* to);
-  LGap* GetGapAt(int index) const;
-  bool IsGapAt(int index) const;
-  int NearestGapPos(int index) const;
-  void MarkEmptyBlocks();
-  const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
-  LLabel* GetLabel(int block_id) const {
-    HBasicBlock* block = graph_->blocks()->at(block_id);
-    int first_instruction = block->first_instruction_index();
-    return LLabel::cast(instructions_[first_instruction]);
-  }
-  int LookupDestination(int block_id) const {
-    LLabel* cur = GetLabel(block_id);
-    while (cur->replacement() != NULL) {
-      cur = cur->replacement();
-    }
-    return cur->block_id();
-  }
-  Label* GetAssemblyLabel(int block_id) const {
-    LLabel* label = GetLabel(block_id);
-    ASSERT(!label->HasReplacement());
-    return label->label();
-  }
-
-  const ZoneList<Handle<JSFunction> >* inlined_closures() const {
-    return &inlined_closures_;
-  }
-
-  void AddInlinedClosure(Handle<JSFunction> closure) {
-    inlined_closures_.Add(closure, zone());
-  }
-
-  Zone* zone() const { return graph_->zone(); }
-
- private:
-  int spill_slot_count_;
-  CompilationInfo* info_;
-  HGraph* const graph_;
-  ZoneList<LInstruction*> instructions_;
-  ZoneList<LPointerMap*> pointer_maps_;
-  ZoneList<Handle<JSFunction> > inlined_closures_;
 };
 
 
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 36c67d0..fb687f7 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -322,7 +322,8 @@
     return ToRegister(op->index());
   } else if (op->IsConstantOperand()) {
     LConstantOperand* const_op = LConstantOperand::cast(op);
-    Handle<Object> literal = chunk_->LookupLiteral(const_op);
+    HConstant* constant = chunk_->LookupConstant(const_op);
+    Handle<Object> literal = constant->handle();
     Representation r = chunk_->LookupLiteralRepresentation(const_op);
     if (r.IsInteger32()) {
       ASSERT(literal->IsNumber());
@@ -360,7 +361,8 @@
     return ToDoubleRegister(op->index());
   } else if (op->IsConstantOperand()) {
     LConstantOperand* const_op = LConstantOperand::cast(op);
-    Handle<Object> literal = chunk_->LookupLiteral(const_op);
+    HConstant* constant = chunk_->LookupConstant(const_op);
+    Handle<Object> literal = constant->handle();
     Representation r = chunk_->LookupLiteralRepresentation(const_op);
     if (r.IsInteger32()) {
       ASSERT(literal->IsNumber());
@@ -386,9 +388,9 @@
 
 
 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
-  Handle<Object> literal = chunk_->LookupLiteral(op);
+  HConstant* constant = chunk_->LookupConstant(op);
   ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
-  return literal;
+  return constant->handle();
 }
 
 
@@ -398,33 +400,33 @@
 
 
 int LCodeGen::ToInteger32(LConstantOperand* op) const {
-  Handle<Object> value = chunk_->LookupLiteral(op);
+  HConstant* constant = chunk_->LookupConstant(op);
   ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
-  ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
-      value->Number());
-  return static_cast<int32_t>(value->Number());
+  ASSERT(constant->HasInteger32Value());
+  return constant->Integer32Value();
 }
 
 
 double LCodeGen::ToDouble(LConstantOperand* op) const {
-  Handle<Object> value = chunk_->LookupLiteral(op);
-  return value->Number();
+  HConstant* constant = chunk_->LookupConstant(op);
+  ASSERT(constant->HasDoubleValue());
+  return constant->DoubleValue();
 }
 
 
 Operand LCodeGen::ToOperand(LOperand* op) {
   if (op->IsConstantOperand()) {
     LConstantOperand* const_op = LConstantOperand::cast(op);
-    Handle<Object> literal = chunk_->LookupLiteral(const_op);
+    HConstant* constant = chunk()->LookupConstant(const_op);
     Representation r = chunk_->LookupLiteralRepresentation(const_op);
     if (r.IsInteger32()) {
-      ASSERT(literal->IsNumber());
-      return Operand(static_cast<int32_t>(literal->Number()));
+      ASSERT(constant->HasInteger32Value());
+      return Operand(constant->Integer32Value());
     } else if (r.IsDouble()) {
       Abort("ToOperand Unsupported double immediate.");
     }
     ASSERT(r.IsTagged());
-    return Operand(literal);
+    return Operand(constant->handle());
   } else if (op->IsRegister()) {
     return Operand(ToRegister(op));
   } else if (op->IsDoubleRegister()) {
@@ -553,8 +555,8 @@
     DoubleRegister reg = ToDoubleRegister(op);
     translation->StoreDoubleRegister(reg);
   } else if (op->IsConstantOperand()) {
-    Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op));
-    int src_index = DefineDeoptimizationLiteral(literal);
+    HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
+    int src_index = DefineDeoptimizationLiteral(constant->handle());
     translation->StoreLiteral(src_index);
   } else {
     UNREACHABLE();
@@ -5357,9 +5359,10 @@
 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));
+         FieldMemOperand(result, DescriptorArray::kLastAddedOffset));
   __ ldr(result,
          FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
   __ cmp(result, Operand(0));
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 933399e..84e866e 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -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,13 +3712,18 @@
   // 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
   // index field does not contain a smi.
-  ldr(r3, FieldMemOperand(r3, DescriptorArray::kEnumerationIndexOffset));
+  ldr(r3, FieldMemOperand(r3, DescriptorArray::kLastAddedOffset));
   JumpIfSmi(r3, call_runtime);
 
   // For all objects but the receiver, check that the cache is empty.
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 6b7d116..0a9e1df 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -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);
diff --git a/src/ast.cc b/src/ast.cc
index 07e5003..9d18f69 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -528,6 +528,7 @@
     if (!type->prototype()->IsJSObject()) return false;
     // Go up the prototype chain, recording where we are currently.
     holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
+    if (!holder_->HasFastProperties()) return false;
     type = Handle<Map>(holder()->map());
   }
 }
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 4238a12..54eb9b8 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -390,25 +390,32 @@
 
   DescriptorArray::WhitenessWitness witness(*descriptors);
 
+  int index = 0;
+
   {  // Add length.
     Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionLength));
-    CallbacksDescriptor d(*factory()->length_symbol(), *f, attribs);
-    descriptors->Set(0, &d, witness);
+    CallbacksDescriptor d(*factory()->length_symbol(), *f, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
+    ++index;
   }
   {  // Add name.
     Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionName));
-    CallbacksDescriptor d(*factory()->name_symbol(), *f, attribs);
-    descriptors->Set(1, &d, witness);
+    CallbacksDescriptor d(*factory()->name_symbol(), *f, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
+    ++index;
   }
   {  // Add arguments.
     Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionArguments));
-    CallbacksDescriptor d(*factory()->arguments_symbol(), *f, attribs);
-    descriptors->Set(2, &d, witness);
+    CallbacksDescriptor d(
+        *factory()->arguments_symbol(), *f, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
+    ++index;
   }
   {  // Add caller.
     Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionCaller));
-    CallbacksDescriptor d(*factory()->caller_symbol(), *f, attribs);
-    descriptors->Set(3, &d, witness);
+    CallbacksDescriptor d(*factory()->caller_symbol(), *f, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
+    ++index;
   }
   if (prototypeMode != DONT_ADD_PROTOTYPE) {
     // Add prototype.
@@ -416,9 +423,11 @@
       attribs = static_cast<PropertyAttributes>(attribs & ~READ_ONLY);
     }
     Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionPrototype));
-    CallbacksDescriptor d(*factory()->prototype_symbol(), *f, attribs);
-    descriptors->Set(4, &d, witness);
+    CallbacksDescriptor d(
+        *factory()->prototype_symbol(), *f, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
   }
+
   descriptors->Sort(witness);
   return descriptors;
 }
@@ -533,25 +542,32 @@
 
   DescriptorArray::WhitenessWitness witness(*descriptors);
 
+  int index = 0;
   {  // Add length.
     Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionLength));
-    CallbacksDescriptor d(*factory()->length_symbol(), *f, attribs);
-    descriptors->Set(0, &d, witness);
+    CallbacksDescriptor d(*factory()->length_symbol(), *f, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
+    ++index;
   }
   {  // Add name.
     Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionName));
-    CallbacksDescriptor d(*factory()->name_symbol(), *f, attribs);
-    descriptors->Set(1, &d, witness);
+    CallbacksDescriptor d(*factory()->name_symbol(), *f, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
+    ++index;
   }
   {  // Add arguments.
     Handle<AccessorPair> arguments(factory()->NewAccessorPair());
-    CallbacksDescriptor d(*factory()->arguments_symbol(), *arguments, attribs);
-    descriptors->Set(2, &d, witness);
+    CallbacksDescriptor d(
+        *factory()->arguments_symbol(), *arguments, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
+    ++index;
   }
   {  // Add caller.
     Handle<AccessorPair> caller(factory()->NewAccessorPair());
-    CallbacksDescriptor d(*factory()->caller_symbol(), *caller, attribs);
-    descriptors->Set(3, &d, witness);
+    CallbacksDescriptor d(
+        *factory()->caller_symbol(), *caller, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
+    ++index;
   }
 
   if (prototypeMode != DONT_ADD_PROTOTYPE) {
@@ -560,8 +576,9 @@
       attribs = static_cast<PropertyAttributes>(attribs | READ_ONLY);
     }
     Handle<Foreign> f(factory()->NewForeign(&Accessors::FunctionPrototype));
-    CallbacksDescriptor d(*factory()->prototype_symbol(), *f, attribs);
-    descriptors->Set(4, &d, witness);
+    CallbacksDescriptor d(
+        *factory()->prototype_symbol(), *f, attribs, index + 1);
+    descriptors->Set(index, &d, witness);
   }
 
   descriptors->Sort(witness);
@@ -950,38 +967,42 @@
     DescriptorArray::WhitenessWitness witness(*descriptors);
     PropertyAttributes final =
         static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
-    int enum_index = 0;
+    int index = 0;
     {
       // ECMA-262, section 15.10.7.1.
       FieldDescriptor field(heap->source_symbol(),
                             JSRegExp::kSourceFieldIndex,
                             final,
-                            enum_index++);
-      descriptors->Set(0, &field, witness);
+                            index + 1);
+      descriptors->Set(index, &field, witness);
+      ++index;
     }
     {
       // ECMA-262, section 15.10.7.2.
       FieldDescriptor field(heap->global_symbol(),
                             JSRegExp::kGlobalFieldIndex,
                             final,
-                            enum_index++);
-      descriptors->Set(1, &field, witness);
+                            index + 1);
+      descriptors->Set(index, &field, witness);
+      ++index;
     }
     {
       // ECMA-262, section 15.10.7.3.
       FieldDescriptor field(heap->ignore_case_symbol(),
                             JSRegExp::kIgnoreCaseFieldIndex,
                             final,
-                            enum_index++);
-      descriptors->Set(2, &field, witness);
+                            index + 1);
+      descriptors->Set(index, &field, witness);
+      ++index;
     }
     {
       // ECMA-262, section 15.10.7.4.
       FieldDescriptor field(heap->multiline_symbol(),
                             JSRegExp::kMultilineFieldIndex,
                             final,
-                            enum_index++);
-      descriptors->Set(3, &field, witness);
+                            index + 1);
+      descriptors->Set(index, &field, witness);
+      ++index;
     }
     {
       // ECMA-262, section 15.10.7.5.
@@ -990,10 +1011,9 @@
       FieldDescriptor field(heap->last_index_symbol(),
                             JSRegExp::kLastIndexFieldIndex,
                             writable,
-                            enum_index++);
-      descriptors->Set(4, &field, witness);
+                            index + 1);
+      descriptors->Set(index, &field, witness);
     }
-    descriptors->SetNextEnumerationIndex(enum_index);
     descriptors->Sort(witness);
 
     initial_map->set_inobject_properties(5);
@@ -1138,17 +1158,26 @@
     // Create the descriptor array for the arguments object.
     Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3);
     DescriptorArray::WhitenessWitness witness(*descriptors);
+    int index = 0;
     {  // length
-      FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM);
-      descriptors->Set(0, &d, witness);
+      FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM, index + 1);
+      descriptors->Set(index, &d, witness);
+      ++index;
     }
     {  // callee
-      CallbacksDescriptor d(*factory->callee_symbol(), *callee, attributes);
-      descriptors->Set(1, &d, witness);
+      CallbacksDescriptor d(*factory->callee_symbol(),
+                            *callee,
+                            attributes,
+                            index + 1);
+      descriptors->Set(index, &d, witness);
+      ++index;
     }
     {  // caller
-      CallbacksDescriptor d(*factory->caller_symbol(), *caller, attributes);
-      descriptors->Set(2, &d, witness);
+      CallbacksDescriptor d(*factory->caller_symbol(),
+                            *caller,
+                            attributes,
+                            index + 1);
+      descriptors->Set(index, &d, witness);
     }
     descriptors->Sort(witness);
 
@@ -1741,26 +1770,27 @@
     JSFunction* array_function = global_context()->array_function();
     Handle<DescriptorArray> array_descriptors(
         array_function->initial_map()->instance_descriptors());
-    int index = array_descriptors->SearchWithCache(heap()->length_symbol());
+    int old = array_descriptors->SearchWithCache(heap()->length_symbol());
     MaybeObject* copy_result =
-        reresult_descriptors->CopyFrom(0, *array_descriptors, index, witness);
+        reresult_descriptors->CopyFrom(0, *array_descriptors, old, witness);
     if (copy_result->IsFailure()) return false;
 
-    int enum_index = 0;
+    int index = 1;
     {
       FieldDescriptor index_field(heap()->index_symbol(),
                                   JSRegExpResult::kIndexIndex,
                                   NONE,
-                                  enum_index++);
-      reresult_descriptors->Set(1, &index_field, witness);
+                                  index + 1);
+      reresult_descriptors->Set(index, &index_field, witness);
+      ++index;
     }
 
     {
       FieldDescriptor input_field(heap()->input_symbol(),
                                   JSRegExpResult::kInputIndex,
                                   NONE,
-                                  enum_index++);
-      reresult_descriptors->Set(2, &input_field, witness);
+                                  index + 1);
+      reresult_descriptors->Set(index, &input_field, witness);
     }
     reresult_descriptors->Sort(witness);
 
diff --git a/src/factory.cc b/src/factory.cc
index e7c612b..fa609e0 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -465,14 +465,15 @@
 }
 
 
-Handle<Map> Factory::CopyMapDropDescriptors(Handle<Map> src) {
-  CALL_HEAP_FUNCTION(isolate(), src->CopyDropDescriptors(), Map);
+Handle<Map> Factory::CopyWithPreallocatedFieldDescriptors(Handle<Map> src) {
+  CALL_HEAP_FUNCTION(
+      isolate(), src->CopyWithPreallocatedFieldDescriptors(), Map);
 }
 
 
 Handle<Map> Factory::CopyMap(Handle<Map> src,
                              int extra_inobject_properties) {
-  Handle<Map> copy = CopyMapDropDescriptors(src);
+  Handle<Map> copy = CopyWithPreallocatedFieldDescriptors(src);
   // Check that we do not overflow the instance size when adding the
   // extra inobject properties.
   int instance_size_delta = extra_inobject_properties * kPointerSize;
@@ -892,7 +893,7 @@
     String* key,
     Object* value,
     PropertyAttributes attributes) {
-  CallbacksDescriptor desc(key, value, attributes);
+  CallbacksDescriptor desc(key, value, attributes, 0);
   MaybeObject* obj = array->CopyInsert(&desc);
   return obj;
 }
@@ -936,6 +937,8 @@
   // Fill in new callback descriptors.  Process the callbacks from
   // back to front so that the last callback with a given name takes
   // precedence over previously added callbacks with that name.
+  int added_descriptor_count = descriptor_count;
+  int next_enum = array->NextEnumerationIndex();
   for (int i = nof_callbacks - 1; i >= 0; i--) {
     Handle<AccessorInfo> entry =
         Handle<AccessorInfo>(AccessorInfo::cast(callbacks.get(i)));
@@ -943,19 +946,26 @@
     Handle<String> key =
         SymbolFromString(Handle<String>(String::cast(entry->name())));
     // Check if a descriptor with this name already exists before writing.
-    if (LinearSearch(*result, EXPECT_UNSORTED, *key, descriptor_count) ==
+    if (LinearSearch(*result, EXPECT_UNSORTED, *key, added_descriptor_count) ==
         DescriptorArray::kNotFound) {
-      CallbacksDescriptor desc(*key, *entry, entry->property_attributes());
-      result->Set(descriptor_count, &desc, witness);
-      descriptor_count++;
+      CallbacksDescriptor desc(*key,
+                               *entry,
+                               entry->property_attributes(),
+                               next_enum++);
+      result->Set(added_descriptor_count, &desc, witness);
+      added_descriptor_count++;
     }
   }
 
+  // Return the old descriptor array if there were no new elements.
+  if (added_descriptor_count == descriptor_count) return array;
+
   // If duplicates were detected, allocate a result of the right size
   // and transfer the elements.
-  if (descriptor_count < result->length()) {
-    Handle<DescriptorArray> new_result = NewDescriptorArray(descriptor_count);
-    for (int i = 0; i < descriptor_count; i++) {
+  if (added_descriptor_count < result->length()) {
+    Handle<DescriptorArray> new_result =
+        NewDescriptorArray(added_descriptor_count);
+    for (int i = 0; i < added_descriptor_count; i++) {
       DescriptorArray::CopyFrom(new_result, i, result, i, witness);
     }
     result = new_result;
@@ -963,6 +973,7 @@
 
   // Sort the result before returning.
   result->Sort(witness);
+  ASSERT(result->NextEnumerationIndex() == next_enum);
   return result;
 }
 
diff --git a/src/factory.h b/src/factory.h
index 0485fdd..f170700 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -222,7 +222,7 @@
 
   Handle<JSObject> NewFunctionPrototype(Handle<JSFunction> function);
 
-  Handle<Map> CopyMapDropDescriptors(Handle<Map> map);
+  Handle<Map> CopyWithPreallocatedFieldDescriptors(Handle<Map> map);
 
   // Copy the map adding more inobject properties if possible without
   // overflowing the instance size.
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 607b0c3..1c4f914 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -134,7 +134,7 @@
 DEFINE_bool(use_strict, false, "enforce strict mode")
 DEFINE_bool(es5_readonly, false,
             "activate correct semantics for inheriting readonliness")
-DEFINE_bool(es52_globals, false,
+DEFINE_bool(es52_globals, true,
             "activate new semantics for global var declarations")
 
 DEFINE_bool(harmony_typeof, false, "enable harmony semantics for typeof")
diff --git a/src/heap.cc b/src/heap.cc
index 1b4ec81..a448292 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -320,52 +320,52 @@
 
 void Heap::PrintShortHeapStatistics() {
   if (!FLAG_trace_gc_verbose) return;
-  PrintF("Memory allocator,   used: %6" V8_PTR_PREFIX "d KB"
-             ", available: %6" V8_PTR_PREFIX "d KB\n",
-         isolate_->memory_allocator()->Size() / KB,
-         isolate_->memory_allocator()->Available() / KB);
-  PrintF("New space,          used: %6" V8_PTR_PREFIX "d KB"
-             ", available: %6" V8_PTR_PREFIX "d KB"
-             ", committed: %6" V8_PTR_PREFIX "d KB\n",
-         new_space_.Size() / KB,
-         new_space_.Available() / KB,
-         new_space_.CommittedMemory() / KB);
-  PrintF("Old pointers,       used: %6" V8_PTR_PREFIX "d KB"
-             ", available: %6" V8_PTR_PREFIX "d KB"
-             ", committed: %6" V8_PTR_PREFIX "d KB\n",
-         old_pointer_space_->SizeOfObjects() / KB,
-         old_pointer_space_->Available() / KB,
-         old_pointer_space_->CommittedMemory() / KB);
-  PrintF("Old data space,     used: %6" V8_PTR_PREFIX "d KB"
-             ", available: %6" V8_PTR_PREFIX "d KB"
-             ", committed: %6" V8_PTR_PREFIX "d KB\n",
-         old_data_space_->SizeOfObjects() / KB,
-         old_data_space_->Available() / KB,
-         old_data_space_->CommittedMemory() / KB);
-  PrintF("Code space,         used: %6" V8_PTR_PREFIX "d KB"
-             ", available: %6" V8_PTR_PREFIX "d KB"
-             ", committed: %6" V8_PTR_PREFIX "d KB\n",
-         code_space_->SizeOfObjects() / KB,
-         code_space_->Available() / KB,
-         code_space_->CommittedMemory() / KB);
-  PrintF("Map space,          used: %6" V8_PTR_PREFIX "d KB"
-             ", available: %6" V8_PTR_PREFIX "d KB"
-             ", committed: %6" V8_PTR_PREFIX "d KB\n",
-         map_space_->SizeOfObjects() / KB,
-         map_space_->Available() / KB,
-         map_space_->CommittedMemory() / KB);
-  PrintF("Cell space,         used: %6" V8_PTR_PREFIX "d KB"
-             ", available: %6" V8_PTR_PREFIX "d KB"
-             ", committed: %6" V8_PTR_PREFIX "d KB\n",
-         cell_space_->SizeOfObjects() / KB,
-         cell_space_->Available() / KB,
-         cell_space_->CommittedMemory() / KB);
-  PrintF("Large object space, used: %6" V8_PTR_PREFIX "d KB"
-             ", available: %6" V8_PTR_PREFIX "d KB"
-             ", committed: %6" V8_PTR_PREFIX "d KB\n",
-         lo_space_->SizeOfObjects() / KB,
-         lo_space_->Available() / KB,
-         lo_space_->CommittedMemory() / KB);
+  PrintPID("Memory allocator,   used: %6" V8_PTR_PREFIX "d KB"
+               ", available: %6" V8_PTR_PREFIX "d KB\n",
+           isolate_->memory_allocator()->Size() / KB,
+           isolate_->memory_allocator()->Available() / KB);
+  PrintPID("New space,          used: %6" V8_PTR_PREFIX "d KB"
+               ", available: %6" V8_PTR_PREFIX "d KB"
+               ", committed: %6" V8_PTR_PREFIX "d KB\n",
+           new_space_.Size() / KB,
+           new_space_.Available() / KB,
+           new_space_.CommittedMemory() / KB);
+  PrintPID("Old pointers,       used: %6" V8_PTR_PREFIX "d KB"
+               ", available: %6" V8_PTR_PREFIX "d KB"
+               ", committed: %6" V8_PTR_PREFIX "d KB\n",
+           old_pointer_space_->SizeOfObjects() / KB,
+           old_pointer_space_->Available() / KB,
+           old_pointer_space_->CommittedMemory() / KB);
+  PrintPID("Old data space,     used: %6" V8_PTR_PREFIX "d KB"
+               ", available: %6" V8_PTR_PREFIX "d KB"
+               ", committed: %6" V8_PTR_PREFIX "d KB\n",
+           old_data_space_->SizeOfObjects() / KB,
+           old_data_space_->Available() / KB,
+           old_data_space_->CommittedMemory() / KB);
+  PrintPID("Code space,         used: %6" V8_PTR_PREFIX "d KB"
+               ", available: %6" V8_PTR_PREFIX "d KB"
+               ", committed: %6" V8_PTR_PREFIX "d KB\n",
+           code_space_->SizeOfObjects() / KB,
+           code_space_->Available() / KB,
+           code_space_->CommittedMemory() / KB);
+  PrintPID("Map space,          used: %6" V8_PTR_PREFIX "d KB"
+               ", available: %6" V8_PTR_PREFIX "d KB"
+               ", committed: %6" V8_PTR_PREFIX "d KB\n",
+           map_space_->SizeOfObjects() / KB,
+           map_space_->Available() / KB,
+           map_space_->CommittedMemory() / KB);
+  PrintPID("Cell space,         used: %6" V8_PTR_PREFIX "d KB"
+               ", available: %6" V8_PTR_PREFIX "d KB"
+               ", committed: %6" V8_PTR_PREFIX "d KB\n",
+           cell_space_->SizeOfObjects() / KB,
+           cell_space_->Available() / KB,
+           cell_space_->CommittedMemory() / KB);
+  PrintPID("Large object space, used: %6" V8_PTR_PREFIX "d KB"
+               ", available: %6" V8_PTR_PREFIX "d KB"
+               ", committed: %6" V8_PTR_PREFIX "d KB\n",
+           lo_space_->SizeOfObjects() / KB,
+           lo_space_->Available() / KB,
+           lo_space_->CommittedMemory() / KB);
 }
 
 
@@ -906,8 +906,8 @@
     // have to limit maximal capacity of the young generation.
     new_space_high_promotion_mode_active_ = true;
     if (FLAG_trace_gc) {
-      PrintF("Limited new space size due to high promotion rate: %d MB\n",
-             new_space_.InitialCapacity() / MB);
+      PrintPID("Limited new space size due to high promotion rate: %d MB\n",
+               new_space_.InitialCapacity() / MB);
     }
   } else if (new_space_high_promotion_mode_active_ &&
       IsStableOrDecreasingSurvivalTrend() &&
@@ -917,8 +917,8 @@
     // to grow again.
     new_space_high_promotion_mode_active_ = false;
     if (FLAG_trace_gc) {
-      PrintF("Unlimited new space size due to low promotion rate: %d MB\n",
-             new_space_.MaximumCapacity() / MB);
+      PrintPID("Unlimited new space size due to low promotion rate: %d MB\n",
+               new_space_.MaximumCapacity() / MB);
     }
   }
 
@@ -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());
 
@@ -3885,11 +3883,9 @@
       for (int i = 0; i < count; i++) {
         String* name = fun->shared()->GetThisPropertyAssignmentName(i);
         ASSERT(name->IsSymbol());
-        FieldDescriptor field(name, i, NONE);
-        field.SetEnumerationIndex(i);
+        FieldDescriptor field(name, i, NONE, i + 1);
         descriptors->Set(i, &field, witness);
       }
-      descriptors->SetNextEnumerationIndex(count);
       descriptors->SortUnchecked(witness);
 
       // The descriptors may contain duplicates because the compiler does not
@@ -4184,14 +4180,13 @@
   InitializeJSObjectFromMap(global, dictionary, map);
 
   // Create a new map for the global object.
-  { MaybeObject* maybe_obj = map->CopyDropDescriptors();
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+  Map* new_map;
+  { MaybeObject* maybe_map = map->CopyDropDescriptors();
+    if (!maybe_map->To(&new_map)) return maybe_map;
   }
-  Map* new_map = Map::cast(obj);
 
   // 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.
@@ -5809,8 +5804,8 @@
     if (max_semispace_size < Page::kPageSize) {
       max_semispace_size = Page::kPageSize;
       if (FLAG_trace_gc) {
-        PrintF("Max semispace size cannot be less than %dkbytes\n",
-               Page::kPageSize >> 10);
+        PrintPID("Max semispace size cannot be less than %dkbytes\n",
+                 Page::kPageSize >> 10);
       }
     }
     max_semispace_size_ = max_semispace_size;
@@ -5825,8 +5820,8 @@
     if (max_semispace_size_ > reserved_semispace_size_) {
       max_semispace_size_ = reserved_semispace_size_;
       if (FLAG_trace_gc) {
-        PrintF("Max semispace size cannot be more than %dkbytes\n",
-               reserved_semispace_size_ >> 10);
+        PrintPID("Max semispace size cannot be more than %dkbytes\n",
+                 reserved_semispace_size_ >> 10);
       }
     }
   } else {
@@ -6920,7 +6915,7 @@
     }
   }
 
-  PrintF("%8.0f ms: ", heap_->isolate()->time_millis_since_init());
+  PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init());
 
   if (!FLAG_trace_gc_nvp) {
     int external_time = static_cast<int>(scopes_[Scope::EXTERNAL]);
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 283e484..d76c1d7 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1385,41 +1385,78 @@
 }
 
 
+static bool IsInteger32(double value) {
+  double roundtrip_value = static_cast<double>(static_cast<int32_t>(value));
+  return BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(value);
+}
+
+
 HConstant::HConstant(Handle<Object> handle, Representation r)
     : handle_(handle),
       has_int32_value_(false),
-      has_double_value_(false),
-      int32_value_(0),
-      double_value_(0)  {
+      has_double_value_(false) {
   set_representation(r);
   SetFlag(kUseGVN);
   if (handle_->IsNumber()) {
     double n = handle_->Number();
-    double roundtrip_value = static_cast<double>(static_cast<int32_t>(n));
-    has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n);
-    if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
+    has_int32_value_ = IsInteger32(n);
+    int32_value_ = DoubleToInt32(n);
     double_value_ = n;
     has_double_value_ = true;
   }
 }
 
 
+HConstant::HConstant(int32_t integer_value, Representation r)
+    : has_int32_value_(true),
+      has_double_value_(true),
+      int32_value_(integer_value),
+      double_value_(FastI2D(integer_value)) {
+  set_representation(r);
+  SetFlag(kUseGVN);
+}
+
+
+HConstant::HConstant(double double_value, Representation r)
+    : has_int32_value_(IsInteger32(double_value)),
+      has_double_value_(true),
+      int32_value_(DoubleToInt32(double_value)),
+      double_value_(double_value) {
+  set_representation(r);
+  SetFlag(kUseGVN);
+}
+
+
 HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
   if (r.IsInteger32() && !has_int32_value_) return NULL;
   if (r.IsDouble() && !has_double_value_) return NULL;
+  if (handle_.is_null()) {
+    ASSERT(has_int32_value_ || has_double_value_);
+    if (has_int32_value_) return new(zone) HConstant(int32_value_, r);
+    return new(zone) HConstant(double_value_, r);
+  }
   return new(zone) HConstant(handle_, r);
 }
 
 
 HConstant* HConstant::CopyToTruncatedInt32(Zone* zone) const {
-  if (!has_double_value_) return NULL;
-  int32_t truncated = NumberToInt32(*handle_);
-  return new(zone) HConstant(FACTORY->NewNumberFromInt(truncated),
-                             Representation::Integer32());
+  if (has_int32_value_) {
+    if (handle_.is_null()) {
+      return new(zone) HConstant(int32_value_, Representation::Integer32());
+    } else {
+      // Re-use the existing Handle if possible.
+      return new(zone) HConstant(handle_, Representation::Integer32());
+    }
+  } else if (has_double_value_) {
+    return new(zone) HConstant(DoubleToInt32(double_value_),
+                               Representation::Integer32());
+  } else {
+    return NULL;
+  }
 }
 
 
-bool HConstant::ToBoolean() const {
+bool HConstant::ToBoolean() {
   // Converts the constant's boolean value according to
   // ECMAScript section 9.2 ToBoolean conversion.
   if (HasInteger32Value()) return Integer32Value() != 0;
@@ -1427,17 +1464,25 @@
     double v = DoubleValue();
     return v != 0 && !isnan(v);
   }
-  if (handle()->IsTrue()) return true;
-  if (handle()->IsFalse()) return false;
-  if (handle()->IsUndefined()) return false;
-  if (handle()->IsNull()) return false;
-  if (handle()->IsString() &&
-      String::cast(*handle())->length() == 0) return false;
+  Handle<Object> literal = handle();
+  if (literal->IsTrue()) return true;
+  if (literal->IsFalse()) return false;
+  if (literal->IsUndefined()) return false;
+  if (literal->IsNull()) return false;
+  if (literal->IsString() && String::cast(*literal)->length() == 0) {
+    return false;
+  }
   return true;
 }
 
 void HConstant::PrintDataTo(StringStream* stream) {
-  handle()->ShortPrint(stream);
+  if (has_int32_value_) {
+    stream->Add("%d ", int32_value_);
+  } else if (has_double_value_) {
+    stream->Add("%lf ", FmtElm(double_value_));
+  } else {
+    handle()->ShortPrint(stream);
+  }
 }
 
 
@@ -2089,6 +2134,10 @@
 
 
 HType HConstant::CalculateInferredType() {
+  if (has_int32_value_) {
+    return Smi::IsValid(int32_value_) ? HType::Smi() : HType::HeapNumber();
+  }
+  if (has_double_value_) return HType::HeapNumber();
   return HType::TypeFromValue(handle_);
 }
 
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index fb6fe29..875b631 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -2453,20 +2453,42 @@
 class HConstant: public HTemplateInstruction<0> {
  public:
   HConstant(Handle<Object> handle, Representation r);
+  HConstant(int32_t value, Representation r);
+  HConstant(double value, Representation r);
 
-  Handle<Object> handle() const { return handle_; }
+  Handle<Object> handle() {
+    if (handle_.is_null()) {
+      handle_ = FACTORY->NewNumber(double_value_, TENURED);
+    }
+    ASSERT(has_int32_value_ || !handle_->IsSmi());
+    return handle_;
+  }
 
   bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
 
   bool ImmortalImmovable() const {
+    if (has_int32_value_) {
+      return false;
+    }
+    if (has_double_value_) {
+      if (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
+          isnan(double_value_)) {
+        return true;
+      }
+      return false;
+    }
+
+    ASSERT(!handle_.is_null());
     Heap* heap = HEAP;
+    // We should have handled minus_zero_value and nan_value in the
+    // has_double_value_ clause above.
+    ASSERT(*handle_ != heap->minus_zero_value());
+    ASSERT(*handle_ != heap->nan_value());
     if (*handle_ == heap->undefined_value()) return true;
     if (*handle_ == heap->null_value()) return true;
     if (*handle_ == heap->true_value()) return true;
     if (*handle_ == heap->false_value()) return true;
     if (*handle_ == heap->the_hole_value()) return true;
-    if (*handle_ == heap->minus_zero_value()) return true;
-    if (*handle_ == heap->nan_value()) return true;
     if (*handle_ == heap->empty_string()) return true;
     return false;
   }
@@ -2476,18 +2498,14 @@
   }
 
   virtual bool IsConvertibleToInteger() const {
-    if (handle_->IsSmi()) return true;
-    if (handle_->IsHeapNumber() &&
-        (HeapNumber::cast(*handle_)->value() ==
-         static_cast<double>(NumberToInt32(*handle_)))) return true;
-    return false;
+    return has_int32_value_;
   }
 
   virtual bool EmitAtUses() { return !representation().IsDouble(); }
   virtual HValue* Canonicalize();
   virtual void PrintDataTo(StringStream* stream);
   virtual HType CalculateInferredType();
-  bool IsInteger() const { return handle_->IsSmi(); }
+  bool IsInteger() { return handle()->IsSmi(); }
   HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
   HConstant* CopyToTruncatedInt32(Zone* zone) const;
   bool HasInteger32Value() const { return has_int32_value_; }
@@ -2500,24 +2518,31 @@
     ASSERT(HasDoubleValue());
     return double_value_;
   }
-  bool HasNumberValue() const { return has_int32_value_ || has_double_value_; }
+  bool HasNumberValue() const { return has_double_value_; }
   int32_t NumberValueAsInteger32() const {
     ASSERT(HasNumberValue());
-    if (has_int32_value_) return int32_value_;
-    return DoubleToInt32(double_value_);
+    // Irrespective of whether a numeric HConstant can be safely
+    // represented as an int32, we store the (in some cases lossy)
+    // representation of the number in int32_value_.
+    return int32_value_;
   }
-  bool HasStringValue() const { return handle_->IsString(); }
 
-  bool ToBoolean() const;
+  bool ToBoolean();
 
   virtual intptr_t Hashcode() {
     ASSERT(!HEAP->allow_allocation(false));
-    intptr_t hash = reinterpret_cast<intptr_t>(*handle());
-    // Prevent smis from having fewer hash values when truncated to
-    // the least significant bits.
-    const int kShiftSize = kSmiShiftSize + kSmiTagSize;
-    STATIC_ASSERT(kShiftSize != 0);
-    return hash ^ (hash >> kShiftSize);
+    intptr_t hash;
+
+    if (has_int32_value_) {
+      hash = static_cast<intptr_t>(int32_value_);
+    } else if (has_double_value_) {
+      hash = static_cast<intptr_t>(BitCast<int64_t>(double_value_));
+    } else {
+      ASSERT(!handle_.is_null());
+      hash = reinterpret_cast<intptr_t>(*handle_);
+    }
+
+    return hash;
   }
 
 #ifdef DEBUG
@@ -2531,15 +2556,32 @@
 
   virtual bool DataEquals(HValue* other) {
     HConstant* other_constant = HConstant::cast(other);
-    return handle().is_identical_to(other_constant->handle());
+    if (has_int32_value_) {
+      return other_constant->has_int32_value_ &&
+          int32_value_ == other_constant->int32_value_;
+    } else if (has_double_value_) {
+      return other_constant->has_double_value_ &&
+          BitCast<int64_t>(double_value_) ==
+          BitCast<int64_t>(other_constant->double_value_);
+    } else {
+      ASSERT(!handle_.is_null());
+      return !other_constant->handle_.is_null() &&
+          *handle_ == *other_constant->handle_;
+    }
   }
 
  private:
+  // If this is a numerical constant, handle_ either points to to the
+  // HeapObject the constant originated from or is null.  If the
+  // constant is non-numeric, handle_ always points to a valid
+  // constant HeapObject.
   Handle<Object> handle_;
 
-  // The following two values represent the int32 and the double value of the
-  // given constant if there is a lossless conversion between the constant
-  // and the specific representation.
+  // We store the HConstant in the most specific form safely possible.
+  // The two flags, has_int32_value_ and has_double_value_ tell us if
+  // int32_value_ and double_value_ hold valid, safe representations
+  // of the constant.  has_int32_value_ implies has_double_value_ but
+  // not the converse.
   bool has_int32_value_ : 1;
   bool has_double_value_ : 1;
   int32_t int32_value_;
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 3ce76c1..2ba79b9 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -579,13 +579,25 @@
 }
 
 
+HConstant* HGraph::GetConstantInt32(SetOncePointer<HConstant>* pointer,
+                                    int32_t value) {
+  if (!pointer->is_set()) {
+    HConstant* constant =
+        new(zone()) HConstant(value, Representation::Integer32());
+    constant->InsertAfter(GetConstantUndefined());
+    pointer->set(constant);
+  }
+  return pointer->get();
+}
+
+
 HConstant* HGraph::GetConstant1() {
-  return GetConstant(&constant_1_, Handle<Smi>(Smi::FromInt(1)));
+  return GetConstantInt32(&constant_1_, 1);
 }
 
 
 HConstant* HGraph::GetConstantMinus1() {
-  return GetConstant(&constant_minus1_, Handle<Smi>(Smi::FromInt(-1)));
+  return GetConstantInt32(&constant_minus1_, -1);
 }
 
 
@@ -3378,8 +3390,7 @@
                       Representation representation,
                       int32_t new_offset) {
     HConstant* new_constant = new(BasicBlock()->zone())
-        HConstant(Handle<Object>(Smi::FromInt(new_offset)),
-                  Representation::Integer32());
+       HConstant(new_offset, Representation::Integer32());
     if (*add == NULL) {
       new_constant->InsertBefore(check);
       *add = new(BasicBlock()->zone()) HAdd(NULL,
@@ -4792,7 +4803,10 @@
             CHECK_ALIVE(VisitForValue(value));
             HValue* value = Pop();
             HInstruction* store;
-            CHECK_ALIVE(store = BuildStoreNamed(literal, value, property));
+            CHECK_ALIVE(store = BuildStoreNamed(literal,
+                                                value,
+                                                property->GetReceiverType(),
+                                                property->key()));
             AddInstruction(store);
             if (store->HasObservableSideEffects()) AddSimulate(key->id());
           } else {
@@ -5030,14 +5044,13 @@
 
 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
                                              HValue* value,
-                                             ObjectLiteral::Property* prop) {
-  Literal* key = prop->key()->AsLiteral();
-  Handle<String> name = Handle<String>::cast(key->handle());
+                                             Handle<Map> type,
+                                             Expression* key) {
+  Handle<String> name = Handle<String>::cast(key->AsLiteral()->handle());
   ASSERT(!name.is_null());
 
   LookupResult lookup(isolate());
-  Handle<Map> type = prop->GetReceiverType();
-  bool is_monomorphic = prop->IsMonomorphic() &&
+  bool is_monomorphic = !type.is_null() &&
       ComputeLoadStoreField(type, name, &lookup, true);
 
   return is_monomorphic
@@ -5047,28 +5060,6 @@
 }
 
 
-HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
-                                             HValue* value,
-                                             Expression* expr) {
-  Property* prop = (expr->AsProperty() != NULL)
-      ? expr->AsProperty()
-      : expr->AsAssignment()->target()->AsProperty();
-  Literal* key = prop->key()->AsLiteral();
-  Handle<String> name = Handle<String>::cast(key->handle());
-  ASSERT(!name.is_null());
-
-  LookupResult lookup(isolate());
-  SmallMapList* types = expr->GetReceiverTypes();
-  bool is_monomorphic = expr->IsMonomorphic() &&
-      ComputeLoadStoreField(types->first(), name, &lookup, true);
-
-  return is_monomorphic
-      ? BuildStoreNamedField(object, name, value, types->first(), &lookup,
-                             true)  // Needs smi and map check.
-      : BuildStoreNamedGeneric(object, name, value);
-}
-
-
 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
                                                     HValue* object,
                                                     SmallMapList* types,
@@ -5220,7 +5211,10 @@
 
     SmallMapList* types = expr->GetReceiverTypes();
     if (expr->IsMonomorphic()) {
-      CHECK_ALIVE(instr = BuildStoreNamed(object, value, expr));
+      CHECK_ALIVE(instr = BuildStoreNamed(object,
+                                          value,
+                                          types->first(),
+                                          prop->key()));
 
     } else if (types != NULL && types->length() > 1) {
       HandlePolymorphicStoreNamedField(expr, object, value, types, name);
@@ -5380,10 +5374,11 @@
       CHECK_ALIVE(VisitForValue(prop->obj()));
       HValue* obj = Top();
 
-      HInstruction* load = NULL;
+      Handle<Map> map;
+      HInstruction* load;
       if (prop->IsMonomorphic()) {
         Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
-        Handle<Map> map = prop->GetReceiverTypes()->first();
+        map = prop->GetReceiverTypes()->first();
         load = BuildLoadNamed(obj, prop, map, name);
       } else {
         load = BuildLoadNamedGeneric(obj, prop);
@@ -5400,7 +5395,7 @@
       if (instr->HasObservableSideEffects()) AddSimulate(operation->id());
 
       HInstruction* store;
-      CHECK_ALIVE(store = BuildStoreNamed(obj, instr, prop));
+      CHECK_ALIVE(store = BuildStoreNamed(obj, instr, map, prop->key()));
       AddInstruction(store);
       // Drop the simulated receiver and value.  Return the value.
       Drop(2);
@@ -5642,6 +5637,7 @@
                                LookupResult* lookup) {
   while (map->prototype()->IsJSObject()) {
     Handle<JSObject> holder(JSObject::cast(map->prototype()));
+    if (!holder->HasFastProperties()) break;
     map = Handle<Map>(holder->map());
     map->LookupDescriptor(*holder, *name, lookup);
     if (lookup->IsFound()) return;
@@ -7786,10 +7782,11 @@
       CHECK_ALIVE(VisitForValue(prop->obj()));
       HValue* obj = Top();
 
-      HInstruction* load = NULL;
+      Handle<Map> map;
+      HInstruction* load;
       if (prop->IsMonomorphic()) {
         Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
-        Handle<Map> map = prop->GetReceiverTypes()->first();
+        map = prop->GetReceiverTypes()->first();
         load = BuildLoadNamed(obj, prop, map, name);
       } else {
         load = BuildLoadNamedGeneric(obj, prop);
@@ -7801,7 +7798,7 @@
       input = Pop();
 
       HInstruction* store;
-      CHECK_ALIVE(store = BuildStoreNamed(obj, after, prop));
+      CHECK_ALIVE(store = BuildStoreNamed(obj, after, map, prop->key()));
       AddInstruction(store);
 
       // Overwrite the receiver in the bailout environment with the result
@@ -7923,8 +7920,8 @@
   // for a smi operation. If one of the operands is a constant string
   // do not generate code assuming it is a smi operation.
   if (info.IsSmi() &&
-      ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
-       (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
+      ((left->IsConstant() && HConstant::cast(left)->handle()->IsString()) ||
+       (right->IsConstant() && HConstant::cast(right)->handle()->IsString()))) {
     return instr;
   }
   Representation rep = ToRepresentation(info);
@@ -8142,7 +8139,7 @@
   if (left->IsTypeof() &&
       Token::IsEqualityOp(op) &&
       right->IsConstant() &&
-      HConstant::cast(right)->HasStringValue()) {
+      HConstant::cast(right)->handle()->IsString()) {
     *typeof_expr = HTypeof::cast(left);
     *check = Handle<String>::cast(HConstant::cast(right)->handle());
     return true;
@@ -9266,7 +9263,7 @@
 }
 
 
-void HTracer::TraceLithium(const char* name, LChunk* chunk) {
+void HTracer::TraceLithium(const char* name, LChunkBase* chunk) {
   Trace(name, chunk->graph(), chunk);
 }
 
@@ -9276,7 +9273,7 @@
 }
 
 
-void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
+void HTracer::Trace(const char* name, HGraph* graph, LChunkBase* chunk) {
   Tag tag(this, "cfg");
   PrintStringProperty("name", name);
   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
@@ -9538,7 +9535,7 @@
 
 void HPhase::Begin(const char* name,
                    HGraph* graph,
-                   LChunk* chunk,
+                   LChunkBase* chunk,
                    LAllocator* allocator) {
   name_ = name;
   graph_ = graph;
diff --git a/src/hydrogen.h b/src/hydrogen.h
index ac19db7..93873b1 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -48,7 +48,7 @@
 class HLoopInformation;
 class HTracer;
 class LAllocator;
-class LChunk;
+class LChunkBase;
 class LiveRange;
 
 
@@ -348,6 +348,8 @@
  private:
   HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
                          Handle<Object> value);
+  HConstant* GetConstantInt32(SetOncePointer<HConstant>* pointer,
+                              int32_t integer_value);
 
   void MarkAsDeoptimizingRecursively(HBasicBlock* block);
   void InsertTypeConversions(HInstruction* instr);
@@ -1149,10 +1151,8 @@
                                Handle<String> name);
   HInstruction* BuildStoreNamed(HValue* object,
                                 HValue* value,
-                                Expression* expr);
-  HInstruction* BuildStoreNamed(HValue* object,
-                                HValue* value,
-                                ObjectLiteral::Property* prop);
+                                Handle<Map> type,
+                                Expression* key);
   HInstruction* BuildStoreNamedField(HValue* object,
                                      Handle<String> name,
                                      HValue* value,
@@ -1336,7 +1336,7 @@
   HPhase(const char* name, HGraph* graph) {
     Begin(name, graph, NULL, NULL);
   }
-  HPhase(const char* name, LChunk* chunk) {
+  HPhase(const char* name, LChunkBase* chunk) {
     Begin(name, NULL, chunk, NULL);
   }
   HPhase(const char* name, LAllocator* allocator) {
@@ -1350,14 +1350,14 @@
  private:
   void Begin(const char* name,
              HGraph* graph,
-             LChunk* chunk,
+             LChunkBase* chunk,
              LAllocator* allocator);
   void End() const;
 
   int64_t start_;
   const char* name_;
   HGraph* graph_;
-  LChunk* chunk_;
+  LChunkBase* chunk_;
   LAllocator* allocator_;
   unsigned start_allocation_size_;
 };
@@ -1367,7 +1367,7 @@
  public:
   void TraceCompilation(FunctionLiteral* function);
   void TraceHydrogen(const char* name, HGraph* graph);
-  void TraceLithium(const char* name, LChunk* chunk);
+  void TraceLithium(const char* name, LChunkBase* chunk);
   void TraceLiveRanges(const char* name, LAllocator* allocator);
 
   static HTracer* Instance() {
@@ -1408,7 +1408,7 @@
   }
 
   void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
-  void Trace(const char* name, HGraph* graph, LChunk* chunk);
+  void Trace(const char* name, HGraph* graph, LChunkBase* chunk);
   void FlushToFile();
 
   void PrintEmptyProperty(const char* name) {
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 1a9aea2..2867d5e 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1092,7 +1092,7 @@
   // We got a map in register eax. Get the enumeration cache from it.
   __ bind(&use_cache);
   __ LoadInstanceDescriptors(eax, ecx);
-  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset));
+  __ mov(ecx, FieldOperand(ecx, DescriptorArray::kLastAddedOffset));
   __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
 
   // Set up the four remaining stack slots.
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index b307512..6317a54 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -360,24 +360,24 @@
 
 
 int LCodeGen::ToInteger32(LConstantOperand* op) const {
-  Handle<Object> value = chunk_->LookupLiteral(op);
+  HConstant* constant = chunk_->LookupConstant(op);
   ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
-  ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
-      value->Number());
-  return static_cast<int32_t>(value->Number());
+  ASSERT(constant->HasInteger32Value());
+  return constant->Integer32Value();
 }
 
 
 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
-  Handle<Object> literal = chunk_->LookupLiteral(op);
+  HConstant* constant = chunk_->LookupConstant(op);
   ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
-  return literal;
+  return constant->handle();
 }
 
 
 double LCodeGen::ToDouble(LConstantOperand* op) const {
-  Handle<Object> value = chunk_->LookupLiteral(op);
-  return value->Number();
+  HConstant* constant = chunk_->LookupConstant(op);
+  ASSERT(constant->HasDoubleValue());
+  return constant->DoubleValue();
 }
 
 
@@ -494,8 +494,8 @@
     XMMRegister reg = ToDoubleRegister(op);
     translation->StoreDoubleRegister(reg);
   } else if (op->IsConstantOperand()) {
-    Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op));
-    int src_index = DefineDeoptimizationLiteral(literal);
+    HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
+    int src_index = DefineDeoptimizationLiteral(constant->handle());
     translation->StoreLiteral(src_index);
   } else {
     UNREACHABLE();
@@ -554,9 +554,9 @@
   } else if (context->IsStackSlot()) {
     __ mov(esi, ToOperand(context));
   } else if (context->IsConstantOperand()) {
-    Handle<Object> literal =
-        chunk_->LookupLiteral(LConstantOperand::cast(context));
-    __ LoadHeapObject(esi, Handle<Context>::cast(literal));
+    HConstant* constant =
+        chunk_->LookupConstant(LConstantOperand::cast(context));
+    __ LoadHeapObject(esi, Handle<Context>::cast(constant->handle()));
   } else {
     UNREACHABLE();
   }
@@ -5293,7 +5293,7 @@
   Register result = ToRegister(instr->result());
   __ LoadInstanceDescriptors(map, result);
   __ mov(result,
-         FieldOperand(result, DescriptorArray::kEnumerationIndexOffset));
+         FieldOperand(result, DescriptorArray::kLastAddedOffset));
   __ mov(result,
          FieldOperand(result, FixedArray::SizeFor(instr->idx())));
   __ test(result, result);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index c671e6d..dcb1671 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -387,42 +387,6 @@
 }
 
 
-void LChunk::MarkEmptyBlocks() {
-  HPhase phase("L_Mark empty blocks", this);
-  for (int i = 0; i < graph()->blocks()->length(); ++i) {
-    HBasicBlock* block = graph()->blocks()->at(i);
-    int first = block->first_instruction_index();
-    int last = block->last_instruction_index();
-    LInstruction* first_instr = instructions()->at(first);
-    LInstruction* last_instr = instructions()->at(last);
-
-    LLabel* label = LLabel::cast(first_instr);
-    if (last_instr->IsGoto()) {
-      LGoto* goto_instr = LGoto::cast(last_instr);
-      if (label->IsRedundant() &&
-          !label->is_loop_header()) {
-        bool can_eliminate = true;
-        for (int i = first + 1; i < last && can_eliminate; ++i) {
-          LInstruction* cur = instructions()->at(i);
-          if (cur->IsGap()) {
-            LGap* gap = LGap::cast(cur);
-            if (!gap->IsRedundant()) {
-              can_eliminate = false;
-            }
-          } else {
-            can_eliminate = false;
-          }
-        }
-
-        if (can_eliminate) {
-          label->set_replacement(GetLabel(goto_instr->block_id()));
-        }
-      }
-    }
-  }
-}
-
-
 void LStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
   stream->Add(".");
@@ -474,81 +438,6 @@
 }
 
 
-void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
-  LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
-  int index = -1;
-  if (instr->IsControl()) {
-    instructions_.Add(gap, zone());
-    index = instructions_.length();
-    instructions_.Add(instr, zone());
-  } else {
-    index = instructions_.length();
-    instructions_.Add(instr, zone());
-    instructions_.Add(gap, zone());
-  }
-  if (instr->HasPointerMap()) {
-    pointer_maps_.Add(instr->pointer_map(), zone());
-    instr->pointer_map()->set_lithium_position(index);
-  }
-}
-
-
-LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
-  return LConstantOperand::Create(constant->id(), zone());
-}
-
-
-int LChunk::GetParameterStackSlot(int index) const {
-  // The receiver is at index 0, the first parameter at index 1, so we
-  // shift all parameter indexes down by the number of parameters, and
-  // make sure they end up negative so they are distinguishable from
-  // spill slots.
-  int result = index - info()->scope()->num_parameters() - 1;
-  ASSERT(result < 0);
-  return result;
-}
-
-// A parameter relative to ebp in the arguments stub.
-int LChunk::ParameterAt(int index) {
-  ASSERT(-1 <= index);  // -1 is the receiver.
-  return (1 + info()->scope()->num_parameters() - index) *
-      kPointerSize;
-}
-
-
-LGap* LChunk::GetGapAt(int index) const {
-  return LGap::cast(instructions_[index]);
-}
-
-
-bool LChunk::IsGapAt(int index) const {
-  return instructions_[index]->IsGap();
-}
-
-
-int LChunk::NearestGapPos(int index) const {
-  while (!IsGapAt(index)) index--;
-  return index;
-}
-
-
-void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
-  GetGapAt(index)->GetOrCreateParallelMove(
-      LGap::START, zone())->AddMove(from, to, zone());
-}
-
-
-Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
-  return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
-}
-
-
-Representation LChunk::LookupLiteralRepresentation(
-    LConstantOperand* operand) const {
-  return graph_->LookupValue(operand->index())->representation();
-}
-
-
 LChunk* LChunkBuilder::Build() {
   ASSERT(is_unused());
   chunk_ = new(zone()) LChunk(info(), graph());
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index bc7ef58..09cb17b 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -2319,74 +2319,19 @@
 
 
 class LChunkBuilder;
-class LChunk: public ZoneObject {
+class LChunk: public LChunkBase {
  public:
   LChunk(CompilationInfo* info, HGraph* graph)
-    : spill_slot_count_(0),
-      num_double_slots_(0),
-      info_(info),
-      graph_(graph),
-      instructions_(32, graph->zone()),
-      pointer_maps_(8, graph->zone()),
-      inlined_closures_(1, graph->zone()) { }
-
-  void AddInstruction(LInstruction* instruction, HBasicBlock* block);
-  LConstantOperand* DefineConstantOperand(HConstant* constant);
-  Handle<Object> LookupLiteral(LConstantOperand* operand) const;
-  Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
+      : LChunkBase(info, graph),
+        num_double_slots_(0) { }
 
   int GetNextSpillIndex(bool is_double);
   LOperand* GetNextSpillSlot(bool is_double);
 
-  int ParameterAt(int index);
-  int GetParameterStackSlot(int index) const;
-  int spill_slot_count() const { return spill_slot_count_; }
   int num_double_slots() const { return num_double_slots_; }
-  CompilationInfo* info() const { return info_; }
-  HGraph* graph() const { return graph_; }
-  const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
-  void AddGapMove(int index, LOperand* from, LOperand* to);
-  LGap* GetGapAt(int index) const;
-  bool IsGapAt(int index) const;
-  int NearestGapPos(int index) const;
-  void MarkEmptyBlocks();
-  const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
-  LLabel* GetLabel(int block_id) const {
-    HBasicBlock* block = graph_->blocks()->at(block_id);
-    int first_instruction = block->first_instruction_index();
-    return LLabel::cast(instructions_[first_instruction]);
-  }
-  int LookupDestination(int block_id) const {
-    LLabel* cur = GetLabel(block_id);
-    while (cur->replacement() != NULL) {
-      cur = cur->replacement();
-    }
-    return cur->block_id();
-  }
-  Label* GetAssemblyLabel(int block_id) const {
-    LLabel* label = GetLabel(block_id);
-    ASSERT(!label->HasReplacement());
-    return label->label();
-  }
-
-  const ZoneList<Handle<JSFunction> >* inlined_closures() const {
-    return &inlined_closures_;
-  }
-
-  void AddInlinedClosure(Handle<JSFunction> closure) {
-    inlined_closures_.Add(closure, zone());
-  }
-
-  Zone* zone() const { return graph_->zone(); }
 
  private:
-  int spill_slot_count_;
   int num_double_slots_;
-  CompilationInfo* info_;
-  HGraph* const graph_;
-  ZoneList<LInstruction*> instructions_;
-  ZoneList<LPointerMap*> pointer_maps_;
-  ZoneList<Handle<JSFunction> > inlined_closures_;
 };
 
 
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 2012a5a..237bfd9 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -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,13 +2892,16 @@
   // 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
   // index field does not contain a smi.
-  mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
+  mov(edx, FieldOperand(edx, DescriptorArray::kLastAddedOffset));
   JumpIfSmi(edx, call_runtime);
 
   // For all objects but the receiver, check that the cache is empty.
diff --git a/src/ic.cc b/src/ic.cc
index bee29f0..d75b3e9 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1518,8 +1518,7 @@
 
       Handle<Map> transition(Map::cast(value));
       DescriptorArray* target_descriptors = transition->instance_descriptors();
-      int descriptor = target_descriptors->SearchWithCache(*name);
-      ASSERT(descriptor != DescriptorArray::kNotFound);
+      int descriptor = target_descriptors->LastAdded();
       PropertyDetails details = target_descriptors->GetDetails(descriptor);
 
       if (details.type() != FIELD || details.attributes() != NONE) return;
@@ -1990,8 +1989,7 @@
 
       Handle<Map> transition(Map::cast(value));
       DescriptorArray* target_descriptors = transition->instance_descriptors();
-      int descriptor = target_descriptors->SearchWithCache(*name);
-      ASSERT(descriptor != DescriptorArray::kNotFound);
+      int descriptor = target_descriptors->LastAdded();
       PropertyDetails details = target_descriptors->GetDetails(descriptor);
 
       if (details.type() == FIELD && details.attributes() == NONE) {
diff --git a/src/incremental-marking-inl.h b/src/incremental-marking-inl.h
index 2dae6f2..5c2c8ab 100644
--- a/src/incremental-marking-inl.h
+++ b/src/incremental-marking-inl.h
@@ -107,7 +107,7 @@
       // trace it.  In this case we switch to non-incremental marking in
       // order to finish off this marking phase.
       if (FLAG_trace_gc) {
-        PrintF("Hurrying incremental marking because of lack of progress\n");
+        PrintPID("Hurrying incremental marking because of lack of progress\n");
       }
       allocation_marking_factor_ = kMaxAllocationMarkingFactor;
     }
diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc
index 94afffa..93fa544 100644
--- a/src/incremental-marking.cc
+++ b/src/incremental-marking.cc
@@ -892,8 +892,8 @@
 
   if ((steps_count_ % kAllocationMarkingFactorSpeedupInterval) == 0) {
     if (FLAG_trace_gc) {
-      PrintF("Speed up marking after %d steps\n",
-             static_cast<int>(kAllocationMarkingFactorSpeedupInterval));
+      PrintPID("Speed up marking after %d steps\n",
+               static_cast<int>(kAllocationMarkingFactorSpeedupInterval));
     }
     speed_up = true;
   }
@@ -907,7 +907,7 @@
 
   if (space_left_is_very_small ||
       only_1_nth_of_space_that_was_available_still_left) {
-    if (FLAG_trace_gc) PrintF("Speed up marking because of low space left\n");
+    if (FLAG_trace_gc) PrintPID("Speed up marking because of low space left\n");
     speed_up = true;
   }
 
@@ -918,7 +918,7 @@
   if (size_of_old_space_multiplied_by_n_during_marking) {
     speed_up = true;
     if (FLAG_trace_gc) {
-      PrintF("Speed up marking because of heap size increase\n");
+      PrintPID("Speed up marking because of heap size increase\n");
     }
   }
 
@@ -930,7 +930,7 @@
   // We try to scan at at least twice the speed that we are allocating.
   if (promoted_during_marking > bytes_scanned_ / 2 + scavenge_slack + delay) {
     if (FLAG_trace_gc) {
-      PrintF("Speed up marking because marker was not keeping up\n");
+      PrintPID("Speed up marking because marker was not keeping up\n");
     }
     speed_up = true;
   }
@@ -938,7 +938,7 @@
   if (speed_up) {
     if (state_ != MARKING) {
       if (FLAG_trace_gc) {
-        PrintF("Postponing speeding up marking until marking starts\n");
+        PrintPID("Postponing speeding up marking until marking starts\n");
       }
     } else {
       allocation_marking_factor_ += kAllocationMarkingFactorSpeedup;
@@ -946,7 +946,7 @@
           Min(kMaxAllocationMarkingFactor,
               static_cast<intptr_t>(allocation_marking_factor_ * 1.3)));
       if (FLAG_trace_gc) {
-        PrintF("Marking speed increased to %d\n", allocation_marking_factor_);
+        PrintPID("Marking speed increased to %d\n", allocation_marking_factor_);
       }
     }
   }
diff --git a/src/incremental-marking.h b/src/incremental-marking.h
index 39e8dae..a9c2321 100644
--- a/src/incremental-marking.h
+++ b/src/incremental-marking.h
@@ -215,8 +215,9 @@
     if (IsMarking()) {
       if (allocation_marking_factor_ < kFastMarking) {
         if (FLAG_trace_gc) {
-          PrintF("Increasing marking speed to %d due to high promotion rate\n",
-                 static_cast<int>(kFastMarking));
+          PrintPID("Increasing marking speed to %d "
+                   "due to high promotion rate\n",
+                   static_cast<int>(kFastMarking));
         }
         allocation_marking_factor_ = kFastMarking;
       }
diff --git a/src/lithium.cc b/src/lithium.cc
index fd8b796..c317cf4 100644
--- a/src/lithium.cc
+++ b/src/lithium.cc
@@ -27,6 +27,19 @@
 
 #include "v8.h"
 #include "lithium.h"
+#include "scopes.h"
+
+#if V8_TARGET_ARCH_IA32
+#include "ia32/lithium-ia32.h"
+#elif V8_TARGET_ARCH_X64
+#include "x64/lithium-x64.h"
+#elif V8_TARGET_ARCH_ARM
+#include "arm/lithium-arm.h"
+#elif V8_TARGET_ARCH_MIPS
+#include "mips/lithium-mips.h"
+#else
+#error "Unknown architecture."
+#endif
 
 namespace v8 {
 namespace internal {
@@ -240,4 +253,137 @@
 }
 
 
+LLabel* LChunkBase::GetLabel(int block_id) const {
+  HBasicBlock* block = graph_->blocks()->at(block_id);
+  int first_instruction = block->first_instruction_index();
+  return LLabel::cast(instructions_[first_instruction]);
+}
+
+
+int LChunkBase::LookupDestination(int block_id) const {
+  LLabel* cur = GetLabel(block_id);
+  while (cur->replacement() != NULL) {
+    cur = cur->replacement();
+  }
+  return cur->block_id();
+}
+
+Label* LChunkBase::GetAssemblyLabel(int block_id) const {
+  LLabel* label = GetLabel(block_id);
+  ASSERT(!label->HasReplacement());
+  return label->label();
+}
+
+void LChunkBase::MarkEmptyBlocks() {
+  HPhase phase("L_Mark empty blocks", this);
+  for (int i = 0; i < graph()->blocks()->length(); ++i) {
+    HBasicBlock* block = graph()->blocks()->at(i);
+    int first = block->first_instruction_index();
+    int last = block->last_instruction_index();
+    LInstruction* first_instr = instructions()->at(first);
+    LInstruction* last_instr = instructions()->at(last);
+
+    LLabel* label = LLabel::cast(first_instr);
+    if (last_instr->IsGoto()) {
+      LGoto* goto_instr = LGoto::cast(last_instr);
+      if (label->IsRedundant() &&
+          !label->is_loop_header()) {
+        bool can_eliminate = true;
+        for (int i = first + 1; i < last && can_eliminate; ++i) {
+          LInstruction* cur = instructions()->at(i);
+          if (cur->IsGap()) {
+            LGap* gap = LGap::cast(cur);
+            if (!gap->IsRedundant()) {
+              can_eliminate = false;
+            }
+          } else {
+            can_eliminate = false;
+          }
+        }
+
+        if (can_eliminate) {
+          label->set_replacement(GetLabel(goto_instr->block_id()));
+        }
+      }
+    }
+  }
+}
+
+
+void LChunkBase::AddInstruction(LInstruction* instr, HBasicBlock* block) {
+  LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
+  int index = -1;
+  if (instr->IsControl()) {
+    instructions_.Add(gap, zone());
+    index = instructions_.length();
+    instructions_.Add(instr, zone());
+  } else {
+    index = instructions_.length();
+    instructions_.Add(instr, zone());
+    instructions_.Add(gap, zone());
+  }
+  if (instr->HasPointerMap()) {
+    pointer_maps_.Add(instr->pointer_map(), zone());
+    instr->pointer_map()->set_lithium_position(index);
+  }
+}
+
+
+LConstantOperand* LChunkBase::DefineConstantOperand(HConstant* constant) {
+  return LConstantOperand::Create(constant->id(), zone());
+}
+
+
+int LChunkBase::GetParameterStackSlot(int index) const {
+  // The receiver is at index 0, the first parameter at index 1, so we
+  // shift all parameter indexes down by the number of parameters, and
+  // make sure they end up negative so they are distinguishable from
+  // spill slots.
+  int result = index - info()->scope()->num_parameters() - 1;
+  ASSERT(result < 0);
+  return result;
+}
+
+
+// A parameter relative to ebp in the arguments stub.
+int LChunkBase::ParameterAt(int index) {
+  ASSERT(-1 <= index);  // -1 is the receiver.
+  return (1 + info()->scope()->num_parameters() - index) *
+      kPointerSize;
+}
+
+
+LGap* LChunkBase::GetGapAt(int index) const {
+  return LGap::cast(instructions_[index]);
+}
+
+
+bool LChunkBase::IsGapAt(int index) const {
+  return instructions_[index]->IsGap();
+}
+
+
+int LChunkBase::NearestGapPos(int index) const {
+  while (!IsGapAt(index)) index--;
+  return index;
+}
+
+
+void LChunkBase::AddGapMove(int index, LOperand* from, LOperand* to) {
+  GetGapAt(index)->GetOrCreateParallelMove(
+      LGap::START, zone())->AddMove(from, to, zone());
+}
+
+
+HConstant* LChunkBase::LookupConstant(LConstantOperand* operand) const {
+  return HConstant::cast(graph_->LookupValue(operand->index()));
+}
+
+
+Representation LChunkBase::LookupLiteralRepresentation(
+    LConstantOperand* operand) const {
+  return graph_->LookupValue(operand->index())->representation();
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/lithium.h b/src/lithium.h
index ff644ee..686441e 100644
--- a/src/lithium.h
+++ b/src/lithium.h
@@ -622,6 +622,64 @@
 };
 
 
+class LGap;
+class LLabel;
+
+// Superclass providing data and behavior common to all the
+// arch-specific LChunk classes.
+class LChunkBase: public ZoneObject {
+ public:
+  LChunkBase(CompilationInfo* info, HGraph* graph)
+    : spill_slot_count_(0),
+      info_(info),
+      graph_(graph),
+      instructions_(32, graph->zone()),
+      pointer_maps_(8, graph->zone()),
+      inlined_closures_(1, graph->zone()) { }
+
+  void AddInstruction(LInstruction* instruction, HBasicBlock* block);
+  LConstantOperand* DefineConstantOperand(HConstant* constant);
+  HConstant* LookupConstant(LConstantOperand* operand) const;
+  Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
+
+  int ParameterAt(int index);
+  int GetParameterStackSlot(int index) const;
+  int spill_slot_count() const { return spill_slot_count_; }
+  CompilationInfo* info() const { return info_; }
+  HGraph* graph() const { return graph_; }
+  const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
+  void AddGapMove(int index, LOperand* from, LOperand* to);
+  LGap* GetGapAt(int index) const;
+  bool IsGapAt(int index) const;
+  int NearestGapPos(int index) const;
+  void MarkEmptyBlocks();
+  const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
+  LLabel* GetLabel(int block_id) const;
+  int LookupDestination(int block_id) const;
+  Label* GetAssemblyLabel(int block_id) const;
+
+  const ZoneList<Handle<JSFunction> >* inlined_closures() const {
+    return &inlined_closures_;
+  }
+
+  void AddInlinedClosure(Handle<JSFunction> closure) {
+    inlined_closures_.Add(closure, zone());
+  }
+
+  Zone* zone() const { return info_->zone(); }
+
+ protected:
+  int spill_slot_count_;
+
+ private:
+  CompilationInfo* info_;
+  HGraph* const graph_;
+  ZoneList<LInstruction*> instructions_;
+  ZoneList<LPointerMap*> pointer_maps_;
+  ZoneList<Handle<JSFunction> > inlined_closures_;
+};
+
+
 int ElementsKindToShiftSize(ElementsKind elements_kind);
 
 
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index e75dc49..e614579 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -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;
diff --git a/src/messages.js b/src/messages.js
index 0701c70..4da3805 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -859,9 +859,9 @@
   }
   var name = null;
   for (var prop in this.receiver) {
-    if (this.receiver.__lookupGetter__(prop) === this.fun ||
-        this.receiver.__lookupSetter__(prop) === this.fun ||
-        (!this.receiver.__lookupGetter__(prop) &&
+    if (%_CallFunction(this.receiver, prop, ObjectLookupGetter) === this.fun ||
+        %_CallFunction(this.receiver, prop, ObjectLookupSetter) === this.fun ||
+        (!%_CallFunction(this.receiver, prop, ObjectLookupGetter) &&
          this.receiver[prop] === this.fun)) {
       // If we find more than one match bail out to avoid confusion.
       if (name) {
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 842001d..7bbdfd5 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -407,16 +407,6 @@
 }
 
 
-LChunk::LChunk(CompilationInfo* info, HGraph* graph)
-    : spill_slot_count_(0),
-      info_(info),
-      graph_(graph),
-      instructions_(32, graph->zone()),
-      pointer_maps_(8, graph->zone()),
-      inlined_closures_(1, graph->zone()) {
-}
-
-
 int LChunk::GetNextSpillIndex(bool is_double) {
   // Skip a slot if for a double-width slot.
   if (is_double) spill_slot_count_++;
@@ -434,117 +424,6 @@
 }
 
 
-void LChunk::MarkEmptyBlocks() {
-  HPhase phase("L_Mark empty blocks", this);
-  for (int i = 0; i < graph()->blocks()->length(); ++i) {
-    HBasicBlock* block = graph()->blocks()->at(i);
-    int first = block->first_instruction_index();
-    int last = block->last_instruction_index();
-    LInstruction* first_instr = instructions()->at(first);
-    LInstruction* last_instr = instructions()->at(last);
-
-    LLabel* label = LLabel::cast(first_instr);
-    if (last_instr->IsGoto()) {
-      LGoto* goto_instr = LGoto::cast(last_instr);
-      if (label->IsRedundant() &&
-          !label->is_loop_header()) {
-        bool can_eliminate = true;
-        for (int i = first + 1; i < last && can_eliminate; ++i) {
-          LInstruction* cur = instructions()->at(i);
-          if (cur->IsGap()) {
-            LGap* gap = LGap::cast(cur);
-            if (!gap->IsRedundant()) {
-              can_eliminate = false;
-            }
-          } else {
-            can_eliminate = false;
-          }
-        }
-
-        if (can_eliminate) {
-          label->set_replacement(GetLabel(goto_instr->block_id()));
-        }
-      }
-    }
-  }
-}
-
-
-void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
-  LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
-  int index = -1;
-  if (instr->IsControl()) {
-    instructions_.Add(gap, zone());
-    index = instructions_.length();
-    instructions_.Add(instr, zone());
-  } else {
-    index = instructions_.length();
-    instructions_.Add(instr, zone());
-    instructions_.Add(gap, zone());
-  }
-  if (instr->HasPointerMap()) {
-    pointer_maps_.Add(instr->pointer_map(), zone());
-    instr->pointer_map()->set_lithium_position(index);
-  }
-}
-
-
-LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
-  return LConstantOperand::Create(constant->id(), zone());
-}
-
-
-int LChunk::GetParameterStackSlot(int index) const {
-  // The receiver is at index 0, the first parameter at index 1, so we
-  // shift all parameter indexes down by the number of parameters, and
-  // make sure they end up negative so they are distinguishable from
-  // spill slots.
-  int result = index - info()->scope()->num_parameters() - 1;
-  ASSERT(result < 0);
-  return result;
-}
-
-// A parameter relative to ebp in the arguments stub.
-int LChunk::ParameterAt(int index) {
-  ASSERT(-1 <= index);  // -1 is the receiver.
-  return (1 + info()->scope()->num_parameters() - index) *
-      kPointerSize;
-}
-
-
-LGap* LChunk::GetGapAt(int index) const {
-  return LGap::cast(instructions_[index]);
-}
-
-
-bool LChunk::IsGapAt(int index) const {
-  return instructions_[index]->IsGap();
-}
-
-
-int LChunk::NearestGapPos(int index) const {
-  while (!IsGapAt(index)) index--;
-  return index;
-}
-
-
-void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
-  GetGapAt(index)->GetOrCreateParallelMove(
-      LGap::START, zone())->AddMove(from, to, zone());
-}
-
-
-Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
-  return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
-}
-
-
-Representation LChunk::LookupLiteralRepresentation(
-    LConstantOperand* operand) const {
-  return graph_->LookupValue(operand->index())->representation();
-}
-
-
 LChunk* LChunkBuilder::Build() {
   ASSERT(is_unused());
   chunk_ = new(zone()) LChunk(info(), graph());
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index e21c921..6c1af63 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -2188,65 +2188,13 @@
 
 
 class LChunkBuilder;
-class LChunk: public ZoneObject {
+class LChunk: public LChunkBase {
  public:
-  explicit LChunk(CompilationInfo* info, HGraph* graph);
-
-  void AddInstruction(LInstruction* instruction, HBasicBlock* block);
-  LConstantOperand* DefineConstantOperand(HConstant* constant);
-  Handle<Object> LookupLiteral(LConstantOperand* operand) const;
-  Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
+  explicit LChunk(CompilationInfo* info, HGraph* graph)
+      : LChunkBase(info, graph) { }
 
   int GetNextSpillIndex(bool is_double);
   LOperand* GetNextSpillSlot(bool is_double);
-
-  int ParameterAt(int index);
-  int GetParameterStackSlot(int index) const;
-  int spill_slot_count() const { return spill_slot_count_; }
-  CompilationInfo* info() const { return info_; }
-  HGraph* graph() const { return graph_; }
-  const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
-  void AddGapMove(int index, LOperand* from, LOperand* to);
-  LGap* GetGapAt(int index) const;
-  bool IsGapAt(int index) const;
-  int NearestGapPos(int index) const;
-  void MarkEmptyBlocks();
-  const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
-  LLabel* GetLabel(int block_id) const {
-    HBasicBlock* block = graph_->blocks()->at(block_id);
-    int first_instruction = block->first_instruction_index();
-    return LLabel::cast(instructions_[first_instruction]);
-  }
-  int LookupDestination(int block_id) const {
-    LLabel* cur = GetLabel(block_id);
-    while (cur->replacement() != NULL) {
-      cur = cur->replacement();
-    }
-    return cur->block_id();
-  }
-  Label* GetAssemblyLabel(int block_id) const {
-    LLabel* label = GetLabel(block_id);
-    ASSERT(!label->HasReplacement());
-    return label->label();
-  }
-
-  const ZoneList<Handle<JSFunction> >* inlined_closures() const {
-    return &inlined_closures_;
-  }
-
-  void AddInlinedClosure(Handle<JSFunction> closure) {
-    inlined_closures_.Add(closure, zone());
-  }
-
-  Zone* zone() const { return graph_->zone(); }
-
- private:
-  int spill_slot_count_;
-  CompilationInfo* info_;
-  HGraph* const graph_;
-  ZoneList<LInstruction*> instructions_;
-  ZoneList<LPointerMap*> pointer_maps_;
-  ZoneList<Handle<JSFunction> > inlined_closures_;
 };
 
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 06c3405..fbb0183 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -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);
 }
 
 
@@ -2092,6 +2095,7 @@
                           const WhitenessWitness&) {
   // Range check.
   ASSERT(descriptor_number < number_of_descriptors());
+  ASSERT(desc->GetDetails().index() > 0);
 
   NoIncrementalWriteBarrierSet(this,
                                ToKeyIndex(descriptor_number),
@@ -3437,8 +3441,9 @@
 
 
 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);
@@ -3446,85 +3451,60 @@
 }
 
 
-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;
-  } 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());
-    }
   }
+
+  Object* object = READ_FIELD(this, kInstanceDescriptorsOrBackPointerOffset);
+
+  if (object->IsDescriptorArray()) {
+    value->set_back_pointer_storage(
+        DescriptorArray::cast(object)->back_pointer_storage());
+  } else {
+    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));
-  } else {
-    DescriptorArray::cast(object)->set_bit_field3_storage(value);
-  }
-}
-
 
 Object* Map::GetBackPointer() {
-  return READ_FIELD(this, kBackPointerOffset);
+  Object* object = READ_FIELD(this, kInstanceDescriptorsOrBackPointerOffset);
+  if (object->IsDescriptorArray()) {
+    return DescriptorArray::cast(object)->back_pointer_storage();
+  } else {
+    ASSERT(object->IsMap() || object->IsUndefined());
+    return object;
+  }
 }
 
 
@@ -3549,8 +3529,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 +3599,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 +3628,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);
+  }
 }
 
 
diff --git a/src/objects.cc b/src/objects.cc
index cd2eebf..d6c86dd 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -514,11 +514,11 @@
         // map change to invalidate any ICs that think they can load
         // from the DontDelete cell without checking if it contains
         // the hole value.
-        Object* new_map;
+        Map* new_map;
         { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
-          if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
+          if (!maybe_new_map->To(&new_map)) return maybe_new_map;
         }
-        set_map(Map::cast(new_map));
+        set_map(new_map);
       }
       JSGlobalPropertyCell* cell =
           JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
@@ -1526,13 +1526,18 @@
                                        PropertyAttributes attributes,
                                        StoreFromKeyed store_mode) {
   ASSERT(!IsJSGlobalProxy());
+  ASSERT(map()->instance_descriptors()->Search(name) ==
+         DescriptorArray::kNotFound);
 
   // Normalize the object if the name is an actual string (not the
   // hidden symbols) and is not a real identifier.
+  // Normalize the object if it will have too many fast properties.
   Isolate* isolate = GetHeap()->isolate();
   StringInputBuffer buffer(name);
-  if (!IsIdentifier(isolate->unicode_cache(), &buffer)
-      && name != isolate->heap()->hidden_symbol()) {
+  if ((!IsIdentifier(isolate->unicode_cache(), &buffer)
+       && name != isolate->heap()->hidden_symbol()) ||
+      (map()->unused_property_fields() == 0 &&
+       TooManyFastProperties(properties()->length(), store_mode))) {
     Object* obj;
     { MaybeObject* maybe_obj =
           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
@@ -1546,7 +1551,7 @@
   int index = map()->NextFreePropertyIndex();
 
   // Allocate new instance descriptors with (name, index) added
-  FieldDescriptor new_field(name, index, attributes);
+  FieldDescriptor new_field(name, index, attributes, 0);
   DescriptorArray* new_descriptors;
   { MaybeObject* maybe_new_descriptors =
         old_descriptors->CopyInsert(&new_field);
@@ -1555,27 +1560,19 @@
     }
   }
 
-  // Only allow map transition if the object isn't the global object and there
-  // is not a transition for the name, or there's a transition for the name but
-  // it's unrelated to properties.
-  int descriptor_index = old_descriptors->SearchWithCache(name);
-
-  // Element transitions are stored in the descriptor for property "", which is
-  // not a identifier and should have forced a switch to slow properties above.
-  bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound;
+  // Only allow map transition if the object isn't the global object.
   bool allow_map_transition =
-      can_insert_transition &&
       (isolate->context()->global_context()->object_function()->map() != map());
 
   ASSERT(index < map()->inobject_properties() ||
          (index - map()->inobject_properties()) < properties()->length() ||
          map()->unused_property_fields() == 0);
+
   // Allocate a new map for the object.
-  Object* r;
-  { MaybeObject* maybe_r = map()->CopyDropDescriptors();
-    if (!maybe_r->ToObject(&r)) return maybe_r;
+  Map* new_map;
+  { MaybeObject* maybe_r = map()->CopyReplaceDescriptors(new_descriptors);
+    if (!maybe_r->To(&new_map)) return maybe_r;
   }
-  Map* new_map = Map::cast(r);
 
   TransitionArray* new_transitions = NULL;
   if (allow_map_transition) {
@@ -1586,31 +1583,24 @@
   }
 
   if (map()->unused_property_fields() == 0) {
-    if (TooManyFastProperties(properties()->length(), store_mode)) {
-      Object* obj;
-      { MaybeObject* maybe_obj =
-            NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
-        if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-      }
-      return AddSlowProperty(name, value, attributes);
-    }
     // Make room for the new value
-    Object* values;
+    FixedArray* values;
     { MaybeObject* maybe_values =
           properties()->CopySize(properties()->length() + kFieldsAdded);
-      if (!maybe_values->ToObject(&values)) return maybe_values;
+      if (!maybe_values->To(&values)) return maybe_values;
     }
-    set_properties(FixedArray::cast(values));
+    set_properties(values);
     new_map->set_unused_property_fields(kFieldsAdded - 1);
   } else {
     new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
   }
+
   // Apply all changes at once, so they are atomic.
   if (allow_map_transition) {
     MaybeObject* transition_added = map()->set_transitions(new_transitions);
     if (transition_added->IsFailure()) return transition_added;
   }
-  new_map->set_instance_descriptors(new_descriptors);
+
   new_map->SetBackPointer(map());
   set_map(new_map);
   return FastPropertyAtPut(index, value);
@@ -1622,7 +1612,7 @@
     JSFunction* function,
     PropertyAttributes attributes) {
   // Allocate new instance descriptors with (name, function) added
-  ConstantFunctionDescriptor d(name, function, attributes);
+  ConstantFunctionDescriptor d(name, function, attributes, 0);
   DescriptorArray* new_descriptors;
   { MaybeObject* maybe_new_descriptors =
         map()->instance_descriptors()->CopyInsert(&d);
@@ -1633,11 +1623,10 @@
 
   // Allocate a new map for the object.
   Map* new_map;
-  { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
+  { MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(new_descriptors);
     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   }
 
-  new_map->set_instance_descriptors(new_descriptors);
   Map* old_map = map();
   set_map(new_map);
 
@@ -1865,27 +1854,19 @@
   }
 
   int index = map()->NextFreePropertyIndex();
-  FieldDescriptor new_field(name, index, attributes);
+  FieldDescriptor new_field(name, index, attributes, 0);
   // Make a new DescriptorArray replacing an entry with FieldDescriptor.
-  Object* descriptors_unchecked;
-  { MaybeObject* maybe_descriptors_unchecked =
+  DescriptorArray* new_descriptors;
+  { MaybeObject* maybe_descriptors =
         map()->instance_descriptors()->CopyInsert(&new_field);
-    if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
-      return maybe_descriptors_unchecked;
-    }
+    if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
   }
-  DescriptorArray* new_descriptors =
-      DescriptorArray::cast(descriptors_unchecked);
 
   // Make a new map for the object.
-  Object* new_map_unchecked;
-  { MaybeObject* maybe_new_map_unchecked = map()->CopyDropDescriptors();
-    if (!maybe_new_map_unchecked->ToObject(&new_map_unchecked)) {
-      return maybe_new_map_unchecked;
-    }
+  Map* new_map;
+  { MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(new_descriptors);
+    if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   }
-  Map* new_map = Map::cast(new_map_unchecked);
-  new_map->set_instance_descriptors(new_descriptors);
 
   // Make new properties array if necessary.
   FixedArray* new_properties = 0;  // Will always be NULL or a valid pointer.
@@ -2938,7 +2919,7 @@
 
       Map* transition_map = Map::cast(transition);
       DescriptorArray* descriptors = transition_map->instance_descriptors();
-      int descriptor = descriptors->SearchWithCache(*name);
+      int descriptor = descriptors->LastAdded();
       PropertyDetails details = descriptors->GetDetails(descriptor);
       ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION);
 
@@ -3062,7 +3043,7 @@
 
       Map* transition_map = Map::cast(transition);
       DescriptorArray* descriptors = transition_map->instance_descriptors();
-      int descriptor = descriptors->Search(name);
+      int descriptor = descriptors->LastAdded();
       PropertyDetails details = descriptors->GetDetails(descriptor);
       ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION);
 
@@ -3411,9 +3392,7 @@
                                                -instance_size_delta);
   }
 
-
   set_map(new_map);
-  new_map->clear_instance_descriptors();
 
   set_properties(dictionary);
 
@@ -4612,7 +4591,7 @@
 
   // step 2: create a copy of the descriptors, incl. the new getter/setter pair
   Map* map1 = obj->map();
-  CallbacksDescriptor callbacks_descr2(name, accessors2, attributes);
+  CallbacksDescriptor callbacks_descr2(name, accessors2, attributes, 0);
   DescriptorArray* descriptors2;
   { MaybeObject* maybe_descriptors2 =
         map1->instance_descriptors()->CopyInsert(&callbacks_descr2);
@@ -4621,10 +4600,9 @@
 
   // step 3: create a new map with the new descriptors
   Map* map2;
-  { MaybeObject* maybe_map2 = map1->CopyDropDescriptors();
+  { MaybeObject* maybe_map2 = map1->CopyReplaceDescriptors(descriptors2);
     if (!maybe_map2->To(&map2)) return maybe_map2;
   }
-  map2->set_instance_descriptors(descriptors2);
 
   // step 4: create a new getter/setter pair with a transition to the new map
   AccessorPair* accessors1;
@@ -4658,9 +4636,9 @@
                                      AccessorComponent component,
                                      Object* accessor,
                                      PropertyAttributes attributes ) {
-  DescriptorArray* descs = Map::cast(map)->instance_descriptors();
-  int number = descs->SearchWithCache(name);
-  ASSERT(number != DescriptorArray::kNotFound);
+  Map* transitioned_map = Map::cast(map);
+  DescriptorArray* descs = transitioned_map->instance_descriptors();
+  int number = descs->LastAdded();
   Object* target_accessor =
       AccessorPair::cast(descs->GetCallbacksObject(number))->get(component);
   PropertyAttributes target_attributes = descs->GetDetails(number).attributes();
@@ -4683,7 +4661,7 @@
 
   // step 2: create a copy of the descriptors, incl. the new getter/setter pair
   Map* map2 = obj->map();
-  CallbacksDescriptor callbacks_descr3(name, accessors3, attributes);
+  CallbacksDescriptor callbacks_descr3(name, accessors3, attributes, 0);
   DescriptorArray* descriptors3;
   { MaybeObject* maybe_descriptors3 =
         map2->instance_descriptors()->CopyInsert(&callbacks_descr3);
@@ -4692,10 +4670,9 @@
 
   // step 3: create a new map with the new descriptors
   Map* map3;
-  { MaybeObject* maybe_map3 = map2->CopyDropDescriptors();
+  { MaybeObject* maybe_map3 = map2->CopyReplaceDescriptors(descriptors3);
     if (!maybe_map3->To(&map3)) return maybe_map3;
   }
-  map3->set_instance_descriptors(descriptors3);
 
   // step 4: add a new transition to the new map
   TransitionArray* new_transitions;
@@ -4862,9 +4839,9 @@
   if (name->AsArrayIndex(&index)) {
     for (Object* obj = this;
          obj != heap->null_value();
-         obj = JSObject::cast(obj)->GetPrototype()) {
-      JSObject* js_object = JSObject::cast(obj);
-      if (js_object->HasDictionaryElements()) {
+         obj = JSReceiver::cast(obj)->GetPrototype()) {
+      if (obj->IsJSObject() && JSObject::cast(obj)->HasDictionaryElements()) {
+        JSObject* js_object = JSObject::cast(obj);
         SeededNumberDictionary* dictionary = js_object->element_dictionary();
         int entry = dictionary->FindEntry(index);
         if (entry != SeededNumberDictionary::kNotFound) {
@@ -4879,9 +4856,9 @@
   } else {
     for (Object* obj = this;
          obj != heap->null_value();
-         obj = JSObject::cast(obj)->GetPrototype()) {
+         obj = JSReceiver::cast(obj)->GetPrototype()) {
       LookupResult result(heap->isolate());
-      JSObject::cast(obj)->LocalLookup(name, &result);
+      JSReceiver::cast(obj)->LocalLookup(name, &result);
       if (result.IsProperty()) {
         if (result.IsReadOnly()) return heap->undefined_value();
         if (result.IsPropertyCallbacks()) {
@@ -4918,46 +4895,18 @@
 }
 
 
-MaybeObject* Map::CopyDropDescriptors() {
-  Heap* heap = GetHeap();
-  Object* result;
+MaybeObject* Map::RawCopy(int instance_size) {
+  Map* result;
   { MaybeObject* maybe_result =
-        heap->AllocateMap(instance_type(), instance_size());
-    if (!maybe_result->ToObject(&result)) return maybe_result;
+        GetHeap()->AllocateMap(instance_type(), instance_size);
+    if (!maybe_result->To(&result)) return maybe_result;
   }
-  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());
 
-  // If the map has pre-allocated properties always start out with a descriptor
-  // array describing these properties.
-  if (pre_allocated_property_fields() > 0) {
-    ASSERT(constructor()->IsJSFunction());
-    JSFunction* ctor = JSFunction::cast(constructor());
-    Object* descriptors;
-    { MaybeObject* maybe_descriptors =
-          ctor->initial_map()->instance_descriptors()->Copy(
-              DescriptorArray::MAY_BE_SHARED);
-      if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
-    }
-    Map::cast(result)->set_instance_descriptors(
-        DescriptorArray::cast(descriptors));
-    Map::cast(result)->set_pre_allocated_property_fields(
-        pre_allocated_property_fields());
-  }
-  Map::cast(result)->set_bit_field(bit_field());
-  Map::cast(result)->set_bit_field2(bit_field2());
-  Map::cast(result)->set_bit_field3(bit_field3());
-  Map::cast(result)->set_is_shared(false);
-  Map::cast(result)->ClearCodeCache(heap);
+  result->set_prototype(prototype());
+  result->set_constructor(constructor());
+  result->set_bit_field(bit_field());
+  result->set_bit_field2(bit_field2());
+  result->set_bit_field3(bit_field3());
   return result;
 }
 
@@ -4969,29 +4918,21 @@
     new_instance_size -= inobject_properties() * kPointerSize;
   }
 
-  Object* result;
-  { MaybeObject* maybe_result =
-        GetHeap()->AllocateMap(instance_type(), new_instance_size);
-    if (!maybe_result->ToObject(&result)) return maybe_result;
+  Map* result;
+  { MaybeObject* maybe_result = RawCopy(new_instance_size);
+    if (!maybe_result->To(&result)) return maybe_result;
   }
 
   if (mode != CLEAR_INOBJECT_PROPERTIES) {
-    Map::cast(result)->set_inobject_properties(inobject_properties());
+    result->set_inobject_properties(inobject_properties());
   }
 
-  Map::cast(result)->set_prototype(prototype());
-  Map::cast(result)->set_constructor(constructor());
-
-  Map::cast(result)->set_bit_field(bit_field());
-  Map::cast(result)->set_bit_field2(bit_field2());
-  Map::cast(result)->set_bit_field3(bit_field3());
-  Map::cast(result)->set_code_cache(code_cache());
-
-  Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
+  result->set_code_cache(code_cache());
+  result->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
 
 #ifdef DEBUG
   if (FLAG_verify_heap && Map::cast(result)->is_shared()) {
-    Map::cast(result)->SharedMapVerify();
+    result->SharedMapVerify();
   }
 #endif
 
@@ -4999,19 +4940,56 @@
 }
 
 
-MaybeObject* Map::CopyDropTransitions(
-    DescriptorArray::SharedMode shared_mode) {
-  Object* new_map;
-  { MaybeObject* maybe_new_map = CopyDropDescriptors();
-    if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
+MaybeObject* Map::CopyDropDescriptors() {
+  Map* result;
+  { MaybeObject* maybe_result = RawCopy(instance_size());
+    if (!maybe_result->To(&result)) return maybe_result;
   }
-  Object* descriptors;
+
+  // Please note instance_type and instance_size are set when allocated.
+  result->set_inobject_properties(inobject_properties());
+  result->set_unused_property_fields(unused_property_fields());
+
+  result->set_pre_allocated_property_fields(pre_allocated_property_fields());
+  result->set_is_shared(false);
+  result->ClearCodeCache(GetHeap());
+  return result;
+}
+
+
+MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors) {
+  Map* result;
+  { MaybeObject* maybe_result = CopyDropDescriptors();
+    if (!maybe_result->To(&result)) return maybe_result;
+  }
+  result->set_instance_descriptors(descriptors);
+  return result;
+}
+
+
+MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
+  if (pre_allocated_property_fields() == 0) return CopyDropDescriptors();
+
+  // If the map has pre-allocated properties always start out with a descriptor
+  // array describing these properties.
+  ASSERT(constructor()->IsJSFunction());
+  JSFunction* ctor = JSFunction::cast(constructor());
+  DescriptorArray* descriptors;
   { MaybeObject* maybe_descriptors =
-        instance_descriptors()->Copy(shared_mode);
-    if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
+        ctor->initial_map()->instance_descriptors()->Copy(
+            DescriptorArray::MAY_BE_SHARED);
+    if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
   }
-  cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
-  return new_map;
+  return CopyReplaceDescriptors(descriptors);
+}
+
+
+MaybeObject* Map::CopyDropTransitions(DescriptorArray::SharedMode shared_mode) {
+  DescriptorArray* descriptors;
+  { MaybeObject* maybe_descriptors = instance_descriptors()->Copy(shared_mode);
+    if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
+  }
+  return CopyReplaceDescriptors(descriptors);
 }
 
 
@@ -5824,9 +5802,7 @@
     if (!maybe_array->To(&result)) return maybe_array;
   }
 
-  result->set(kBitField3StorageIndex, Smi::FromInt(0));
-  result->set(kEnumerationIndexIndex,
-              Smi::FromInt(PropertyDetails::kInitialIndex));
+  result->set(kLastAddedIndex, Smi::FromInt(-1));
   result->set(kTransitionsIndex, Smi::FromInt(0));
   return result;
 }
@@ -5838,9 +5814,9 @@
   ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
   ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
   if (HasEnumCache()) {
-    FixedArray::cast(get(kEnumerationIndexIndex))->
+    FixedArray::cast(get(kLastAddedIndex))->
       set(kEnumCacheBridgeCacheIndex, new_cache);
-    FixedArray::cast(get(kEnumerationIndexIndex))->
+    FixedArray::cast(get(kLastAddedIndex))->
       set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
   } else {
     if (IsEmpty()) return;  // Do nothing for empty descriptor array.
@@ -5849,9 +5825,9 @@
     FixedArray::cast(bridge_storage)->
       set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
     NoWriteBarrierSet(FixedArray::cast(bridge_storage),
-                      kEnumCacheBridgeEnumIndex,
-                      get(kEnumerationIndexIndex));
-    set(kEnumerationIndexIndex, bridge_storage);
+                      kEnumCacheBridgeLastAdded,
+                      get(kLastAddedIndex));
+    set(kLastAddedIndex, bridge_storage);
   }
 }
 
@@ -5918,14 +5894,11 @@
 
   // Set the enumeration index in the descriptors and set the enumeration index
   // in the result.
-  int enumeration_index = NextEnumerationIndex();
   if (keep_enumeration_index) {
     descriptor->SetEnumerationIndex(GetDetails(index).index());
   } else {
-    descriptor->SetEnumerationIndex(enumeration_index);
-    ++enumeration_index;
+    descriptor->SetEnumerationIndex(NextEnumerationIndex());
   }
-  new_descriptors->SetNextEnumerationIndex(enumeration_index);
 
   // Copy the descriptors, inserting or replacing a descriptor.
   int to_index = 0;
@@ -5948,6 +5921,12 @@
   ASSERT(insertion_index < new_descriptors->number_of_descriptors());
   new_descriptors->Set(insertion_index, descriptor, witness);
 
+  if (!replacing) {
+    new_descriptors->SetLastAdded(insertion_index);
+  } else {
+    new_descriptors->SetLastAdded(LastAdded());
+  }
+
   ASSERT(to_index == new_descriptors->number_of_descriptors());
   SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
 
@@ -5972,8 +5951,9 @@
           new_descriptors->CopyFrom(i, this, i, witness);
       if (copy_result->IsFailure()) return copy_result;
     }
+    new_descriptors->SetLastAdded(LastAdded());
   }
-  new_descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
+
   return new_descriptors;
 }
 
@@ -5984,6 +5964,8 @@
 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
   // In-place heap sort.
   int len = number_of_descriptors();
+  // Nothing to sort.
+  if (len == 0) return;
 
   // Bottom-up max-heap construction.
   // Index of the last node with children
@@ -6031,6 +6013,19 @@
       parent_index = child_index;
     }
   }
+
+  int last_enum_index = -1;
+  int last_added = -1;
+  for (int i = 0; i < len; ++i) {
+    int current_enum = GetDetails(i).index();
+    if (current_enum > last_enum_index) {
+      last_added = i;
+      last_enum_index = current_enum;
+    }
+  }
+  SetLastAdded(last_added);
+
+  ASSERT(LastAdded() != -1);
 }
 
 
@@ -7413,7 +7408,7 @@
   if (transition_index == 0 &&
       !t->HasElementsTransition() &&
       !t->HasPrototypeTransitions()) {
-    return ClearTransitions();
+    return ClearTransitions(heap);
   }
 
   int trim = t->number_of_transitions() - transition_index;
@@ -7790,25 +7785,34 @@
     return false;
   }
 
-  // If the prototype is null inline constructors cause no problems.
-  if (!prototype->IsJSObject()) {
-    ASSERT(prototype->IsNull());
-    return true;
-  }
-
   Heap* heap = GetHeap();
 
-  // Traverse the proposed prototype chain looking for setters for properties of
-  // the same names as are set by the inline constructor.
+  // Traverse the proposed prototype chain looking for properties of the
+  // same names as are set by the inline constructor.
   for (Object* obj = prototype;
        obj != heap->null_value();
        obj = obj->GetPrototype()) {
-    JSObject* js_object = JSObject::cast(obj);
+    JSReceiver* receiver = JSReceiver::cast(obj);
     for (int i = 0; i < this_property_assignments_count(); i++) {
       LookupResult result(heap->isolate());
       String* name = GetThisPropertyAssignmentName(i);
-      js_object->LocalLookupRealNamedProperty(name, &result);
-      if (result.IsCallbacks()) return false;
+      receiver->LocalLookup(name, &result);
+      if (result.IsProperty()) {
+        switch (result.type()) {
+          case NORMAL:
+          case FIELD:
+          case CONSTANT_FUNCTION:
+            break;
+          case INTERCEPTOR:
+          case CALLBACKS:
+          case HANDLER:
+            return false;
+          case TRANSITION:
+          case NONEXISTENT:
+            UNREACHABLE();
+            break;
+        }
+      }
     }
   }
 
@@ -12719,7 +12723,7 @@
                                      JSFunction::cast(value),
                                      details.attributes(),
                                      details.index());
-        descriptors->Set(next_descriptor++, &d, witness);
+        descriptors->Set(next_descriptor, &d, witness);
       } else if (type == NORMAL) {
         if (current_offset < inobject_props) {
           obj->InObjectPropertyAtPut(current_offset,
@@ -12733,7 +12737,7 @@
                           current_offset++,
                           details.attributes(),
                           details.index());
-        descriptors->Set(next_descriptor++, &d, witness);
+        descriptors->Set(next_descriptor, &d, witness);
       } else if (type == CALLBACKS) {
         if (value->IsAccessorPair()) {
           MaybeObject* maybe_copy =
@@ -12744,30 +12748,31 @@
                               value,
                               details.attributes(),
                               details.index());
-        descriptors->Set(next_descriptor++, &d, witness);
+        descriptors->Set(next_descriptor, &d, witness);
       } else {
         UNREACHABLE();
       }
+      ++next_descriptor;
     }
   }
   ASSERT(current_offset == number_of_fields);
 
   descriptors->Sort(witness);
   // Allocate new map.
-  Object* new_map;
-  { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
-    if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
+  Map* new_map;
+  { MaybeObject* maybe_new_map =
+        obj->map()->CopyReplaceDescriptors(descriptors);
+    if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   }
 
+  new_map->set_unused_property_fields(unused_property_fields);
+
   // Transform the object.
-  obj->set_map(Map::cast(new_map));
-  obj->map()->set_instance_descriptors(descriptors);
-  obj->map()->set_unused_property_fields(unused_property_fields);
+  obj->set_map(new_map);
 
   obj->set_properties(FixedArray::cast(fields));
   ASSERT(obj->IsJSObject());
 
-  descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
   // Check that it really works.
   ASSERT(obj->HasFastProperties());
 
diff --git a/src/objects.h b/src/objects.h
index d7cd80f..89d2809 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2476,37 +2476,44 @@
 
   inline int number_of_entries() { return number_of_descriptors(); }
 
-  int NextEnumerationIndex() {
-    if (IsEmpty()) return PropertyDetails::kInitialIndex;
-    Object* obj = get(kEnumerationIndexIndex);
+  int LastAdded() {
+    ASSERT(!IsEmpty());
+    Object* obj = get(kLastAddedIndex);
     if (obj->IsSmi()) {
       return Smi::cast(obj)->value();
     } else {
-      Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
+      Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeLastAdded);
       return Smi::cast(index)->value();
     }
   }
 
-  // Set next enumeration index and flush any enum cache.
-  void SetNextEnumerationIndex(int value) {
-    if (!IsEmpty()) {
-      set(kEnumerationIndexIndex, Smi::FromInt(value));
+  int NextEnumerationIndex() {
+    if (number_of_descriptors() == 0) {
+      return PropertyDetails::kInitialIndex;
     }
+    return GetDetails(LastAdded()).index() + 1;
   }
+
+  // Set index of the last added descriptor and flush any enum cache.
+  void SetLastAdded(int index) {
+    ASSERT(!IsEmpty() || index > 0);
+    set(kLastAddedIndex, Smi::FromInt(index));
+  }
+
   bool HasEnumCache() {
-    return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
+    return !IsEmpty() && !get(kLastAddedIndex)->IsSmi();
   }
 
   Object* GetEnumCache() {
     ASSERT(HasEnumCache());
-    FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
+    FixedArray* bridge = FixedArray::cast(get(kLastAddedIndex));
     return bridge->get(kEnumCacheBridgeCacheIndex);
   }
 
   Object** GetEnumCacheSlot() {
     ASSERT(HasEnumCache());
     return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
-                                kEnumerationIndexOffset);
+                                kLastAddedOffset);
   }
 
   Object** GetTransitionsSlot() {
@@ -2514,11 +2521,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,28 +2610,28 @@
   // Constant for denoting key was not found.
   static const int kNotFound = -1;
 
-  static const int kBitField3StorageIndex = 0;
-  static const int kEnumerationIndexIndex = 1;
+  static const int kBackPointerStorageIndex = 0;
+  static const int kLastAddedIndex = 1;
   static const int kTransitionsIndex = 2;
   static const int kFirstIndex = 3;
 
   // The length of the "bridge" to the enum cache.
   static const int kEnumCacheBridgeLength = 3;
-  static const int kEnumCacheBridgeEnumIndex = 0;
+  static const int kEnumCacheBridgeLastAdded = 0;
   static const int kEnumCacheBridgeCacheIndex = 1;
   static const int kEnumCacheBridgeIndicesCacheIndex = 2;
 
   // Layout description.
-  static const int kBitField3StorageOffset = FixedArray::kHeaderSize;
-  static const int kEnumerationIndexOffset = kBitField3StorageOffset +
-                                             kPointerSize;
-  static const int kTransitionsOffset = kEnumerationIndexOffset + kPointerSize;
+  static const int kBackPointerStorageOffset = FixedArray::kHeaderSize;
+  static const int kLastAddedOffset = kBackPointerStorageOffset +
+                                      kPointerSize;
+  static const int kTransitionsOffset = kLastAddedOffset + kPointerSize;
   static const int kFirstOffset = kTransitionsOffset + kPointerSize;
 
   // Layout description for the bridge array.
-  static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
+  static const int kEnumCacheBridgeLastAddedOffset = FixedArray::kHeaderSize;
   static const int kEnumCacheBridgeCacheOffset =
-    kEnumCacheBridgeEnumOffset + kPointerSize;
+    kEnumCacheBridgeLastAddedOffset + kPointerSize;
 
   // Layout of descriptor.
   static const int kDescriptorKey = 0;
@@ -3094,6 +3097,7 @@
 
   // Accessors for next enumeration index.
   void SetNextEnumerationIndex(int index) {
+    ASSERT(index != 0);
     this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
   }
 
@@ -4676,12 +4680,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 +4812,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 +4840,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)
@@ -4917,7 +4910,11 @@
                                     String* name,
                                     LookupResult* result);
 
+  MUST_USE_RESULT MaybeObject* RawCopy(int instance_size);
+  MUST_USE_RESULT MaybeObject* CopyWithPreallocatedFieldDescriptors();
   MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
+  MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
+      DescriptorArray* descriptors);
 
   MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode,
                                               NormalizedMapSharingMode sharing);
@@ -5047,23 +5044,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;
diff --git a/src/parser.cc b/src/parser.cc
index e4efdf7..2dbfecc 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -4362,6 +4362,7 @@
                           int end,
                           const char* message,
                           const char* argument_opt) {
+    if (has_error_) return;
     has_error_ = true;
     start_ = start;
     end_ = end;
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index d942d78..3bc8373 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -153,6 +153,11 @@
 }
 
 
+int OS::GetCurrentProcessId() {
+  return static_cast<int>(getpid());
+}
+
+
 // ----------------------------------------------------------------------------
 // POSIX date/time support.
 //
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 2473949..49463be 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -627,6 +627,11 @@
 }
 
 
+int OS::GetCurrentProcessId() {
+  return static_cast<int>(::GetCurrentProcessId());
+}
+
+
 // ----------------------------------------------------------------------------
 // Win32 console output.
 //
diff --git a/src/platform.h b/src/platform.h
index a2ddf7a..14f4551 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -317,6 +317,8 @@
   static const int kMinComplexMemCopy = 256;
 #endif  // V8_TARGET_ARCH_IA32
 
+  static int GetCurrentProcessId();
+
  private:
   static const int msPerSecond = 1000;
 
diff --git a/src/preparser.cc b/src/preparser.cc
index 0c17eec..21da4f8 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -602,14 +602,17 @@
     if (token == i::Token::CASE) {
       Expect(i::Token::CASE, CHECK_OK);
       ParseExpression(true, CHECK_OK);
-      Expect(i::Token::COLON, CHECK_OK);
-    } else if (token == i::Token::DEFAULT) {
-      Expect(i::Token::DEFAULT, CHECK_OK);
-      Expect(i::Token::COLON, CHECK_OK);
     } else {
-      ParseStatement(CHECK_OK);
+      Expect(i::Token::DEFAULT, CHECK_OK);
     }
+    Expect(i::Token::COLON, CHECK_OK);
     token = peek();
+    while (token != i::Token::CASE &&
+           token != i::Token::DEFAULT &&
+           token != i::Token::RBRACE) {
+      ParseStatement(CHECK_OK);
+      token = peek();
+    }
   }
   Expect(i::Token::RBRACE, ok);
   return Statement::Default();
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index d06b62c..a33e904 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -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(),
diff --git a/src/property.h b/src/property.h
index 7200280..f783dc2 100644
--- a/src/property.h
+++ b/src/property.h
@@ -92,7 +92,7 @@
              Object* value,
              PropertyAttributes attributes,
              PropertyType type,
-             int index = 0)
+             int index)
       : key_(key),
         value_(value),
         details_(attributes, type, index) { }
@@ -106,7 +106,7 @@
   FieldDescriptor(String* key,
                   int field_index,
                   PropertyAttributes attributes,
-                  int index = 0)
+                  int index)
       : Descriptor(key, Smi::FromInt(field_index), attributes, FIELD, index) {}
 };
 
@@ -116,7 +116,7 @@
   ConstantFunctionDescriptor(String* key,
                              JSFunction* function,
                              PropertyAttributes attributes,
-                             int index = 0)
+                             int index)
       : Descriptor(key, function, attributes, CONSTANT_FUNCTION, index) {}
 };
 
@@ -126,7 +126,7 @@
   CallbacksDescriptor(String* key,
                       Object* foreign,
                       PropertyAttributes attributes,
-                      int index = 0)
+                      int index)
       : Descriptor(key, foreign, attributes, CALLBACKS, index) {}
 };
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 93479d8..42d19aa 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2180,24 +2180,16 @@
         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
         details.index());
     // Construct a new field descriptors array containing the new descriptor.
-    Object* descriptors_unchecked;
-    { MaybeObject* maybe_descriptors_unchecked =
-        instance_desc->CopyInsert(&new_desc);
-      if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
-        return maybe_descriptors_unchecked;
-      }
+    DescriptorArray* new_descriptors;
+    { MaybeObject* maybe_descriptors = instance_desc->CopyInsert(&new_desc);
+      if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
     }
-    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)) {
-        return maybe_map_unchecked;
-      }
+    Map* new_map;
+    { MaybeObject* maybe_map =
+          function->map()->CopyReplaceDescriptors(new_descriptors);
+      if (!maybe_map->To(&new_map)) return maybe_map;
     }
-    Map* new_map = Map::cast(map_unchecked);
-    new_map->set_instance_descriptors(new_descriptors);
     function->set_map(new_map);
   } else {  // Dictionary properties.
     // Directly manipulate the property details.
@@ -10257,11 +10249,12 @@
 
 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
   ASSERT(args.length() == 3);
-  CONVERT_ARG_CHECKED(JSObject, obj, 0);
+  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
   CONVERT_ARG_CHECKED(String, name, 1);
   CONVERT_SMI_ARG_CHECKED(flag, 2);
   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
-  return obj->LookupAccessor(name, component);
+  if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
+  return JSObject::cast(receiver)->LookupAccessor(name, component);
 }
 
 
diff --git a/src/transitions-inl.h b/src/transitions-inl.h
index 517fdc8..16496dd 100644
--- a/src/transitions-inl.h
+++ b/src/transitions-inl.h
@@ -177,8 +177,7 @@
 PropertyDetails TransitionArray::GetTargetDetails(int transition_number) {
   Map* map = GetTargetMap(transition_number);
   DescriptorArray* descriptors = map->instance_descriptors();
-  String* key = GetKey(transition_number);
-  int descriptor = descriptors->SearchWithCache(key);
+  int descriptor = descriptors->LastAdded();
   ASSERT(descriptor != DescriptorArray::kNotFound);
   return descriptors->GetDetails(descriptor);
 }
diff --git a/src/v8utils.cc b/src/v8utils.cc
index 042a60f..627169e 100644
--- a/src/v8utils.cc
+++ b/src/v8utils.cc
@@ -53,6 +53,15 @@
 }
 
 
+void PrintPID(const char* format, ...) {
+  OS::Print("[%d] ", OS::GetCurrentProcessId());
+  va_list arguments;
+  va_start(arguments, format);
+  OS::VPrint(format, arguments);
+  va_end(arguments);
+}
+
+
 void Flush(FILE* out) {
   fflush(out);
 }
diff --git a/src/v8utils.h b/src/v8utils.h
index bb587e1..9072b4e 100644
--- a/src/v8utils.h
+++ b/src/v8utils.h
@@ -57,6 +57,9 @@
 void PRINTF_CHECKING PrintF(const char* format, ...);
 void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
 
+// Prepends the current process ID to the output.
+void PRINTF_CHECKING PrintPID(const char* format, ...);
+
 // Our version of fflush.
 void Flush(FILE* out);
 
diff --git a/src/version.cc b/src/version.cc
index 87c152e..5a0018d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     12
-#define BUILD_NUMBER      10
+#define BUILD_NUMBER      11
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 050c0d6..1259160 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1109,7 +1109,7 @@
   // We got a map in register rax. Get the enumeration cache from it.
   __ bind(&use_cache);
   __ LoadInstanceDescriptors(rax, rcx);
-  __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
+  __ movq(rcx, FieldOperand(rcx, DescriptorArray::kLastAddedOffset));
   __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
 
   // Set up the four remaining stack slots.
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 6bec93a..68e4396 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -320,24 +320,24 @@
 
 
 int LCodeGen::ToInteger32(LConstantOperand* op) const {
-  Handle<Object> value = chunk_->LookupLiteral(op);
+  HConstant* constant = chunk_->LookupConstant(op);
   ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
-  ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
-      value->Number());
-  return static_cast<int32_t>(value->Number());
+  ASSERT(constant->HasInteger32Value());
+  return constant->Integer32Value();
 }
 
 
 double LCodeGen::ToDouble(LConstantOperand* op) const {
-  Handle<Object> value = chunk_->LookupLiteral(op);
-  return value->Number();
+  HConstant* constant = chunk_->LookupConstant(op);
+  ASSERT(constant->HasDoubleValue());
+  return constant->DoubleValue();
 }
 
 
 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
-  Handle<Object> literal = chunk_->LookupLiteral(op);
+  HConstant* constant = chunk_->LookupConstant(op);
   ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
-  return literal;
+  return constant->handle();
 }
 
 
@@ -442,8 +442,8 @@
     XMMRegister reg = ToDoubleRegister(op);
     translation->StoreDoubleRegister(reg);
   } else if (op->IsConstantOperand()) {
-    Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op));
-    int src_index = DefineDeoptimizationLiteral(literal);
+    HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
+    int src_index = DefineDeoptimizationLiteral(constant->handle());
     translation->StoreLiteral(src_index);
   } else {
     UNREACHABLE();
@@ -5005,7 +5005,7 @@
   Register result = ToRegister(instr->result());
   __ LoadInstanceDescriptors(map, result);
   __ movq(result,
-          FieldOperand(result, DescriptorArray::kEnumerationIndexOffset));
+          FieldOperand(result, DescriptorArray::kLastAddedOffset));
   __ movq(result,
           FieldOperand(result, FixedArray::SizeFor(instr->idx())));
   Condition cc = masm()->CheckSmi(result);
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 642e951..f6ef45a 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -376,42 +376,6 @@
 }
 
 
-void LChunk::MarkEmptyBlocks() {
-  HPhase phase("L_Mark empty blocks", this);
-  for (int i = 0; i < graph()->blocks()->length(); ++i) {
-    HBasicBlock* block = graph()->blocks()->at(i);
-    int first = block->first_instruction_index();
-    int last = block->last_instruction_index();
-    LInstruction* first_instr = instructions()->at(first);
-    LInstruction* last_instr = instructions()->at(last);
-
-    LLabel* label = LLabel::cast(first_instr);
-    if (last_instr->IsGoto()) {
-      LGoto* goto_instr = LGoto::cast(last_instr);
-      if (label->IsRedundant() &&
-          !label->is_loop_header()) {
-        bool can_eliminate = true;
-        for (int i = first + 1; i < last && can_eliminate; ++i) {
-          LInstruction* cur = instructions()->at(i);
-          if (cur->IsGap()) {
-            LGap* gap = LGap::cast(cur);
-            if (!gap->IsRedundant()) {
-              can_eliminate = false;
-            }
-          } else {
-            can_eliminate = false;
-          }
-        }
-
-        if (can_eliminate) {
-          label->set_replacement(GetLabel(goto_instr->block_id()));
-        }
-      }
-    }
-  }
-}
-
-
 void LStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
   stream->Add(".");
@@ -463,81 +427,6 @@
 }
 
 
-void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
-  LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
-  int index = -1;
-  if (instr->IsControl()) {
-    instructions_.Add(gap, zone());
-    index = instructions_.length();
-    instructions_.Add(instr, zone());
-  } else {
-    index = instructions_.length();
-    instructions_.Add(instr, zone());
-    instructions_.Add(gap, zone());
-  }
-  if (instr->HasPointerMap()) {
-    pointer_maps_.Add(instr->pointer_map(), zone());
-    instr->pointer_map()->set_lithium_position(index);
-  }
-}
-
-
-LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
-  return LConstantOperand::Create(constant->id(), zone());
-}
-
-
-int LChunk::GetParameterStackSlot(int index) const {
-  // The receiver is at index 0, the first parameter at index 1, so we
-  // shift all parameter indexes down by the number of parameters, and
-  // make sure they end up negative so they are distinguishable from
-  // spill slots.
-  int result = index - info()->scope()->num_parameters() - 1;
-  ASSERT(result < 0);
-  return result;
-}
-
-// A parameter relative to ebp in the arguments stub.
-int LChunk::ParameterAt(int index) {
-  ASSERT(-1 <= index);  // -1 is the receiver.
-  return (1 + info()->scope()->num_parameters() - index) *
-      kPointerSize;
-}
-
-
-LGap* LChunk::GetGapAt(int index) const {
-  return LGap::cast(instructions_[index]);
-}
-
-
-bool LChunk::IsGapAt(int index) const {
-  return instructions_[index]->IsGap();
-}
-
-
-int LChunk::NearestGapPos(int index) const {
-  while (!IsGapAt(index)) index--;
-  return index;
-}
-
-
-void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
-  GetGapAt(index)->GetOrCreateParallelMove(
-      LGap::START, zone())->AddMove(from, to, zone());
-}
-
-
-Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
-  return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
-}
-
-
-Representation LChunk::LookupLiteralRepresentation(
-    LConstantOperand* operand) const {
-  return graph_->LookupValue(operand->index())->representation();
-}
-
-
 LChunk* LChunkBuilder::Build() {
   ASSERT(is_unused());
   chunk_ = new(zone()) LChunk(info(), graph());
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index a00867d..14a6c54 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -2178,71 +2178,13 @@
 
 
 class LChunkBuilder;
-class LChunk: public ZoneObject {
+class LChunk: public LChunkBase {
  public:
   LChunk(CompilationInfo* info, HGraph* graph)
-    : spill_slot_count_(0),
-      info_(info),
-      graph_(graph),
-      instructions_(32, graph->zone()),
-      pointer_maps_(8, graph->zone()),
-      inlined_closures_(1, graph->zone()) { }
-
-  void AddInstruction(LInstruction* instruction, HBasicBlock* block);
-  LConstantOperand* DefineConstantOperand(HConstant* constant);
-  Handle<Object> LookupLiteral(LConstantOperand* operand) const;
-  Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
+      : LChunkBase(info, graph) { }
 
   int GetNextSpillIndex(bool is_double);
   LOperand* GetNextSpillSlot(bool is_double);
-
-  int ParameterAt(int index);
-  int GetParameterStackSlot(int index) const;
-  int spill_slot_count() const { return spill_slot_count_; }
-  CompilationInfo* info() const { return info_; }
-  HGraph* graph() const { return graph_; }
-  const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
-  void AddGapMove(int index, LOperand* from, LOperand* to);
-  LGap* GetGapAt(int index) const;
-  bool IsGapAt(int index) const;
-  int NearestGapPos(int index) const;
-  void MarkEmptyBlocks();
-  const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
-  LLabel* GetLabel(int block_id) const {
-    HBasicBlock* block = graph_->blocks()->at(block_id);
-    int first_instruction = block->first_instruction_index();
-    return LLabel::cast(instructions_[first_instruction]);
-  }
-  int LookupDestination(int block_id) const {
-    LLabel* cur = GetLabel(block_id);
-    while (cur->replacement() != NULL) {
-      cur = cur->replacement();
-    }
-    return cur->block_id();
-  }
-  Label* GetAssemblyLabel(int block_id) const {
-    LLabel* label = GetLabel(block_id);
-    ASSERT(!label->HasReplacement());
-    return label->label();
-  }
-
-  const ZoneList<Handle<JSFunction> >* inlined_closures() const {
-    return &inlined_closures_;
-  }
-
-  void AddInlinedClosure(Handle<JSFunction> closure) {
-    inlined_closures_.Add(closure, zone());
-  }
-
-  Zone* zone() const { return graph_->zone(); }
-
- private:
-  int spill_slot_count_;
-  CompilationInfo* info_;
-  HGraph* const graph_;
-  ZoneList<LInstruction*> instructions_;
-  ZoneList<LPointerMap*> pointer_maps_;
-  ZoneList<Handle<JSFunction> > inlined_closures_;
 };
 
 
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index cda7549..4b8ca8f 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -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,13 +4463,17 @@
   // 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
   // index field does not contain a smi.
-  movq(rdx, FieldOperand(rdx, DescriptorArray::kEnumerationIndexOffset));
+  movq(rdx, FieldOperand(rdx, DescriptorArray::kLastAddedOffset));
   JumpIfSmi(rdx, call_runtime);
 
   // For all objects but the receiver, check that the cache is empty.