Version 3.19.14

Fixed crashes when calling new Array(a) with a single argument that could result in creating a holey array with a packed elements kind. (Chromium issue 245480)

Fixed issues in parallel compilation. (Chromium issue 248076)

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@15100 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 6117e56..907760a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-06-13: Version 3.19.14
+
+        Fixed crashes when calling new Array(a) with a single argument that
+        could result in creating a holey array with a packed elements kind.
+        (Chromium issue 245480)
+
+        Fixed issues in parallel compilation.
+        (Chromium issue 248076)
+
+        Performance and stability improvements on all platforms.
+
+
 2013-06-11: Version 3.19.13
 
         Performance and stability improvements on all platforms.
diff --git a/include/v8.h b/include/v8.h
index c0bec79..6fcc332 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -5333,7 +5333,7 @@
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 130;
+  static const int kEmptyStringRootIndex = 131;
 
   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
@@ -5343,10 +5343,10 @@
   static const int kNodeIsIndependentShift = 4;
   static const int kNodeIsPartiallyDependentShift = 5;
 
-  static const int kJSObjectType = 0xaf;
+  static const int kJSObjectType = 0xb0;
   static const int kFirstNonstringType = 0x80;
   static const int kOddballType = 0x83;
-  static const int kForeignType = 0x87;
+  static const int kForeignType = 0x88;
 
   static const int kUndefinedOddballKind = 5;
   static const int kNullOddballKind = 3;
diff --git a/src/api.cc b/src/api.cc
index 20496fe..5491971 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -183,6 +183,10 @@
   heap_stats.cell_space_size = &cell_space_size;
   intptr_t cell_space_capacity;
   heap_stats.cell_space_capacity = &cell_space_capacity;
+  intptr_t property_cell_space_size;
+  heap_stats.property_cell_space_size = &property_cell_space_size;
+  intptr_t property_cell_space_capacity;
+  heap_stats.property_cell_space_capacity = &property_cell_space_capacity;
   intptr_t lo_space_size;
   heap_stats.lo_space_size = &lo_space_size;
   int global_handle_count;
@@ -6162,7 +6166,7 @@
   ENTER_V8(isolate);
 
   for (i::Handle<i::Object> array_obj(obj->weak_first_array(), isolate);
-       *array_obj != i::Smi::FromInt(0);) {
+       !array_obj->IsUndefined();) {
     i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*array_obj));
     typed_array->Neuter();
     array_obj = i::handle(typed_array->weak_next(), isolate);
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 1e0d5c1..17831c8 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -179,24 +179,22 @@
 }
 
 
-Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
-  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+Handle<Cell> RelocInfo::target_cell_handle() {
+  ASSERT(rmode_ == RelocInfo::CELL);
   Address address = Memory::Address_at(pc_);
-  return Handle<JSGlobalPropertyCell>(
-      reinterpret_cast<JSGlobalPropertyCell**>(address));
+  return Handle<Cell>(reinterpret_cast<Cell**>(address));
 }
 
 
-JSGlobalPropertyCell* RelocInfo::target_cell() {
-  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
-  return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
+Cell* RelocInfo::target_cell() {
+  ASSERT(rmode_ == RelocInfo::CELL);
+  return Cell::FromValueAddress(Memory::Address_at(pc_));
 }
 
 
-void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
-                                WriteBarrierMode mode) {
-  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
-  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
+void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
+  ASSERT(rmode_ == RelocInfo::CELL);
+  Address address = cell->address() + Cell::kValueOffset;
   Memory::Address_at(pc_) = address;
   if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
     // TODO(1550) We are passing NULL as a slot because cell can never be on
@@ -286,8 +284,8 @@
     visitor->VisitEmbeddedPointer(this);
   } else if (RelocInfo::IsCodeTarget(mode)) {
     visitor->VisitCodeTarget(this);
-  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
-    visitor->VisitGlobalPropertyCell(this);
+  } else if (mode == RelocInfo::CELL) {
+    visitor->VisitCell(this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     visitor->VisitExternalReference(this);
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
@@ -314,8 +312,8 @@
     StaticVisitor::VisitEmbeddedPointer(heap, this);
   } else if (RelocInfo::IsCodeTarget(mode)) {
     StaticVisitor::VisitCodeTarget(heap, this);
-  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
-    StaticVisitor::VisitGlobalPropertyCell(heap, this);
+  } else if (mode == RelocInfo::CELL) {
+    StaticVisitor::VisitCell(heap, this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     StaticVisitor::VisitExternalReference(this);
   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index b26bf7e..ee6eb97 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -3504,7 +3504,7 @@
     // Get the map location in scratch and patch it.
     __ GetRelocatedValueLocation(inline_site, scratch);
     __ ldr(scratch, MemOperand(scratch));
-    __ str(map, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
+    __ str(map, FieldMemOperand(scratch, Cell::kValueOffset));
   }
 
   // Register mapping: r3 is object map and r4 is function prototype.
@@ -4637,7 +4637,7 @@
             masm->isolate()->heap()->the_hole_value());
 
   // Load the cache state into r3.
-  __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+  __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
 
   // A monomorphic cache hit or an already megamorphic state: invoke the
   // function without changing the state.
@@ -4652,10 +4652,10 @@
   // MegamorphicSentinel is an immortal immovable object (undefined) so no
   // write-barrier is needed.
   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex, ne);
-  __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset), ne);
+  __ str(ip, FieldMemOperand(r2, Cell::kValueOffset), ne);
 
   // An uninitialized cache is patched with the function.
-  __ str(r1, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset), eq);
+  __ str(r1, FieldMemOperand(r2, Cell::kValueOffset), eq);
   // No need for a write barrier here - cells are rescanned.
 
   __ bind(&done);
@@ -4677,7 +4677,7 @@
             masm->isolate()->heap()->the_hole_value());
 
   // Load the cache state into r3.
-  __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+  __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
 
   // A monomorphic cache hit or an already megamorphic state: invoke the
   // function without changing the state.
@@ -4711,7 +4711,7 @@
   // write-barrier is needed.
   __ bind(&megamorphic);
   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
-  __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+  __ str(ip, FieldMemOperand(r2, Cell::kValueOffset));
   __ jmp(&done);
 
   // An uninitialized cache is patched with the function or sentinel to
@@ -4729,11 +4729,11 @@
       TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(),
           GetInitialFastElementsKind());
   __ mov(r3, Operand(initial_kind_sentinel));
-  __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+  __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
   __ b(&done);
 
   __ bind(&not_array_function);
-  __ str(r1, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+  __ str(r1, FieldMemOperand(r2, Cell::kValueOffset));
   // No need for a write barrier here - cells are rescanned.
 
   __ bind(&done);
@@ -4809,7 +4809,7 @@
     ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
               masm->isolate()->heap()->undefined_value());
     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
-    __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+    __ str(ip, FieldMemOperand(r2, Cell::kValueOffset));
   }
   // Check for function proxy.
   __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE));
@@ -7332,14 +7332,13 @@
     __ CompareObjectType(r3, r3, r4, MAP_TYPE);
     __ Assert(eq, "Unexpected initial map for Array function");
 
-    // We should either have undefined in ebx or a valid jsglobalpropertycell
+    // We should either have undefined in ebx or a valid cell
     Label okay_here;
-    Handle<Map> global_property_cell_map(
-        masm->isolate()->heap()->global_property_cell_map());
+    Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
     __ cmp(r2, Operand(undefined_sentinel));
     __ b(eq, &okay_here);
     __ ldr(r3, FieldMemOperand(r2, 0));
-    __ cmp(r3, Operand(global_property_cell_map));
+    __ cmp(r3, Operand(cell_map));
     __ Assert(eq, "Expected property cell in register ebx");
     __ bind(&okay_here);
   }
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 8b24bf1..39a4018 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -129,7 +129,7 @@
   CompilationInfo* info = info_;
   handler_table_ =
       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
-  profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
+  profiling_counter_ = isolate()->factory()->NewCell(
       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
   SetFunctionPosition(function());
   Comment cmnt(masm_, "[ function compiled by full code generator");
@@ -327,9 +327,9 @@
 
 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
   __ mov(r2, Operand(profiling_counter_));
-  __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+  __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
   __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC);
-  __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+  __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
 }
 
 
@@ -345,7 +345,7 @@
   }
   __ mov(r2, Operand(profiling_counter_));
   __ mov(r3, Operand(Smi::FromInt(reset_value)));
-  __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+  __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
 }
 
 
@@ -1164,15 +1164,13 @@
   Label non_proxy;
   __ bind(&fixed_array);
 
-  Handle<JSGlobalPropertyCell> cell =
-      isolate()->factory()->NewJSGlobalPropertyCell(
-          Handle<Object>(
-              Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
-              isolate()));
+  Handle<Cell> cell = isolate()->factory()->NewCell(
+      Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
+                     isolate()));
   RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
   __ LoadHeapObject(r1, cell);
   __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
-  __ str(r2, FieldMemOperand(r1, JSGlobalPropertyCell::kValueOffset));
+  __ str(r2, FieldMemOperand(r1, Cell::kValueOffset));
 
   __ mov(r1, Operand(Smi::FromInt(1)));  // Smi indicates slow check
   __ ldr(r2, MemOperand(sp, 0 * kPointerSize));  // Get enumerated object
@@ -1991,8 +1989,12 @@
   VisitForStackValue(expr->expression());
 
   switch (expr->yield_kind()) {
-    case Yield::INITIAL:
-    case Yield::SUSPEND: {
+    case Yield::SUSPEND:
+      // Pop value from top-of-stack slot; box result into result register.
+      EmitCreateIteratorResult(false);
+      __ push(result_register());
+      // Fall through.
+    case Yield::INITIAL: {
       VisitForStackValue(expr->generator_object());
       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
       __ ldr(context_register(),
@@ -2001,12 +2003,8 @@
       Label resume;
       __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
       __ b(ne, &resume);
-      if (expr->yield_kind() == Yield::SUSPEND) {
-        EmitReturnIteratorResult(false);
-      } else {
-        __ pop(result_register());
-        EmitReturnSequence();
-      }
+      __ pop(result_register());
+      EmitReturnSequence();
 
       __ bind(&resume);
       context()->Plug(result_register());
@@ -2018,7 +2016,10 @@
       __ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
       __ str(r1, FieldMemOperand(result_register(),
                                  JSGeneratorObject::kContinuationOffset));
-      EmitReturnIteratorResult(true);
+      // Pop value from top-of-stack slot, box result into result register.
+      EmitCreateIteratorResult(true);
+      EmitUnwindBeforeReturn();
+      EmitReturnSequence();
       break;
     }
 
@@ -2048,10 +2049,10 @@
 
       // try { received = yield result.value }
       __ bind(&l_try);
-      __ pop(r0);                                        // result.value
+      EmitCreateIteratorResult(false);                   // pop and box to r0
       __ PushTryHandler(StackHandler::CATCH, expr->index());
       const int handler_size = StackHandlerConstants::kSize;
-      __ push(r0);                                       // result.value
+      __ push(r0);                                       // result
       __ ldr(r3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size));  // g
       __ push(r3);                                       // g
       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
@@ -2059,7 +2060,8 @@
              MemOperand(fp, StandardFrameConstants::kContextOffset));
       __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
       __ b(ne, &l_resume);
-      EmitReturnIteratorResult(false);
+      __ pop(r0);                                        // result
+      EmitReturnSequence();
       __ bind(&l_resume);                                // received in r0
       __ PopTryHandler();
 
@@ -2214,13 +2216,20 @@
 }
 
 
-void FullCodeGenerator::EmitReturnIteratorResult(bool done) {
+void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label gc_required;
   Label allocated;
 
   Handle<Map> map(isolate()->native_context()->generator_result_map());
 
   __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT);
+  __ jmp(&allocated);
+
+  __ bind(&gc_required);
+  __ Push(Smi::FromInt(map->instance_size()));
+  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+  __ ldr(context_register(),
+         MemOperand(fp, StandardFrameConstants::kContextOffset));
 
   __ bind(&allocated);
   __ mov(r1, Operand(map));
@@ -2240,26 +2249,6 @@
   // root set.
   __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset,
                       r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
-
-  if (done) {
-    // Exit all nested statements.
-    NestedStatement* current = nesting_stack_;
-    int stack_depth = 0;
-    int context_length = 0;
-    while (current != NULL) {
-      current = current->Exit(&stack_depth, &context_length);
-    }
-    __ Drop(stack_depth);
-  }
-
-  EmitReturnSequence();
-
-  __ bind(&gc_required);
-  __ Push(Smi::FromInt(map->instance_size()));
-  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ ldr(context_register(),
-         MemOperand(fp, StandardFrameConstants::kContextOffset));
-  __ jmp(&allocated);
 }
 
 
@@ -2683,8 +2672,7 @@
   flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
   Handle<Object> uninitialized =
       TypeFeedbackCells::UninitializedSentinel(isolate());
-  Handle<JSGlobalPropertyCell> cell =
-      isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+  Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
   RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
   __ mov(r2, Operand(cell));
 
@@ -2879,8 +2867,7 @@
   // Record call targets in unoptimized code.
   Handle<Object> uninitialized =
       TypeFeedbackCells::UninitializedSentinel(isolate());
-  Handle<JSGlobalPropertyCell> cell =
-      isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+  Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
   RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
   __ mov(r2, Operand(cell));
 
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index fbb9c6e..1d4ed5f 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -929,7 +929,7 @@
   BailoutId ast_id = hydrogen_env->ast_id();
   ASSERT(!ast_id.IsNone() ||
          hydrogen_env->frame_type() != JS_FUNCTION);
-  int value_count = hydrogen_env->length();
+  int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
   LEnvironment* result = new(zone()) LEnvironment(
       hydrogen_env->closure(),
       hydrogen_env->frame_type(),
@@ -940,13 +940,15 @@
       outer,
       hydrogen_env->entry(),
       zone());
+  bool needs_arguments_object_materialization = false;
   int argument_index = *argument_index_accumulator;
-  for (int i = 0; i < value_count; ++i) {
+  for (int i = 0; i < hydrogen_env->length(); ++i) {
     if (hydrogen_env->is_special_index(i)) continue;
 
     HValue* value = hydrogen_env->values()->at(i);
     LOperand* op = NULL;
     if (value->IsArgumentsObject()) {
+      needs_arguments_object_materialization = true;
       op = NULL;
     } else if (value->IsPushArgument()) {
       op = new(zone()) LArgument(argument_index++);
@@ -958,6 +960,22 @@
                      value->CheckFlag(HInstruction::kUint32));
   }
 
+  if (needs_arguments_object_materialization) {
+    HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+        ? graph()->GetArgumentsObject()
+        : hydrogen_env->entry()->arguments_object();
+    ASSERT(arguments->IsLinked());
+    for (int i = 1; i < arguments->arguments_count(); ++i) {
+      HValue* value = arguments->arguments_values()->at(i);
+      ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+      ASSERT(HInstruction::cast(value)->IsLinked());
+      LOperand* op = UseAny(value);
+      result->AddValue(op,
+                       value->representation(),
+                       value->CheckFlag(HInstruction::kUint32));
+    }
+  }
+
   if (hydrogen_env->frame_type() == JS_FUNCTION) {
     *argument_index_accumulator = argument_index;
   }
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 96befb0..253c63d 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -87,20 +87,7 @@
     RegisterDependentCodeForEmbeddedMaps(code);
   }
   PopulateDeoptimizationData(code);
-  for (int i = 0 ; i < prototype_maps_.length(); i++) {
-    prototype_maps_.at(i)->AddDependentCode(
-        DependentCode::kPrototypeCheckGroup, code);
-  }
-  for (int i = 0 ; i < transition_maps_.length(); i++) {
-    transition_maps_.at(i)->AddDependentCode(
-        DependentCode::kTransitionGroup, code);
-  }
-  if (graph()->depends_on_empty_array_proto_elements()) {
-    isolate()->initial_object_prototype()->map()->AddDependentCode(
-        DependentCode::kElementsCantBeAddedGroup, code);
-    isolate()->initial_array_prototype()->map()->AddDependentCode(
-        DependentCode::kElementsCantBeAddedGroup, code);
-  }
+  info()->CommitDependentMaps(code);
 }
 
 
@@ -593,27 +580,15 @@
 
 
 void LCodeGen::WriteTranslation(LEnvironment* environment,
-                                Translation* translation,
-                                int* pushed_arguments_index,
-                                int* pushed_arguments_count) {
+                                Translation* translation) {
   if (environment == NULL) return;
 
   // The translation includes one command per value in the environment.
-  int translation_size = environment->values()->length();
+  int translation_size = environment->translation_size();
   // The output frame height does not include the parameters.
   int height = translation_size - environment->parameter_count();
 
-  // Function parameters are arguments to the outermost environment. The
-  // arguments index points to the first element of a sequence of tagged
-  // values on the stack that represent the arguments. This needs to be
-  // kept in sync with the LArgumentsElements implementation.
-  *pushed_arguments_index = -environment->parameter_count();
-  *pushed_arguments_count = environment->parameter_count();
-
-  WriteTranslation(environment->outer(),
-                   translation,
-                   pushed_arguments_index,
-                   pushed_arguments_count);
+  WriteTranslation(environment->outer(), translation);
   bool has_closure_id = !info()->closure().is_null() &&
       !info()->closure().is_identical_to(environment->closure());
   int closure_id = has_closure_id
@@ -645,23 +620,6 @@
       break;
   }
 
-  // Inlined frames which push their arguments cause the index to be
-  // bumped and another stack area to be used for materialization,
-  // otherwise actual argument values are unknown for inlined frames.
-  bool arguments_known = true;
-  int arguments_index = *pushed_arguments_index;
-  int arguments_count = *pushed_arguments_count;
-  if (environment->entry() != NULL) {
-    arguments_known = environment->entry()->arguments_pushed();
-    arguments_index = arguments_index < 0
-        ? GetStackSlotCount() : arguments_index + arguments_count;
-    arguments_count = environment->entry()->arguments_count() + 1;
-    if (environment->entry()->arguments_pushed()) {
-      *pushed_arguments_index = arguments_index;
-      *pushed_arguments_count = arguments_count;
-    }
-  }
-
   for (int i = 0; i < translation_size; ++i) {
     LOperand* value = environment->values()->at(i);
     // spilled_registers_ and spilled_double_registers_ are either
@@ -673,10 +631,7 @@
         AddToTranslation(translation,
                          environment->spilled_registers()[value->index()],
                          environment->HasTaggedValueAt(i),
-                         environment->HasUint32ValueAt(i),
-                         arguments_known,
-                         arguments_index,
-                         arguments_count);
+                         environment->HasUint32ValueAt(i));
       } else if (
           value->IsDoubleRegister() &&
           environment->spilled_double_registers()[value->index()] != NULL) {
@@ -685,20 +640,36 @@
             translation,
             environment->spilled_double_registers()[value->index()],
             false,
-            false,
-            arguments_known,
-            arguments_index,
-            arguments_count);
+            false);
       }
     }
 
+    // TODO(mstarzinger): Introduce marker operands to indicate that this value
+    // is not present and must be reconstructed from the deoptimizer. Currently
+    // this is only used for the arguments object.
+    if (value == NULL) {
+      int arguments_count = environment->values()->length() - translation_size;
+      translation->BeginArgumentsObject(arguments_count);
+      for (int i = 0; i < arguments_count; ++i) {
+        LOperand* value = environment->values()->at(translation_size + i);
+        ASSERT(environment->spilled_registers() == NULL ||
+               !value->IsRegister() ||
+               environment->spilled_registers()[value->index()] == NULL);
+        ASSERT(environment->spilled_registers() == NULL ||
+               !value->IsDoubleRegister() ||
+               environment->spilled_double_registers()[value->index()] == NULL);
+        AddToTranslation(translation,
+                         value,
+                         environment->HasTaggedValueAt(translation_size + i),
+                         environment->HasUint32ValueAt(translation_size + i));
+      }
+      continue;
+    }
+
     AddToTranslation(translation,
                      value,
                      environment->HasTaggedValueAt(i),
-                     environment->HasUint32ValueAt(i),
-                     arguments_known,
-                     arguments_index,
-                     arguments_count);
+                     environment->HasUint32ValueAt(i));
   }
 }
 
@@ -706,17 +677,8 @@
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged,
-                                bool is_uint32,
-                                bool arguments_known,
-                                int arguments_index,
-                                int arguments_count) {
-  if (op == NULL) {
-    // TODO(twuerthinger): Introduce marker operands to indicate that this value
-    // is not present and must be reconstructed from the deoptimizer. Currently
-    // this is only used for the arguments object.
-    translation->StoreArgumentsObject(
-        arguments_known, arguments_index, arguments_count);
-  } else if (op->IsStackSlot()) {
+                                bool is_uint32) {
+  if (op->IsStackSlot()) {
     if (is_tagged) {
       translation->StoreStackSlot(op->index());
     } else if (is_uint32) {
@@ -823,8 +785,6 @@
 
     int frame_count = 0;
     int jsframe_count = 0;
-    int args_index = 0;
-    int args_count = 0;
     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
       ++frame_count;
       if (e->frame_type() == JS_FUNCTION) {
@@ -832,7 +792,7 @@
       }
     }
     Translation translation(&translations_, frame_count, jsframe_count, zone());
-    WriteTranslation(environment, &translation, &args_index, &args_count);
+    WriteTranslation(environment, &translation);
     int deoptimization_index = deoptimizations_.length();
     int pc_offset = masm()->pc_offset();
     environment->Register(deoptimization_index,
@@ -2802,8 +2762,7 @@
     // root array to force relocation to be able to later patch with
     // the cached map.
     PredictableCodeSizeScope predictable(masm_, 5 * Assembler::kInstrSize);
-    Handle<JSGlobalPropertyCell> cell =
-        factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
+    Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value());
     __ mov(ip, Operand(Handle<Object>(cell)));
     __ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
     __ cmp(map, Operand(ip));
@@ -2965,7 +2924,7 @@
 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
   Register result = ToRegister(instr->result());
   __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell())));
-  __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
+  __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset));
   if (instr->hydrogen()->RequiresHoleCheck()) {
     __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
     __ cmp(result, ip);
@@ -3000,13 +2959,13 @@
   if (instr->hydrogen()->RequiresHoleCheck()) {
     // We use a temp to check the payload (CompareRoot might clobber ip).
     Register payload = ToRegister(instr->temp());
-    __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
+    __ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset));
     __ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
     DeoptimizeIf(eq, instr->environment());
   }
 
   // Store the value.
-  __ str(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
+  __ str(value, FieldMemOperand(cell, Cell::kValueOffset));
   // Cells are always rescanned, so no write barrier here.
 }
 
@@ -4219,8 +4178,26 @@
     ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
     CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
   } else if (instr->arity() == 1) {
+    Label done;
+    if (IsFastPackedElementsKind(kind)) {
+      Label packed_case;
+      // We might need a change here
+      // look at the first argument
+      __ ldr(r5, MemOperand(sp, 0));
+      __ cmp(r5, Operand::Zero());
+      __ b(eq, &packed_case);
+
+      ElementsKind holey_kind = GetHoleyElementsKind(kind);
+      ArraySingleArgumentConstructorStub stub(holey_kind,
+                                              disable_allocation_sites);
+      CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+      __ jmp(&done);
+      __ bind(&packed_case);
+    }
+
     ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites);
     CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+    __ bind(&done);
   } else {
     ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites);
     CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
@@ -4267,9 +4244,6 @@
   }
 
   if (!transition.is_null()) {
-    if (transition->CanBeDeprecated()) {
-      transition_maps_.Add(transition, info()->zone());
-    }
     __ mov(scratch, Operand(transition));
     __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
     if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
@@ -5279,10 +5253,9 @@
   AllowDeferredHandleDereference smi_check;
   if (isolate()->heap()->InNewSpace(*target)) {
     Register reg = ToRegister(instr->value());
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(target);
+    Handle<Cell> cell = isolate()->factory()->NewJSGlobalPropertyCell(target);
     __ mov(ip, Operand(Handle<Object>(cell)));
-    __ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
+    __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset));
     __ cmp(reg, ip);
   } else {
     __ cmp(reg, Operand(target));
@@ -5382,11 +5355,7 @@
 
   ASSERT(prototypes->length() == maps->length());
 
-  if (instr->hydrogen()->CanOmitPrototypeChecks()) {
-    for (int i = 0; i < maps->length(); i++) {
-      prototype_maps_.Add(maps->at(i), info()->zone());
-    }
-  } else {
+  if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
     for (int i = 0; i < prototypes->length(); i++) {
       __ LoadHeapObject(prototype_reg, prototypes->at(i));
       __ ldr(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index f264259..aeba5ea 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -56,8 +56,6 @@
         deoptimizations_(4, info->zone()),
         deopt_jump_table_(4, info->zone()),
         deoptimization_literals_(8, info->zone()),
-        prototype_maps_(0, info->zone()),
-        transition_maps_(0, info->zone()),
         inlined_function_count_(0),
         scope_(info->scope()),
         status_(UNUSED),
@@ -173,10 +171,7 @@
                                  int additional_offset);
 
   // Emit frame translation commands for an environment.
-  void WriteTranslation(LEnvironment* environment,
-                        Translation* translation,
-                        int* arguments_index,
-                        int* arguments_count);
+  void WriteTranslation(LEnvironment* environment, Translation* translation);
 
   // Declare methods that deal with the individual node types.
 #define DECLARE_DO(type) void Do##type(L##type* node);
@@ -295,10 +290,7 @@
   void AddToTranslation(Translation* translation,
                         LOperand* op,
                         bool is_tagged,
-                        bool is_uint32,
-                        bool arguments_known,
-                        int arguments_index,
-                        int arguments_count);
+                        bool is_uint32);
   void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -406,8 +398,6 @@
   ZoneList<LEnvironment*> deoptimizations_;
   ZoneList<Deoptimizer::JumpTableEntry> deopt_jump_table_;
   ZoneList<Handle<Object> > deoptimization_literals_;
-  ZoneList<Handle<Map> > prototype_maps_;
-  ZoneList<Handle<Map> > transition_maps_;
   int inlined_function_count_;
   Scope* const scope_;
   Status status_;
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index f3cfdc7..4b6eac2 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -400,10 +400,9 @@
                                     Handle<HeapObject> object) {
   AllowDeferredHandleDereference using_raw_address;
   if (isolate()->heap()->InNewSpace(*object)) {
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(object);
+    Handle<Cell> cell = isolate()->factory()->NewCell(object);
     mov(result, Operand(cell));
-    ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
+    ldr(result, FieldMemOperand(result, Cell::kValueOffset));
   } else {
     mov(result, Operand(object));
   }
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 3595b52..1ccc106 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -427,12 +427,10 @@
                                       Handle<Name> name,
                                       Register scratch,
                                       Label* miss) {
-  Handle<JSGlobalPropertyCell> cell =
-      GlobalObject::EnsurePropertyCell(global, name);
+  Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name);
   ASSERT(cell->value()->IsTheHole());
   __ mov(scratch, Operand(cell));
-  __ ldr(scratch,
-         FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
+  __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset));
   __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
   __ cmp(scratch, ip);
   __ b(ne, miss);
@@ -1586,12 +1584,12 @@
 
 
 void CallStubCompiler::GenerateLoadFunctionFromCell(
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Label* miss) {
   // Get the value from the cell.
   __ mov(r3, Operand(cell));
-  __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
+  __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset));
 
   // Check that the cell contains the same function.
   if (heap()->InNewSpace(*function)) {
@@ -1662,7 +1660,7 @@
 Handle<Code> CallStubCompiler::CompileArrayPushCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -1915,7 +1913,7 @@
 Handle<Code> CallStubCompiler::CompileArrayPopCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -1997,7 +1995,7 @@
 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2079,7 +2077,7 @@
 Handle<Code> CallStubCompiler::CompileStringCharAtCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2162,7 +2160,7 @@
 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2234,7 +2232,7 @@
 Handle<Code> CallStubCompiler::CompileMathFloorCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2342,7 +2340,7 @@
 Handle<Code> CallStubCompiler::CompileMathAbsCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2441,7 +2439,7 @@
     const CallOptimization& optimization,
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   Counters* counters = isolate()->counters();
@@ -2613,7 +2611,7 @@
     Handle<JSFunction> function) {
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(object, holder,
-                                          Handle<JSGlobalPropertyCell>::null(),
+                                          Handle<Cell>::null(),
                                           function, Handle<String>::cast(name));
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
@@ -2859,14 +2857,12 @@
   // global object. We bail out to the runtime system to do that.
   __ mov(scratch1(), Operand(cell));
   __ LoadRoot(scratch2(), Heap::kTheHoleValueRootIndex);
-  __ ldr(scratch3(),
-         FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
+  __ ldr(scratch3(), FieldMemOperand(scratch1(), Cell::kValueOffset));
   __ cmp(scratch3(), scratch2());
   __ b(eq, &miss);
 
   // Store the value in the cell.
-  __ str(value(),
-         FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
+  __ str(value(), FieldMemOperand(scratch1(), Cell::kValueOffset));
   // Cells are always rescanned, so no write barrier here.
 
   Counters* counters = isolate()->counters();
@@ -3002,7 +2998,7 @@
 
   // Get the value from the cell.
   __ mov(r3, Operand(cell));
-  __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
+  __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset));
 
   // Check for deleted property if property can actually be deleted.
   if (!is_dont_delete) {
diff --git a/src/assembler.cc b/src/assembler.cc
index 6b0c4b8..626fd4f 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -724,7 +724,7 @@
   // generation.
   int mode_mask = RelocInfo::kCodeTargetMask |
                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
-                  RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
+                  RelocInfo::ModeMask(RelocInfo::CELL) |
                   RelocInfo::kApplyMask;
   RelocIterator it(desc, mode_mask);
   return !it.done();
@@ -754,8 +754,8 @@
       return "code target";
     case RelocInfo::CODE_TARGET_WITH_ID:
       return "code target with id";
-    case RelocInfo::GLOBAL_PROPERTY_CELL:
-      return "global property cell";
+    case RelocInfo::CELL:
+      return "property cell";
     case RelocInfo::RUNTIME_ENTRY:
       return "runtime entry";
     case RelocInfo::JS_RETURN:
@@ -830,7 +830,7 @@
     case EMBEDDED_OBJECT:
       Object::VerifyPointer(target_object());
       break;
-    case GLOBAL_PROPERTY_CELL:
+    case CELL:
       Object::VerifyPointer(target_cell());
       break;
     case DEBUG_BREAK:
diff --git a/src/assembler.h b/src/assembler.h
index 2d9e727..f66f8bf 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -254,7 +254,7 @@
     CODE_TARGET_CONTEXT,  // Code target used for contextual loads and stores.
     DEBUG_BREAK,  // Code target for the debugger statement.
     EMBEDDED_OBJECT,
-    GLOBAL_PROPERTY_CELL,
+    CELL,
 
     // Everything after runtime_entry (inclusive) is not GC'ed.
     RUNTIME_ENTRY,
@@ -282,7 +282,7 @@
     FIRST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
     LAST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
     LAST_CODE_ENUM = DEBUG_BREAK,
-    LAST_GCED_ENUM = GLOBAL_PROPERTY_CELL,
+    LAST_GCED_ENUM = CELL,
     // Modes <= LAST_COMPACT_ENUM are guaranteed to have compact encoding.
     LAST_COMPACT_ENUM = CODE_TARGET_WITH_ID,
     LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE
@@ -386,9 +386,9 @@
   INLINE(void set_target_runtime_entry(Address target,
                                        WriteBarrierMode mode =
                                            UPDATE_WRITE_BARRIER));
-  INLINE(JSGlobalPropertyCell* target_cell());
-  INLINE(Handle<JSGlobalPropertyCell> target_cell_handle());
-  INLINE(void set_target_cell(JSGlobalPropertyCell* cell,
+  INLINE(Cell* target_cell());
+  INLINE(Handle<Cell> target_cell_handle());
+  INLINE(void set_target_cell(Cell* cell,
                               WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
   INLINE(Code* code_age_stub());
   INLINE(void set_code_age_stub(Code* stub));
diff --git a/src/ast.cc b/src/ast.cc
index a5d1e2d..0ebbd35 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -503,19 +503,7 @@
 
 
 void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
-  TypeInfo info = oracle->SwitchType(this);
-  if (info.IsUninitialized()) info = TypeInfo::Unknown();
-  if (info.IsSmi()) {
-    compare_type_ = SMI_ONLY;
-  } else if (info.IsInternalizedString()) {
-    compare_type_ = NAME_ONLY;
-  } else if (info.IsNonInternalizedString()) {
-    compare_type_ = STRING_ONLY;
-  } else if (info.IsNonPrimitive()) {
-    compare_type_ = OBJECT_ONLY;
-  } else {
-    ASSERT(compare_type_ == NONE);
-  }
+  compare_type_ = oracle->ClauseType(CompareId());
 }
 
 
@@ -570,11 +558,11 @@
 bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
                                LookupResult* lookup) {
   target_ = Handle<JSFunction>::null();
-  cell_ = Handle<JSGlobalPropertyCell>::null();
+  cell_ = Handle<Cell>::null();
   ASSERT(lookup->IsFound() &&
          lookup->type() == NORMAL &&
          lookup->holder() == *global);
-  cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup));
+  cell_ = Handle<Cell>(global->GetPropertyCell(lookup));
   if (cell_->value()->IsJSFunction()) {
     Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
     // If the function is in new space we assume it's more likely to
@@ -685,17 +673,11 @@
 }
 
 
+// TODO(rossberg): this function (and all other RecordTypeFeedback functions)
+// should disappear once we use the common type field in the AST consistently.
 void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
-  oracle->CompareType(this, &left_type_, &right_type_, &overall_type_);
-  if (!overall_type_.IsUninitialized() && overall_type_.IsNonPrimitive() &&
-      (op_ == Token::EQ || op_ == Token::EQ_STRICT)) {
-    map_ = oracle->GetCompareMap(this);
-  } else {
-    // May be a compare to nil.
-    map_ = oracle->CompareNilMonomorphicReceiverType(this);
-    if (op_ != Token::EQ_STRICT)
-      compare_nil_types_ = oracle->CompareNilTypes(this);
-  }
+  oracle->CompareTypes(CompareOperationFeedbackId(),
+      &left_type_, &right_type_, &overall_type_, &compare_nil_type_);
 }
 
 
@@ -1072,7 +1054,7 @@
     : label_(label),
       statements_(statements),
       position_(pos),
-      compare_type_(NONE),
+      compare_type_(Type::None(), isolate),
       compare_id_(AstNode::GetNextId(isolate)),
       entry_id_(AstNode::GetNextId(isolate)) {
 }
diff --git a/src/ast.h b/src/ast.h
index 219a69b..b7ada60 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -358,6 +358,7 @@
 
   // Expression type
   Handle<Type> type() { return type_; }
+  void set_type(Handle<Type> type) { type_ = type; }
 
   // Type feedback information for assignments and properties.
   virtual bool IsMonomorphic() {
@@ -388,7 +389,7 @@
 
  protected:
   explicit Expression(Isolate* isolate)
-      : type_(Type::Any(), isolate),
+      : type_(Type::None(), isolate),
         id_(GetNextId(isolate)),
         test_id_(GetNextId(isolate)) {}
 
@@ -1106,24 +1107,15 @@
   // Type feedback information.
   TypeFeedbackId CompareId() { return compare_id_; }
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
-  bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
-  bool IsNameCompare() { return compare_type_ == NAME_ONLY; }
-  bool IsStringCompare() { return compare_type_ == STRING_ONLY; }
-  bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; }
+  Handle<Type> compare_type() { return compare_type_; }
 
  private:
   Expression* label_;
   Label body_target_;
   ZoneList<Statement*>* statements_;
   int position_;
-  enum CompareTypeFeedback {
-    NONE,
-    SMI_ONLY,
-    NAME_ONLY,
-    STRING_ONLY,
-    OBJECT_ONLY
-  };
-  CompareTypeFeedback compare_type_;
+  Handle<Type> compare_type_;
+
   const TypeFeedbackId compare_id_;
   const BailoutId entry_id_;
 };
@@ -1705,7 +1697,7 @@
   // as the holder!
   Handle<JSObject> holder() { return holder_; }
 
-  Handle<JSGlobalPropertyCell> cell() { return cell_; }
+  Handle<Cell> cell() { return cell_; }
 
   bool ComputeTarget(Handle<Map> type, Handle<String> name);
   bool ComputeGlobalTarget(Handle<GlobalObject> global, LookupResult* lookup);
@@ -1745,7 +1737,7 @@
   SmallMapList receiver_types_;
   Handle<JSFunction> target_;
   Handle<JSObject> holder_;
-  Handle<JSGlobalPropertyCell> cell_;
+  Handle<Cell> cell_;
 
   const BailoutId return_id_;
 };
@@ -1765,7 +1757,7 @@
   virtual bool IsMonomorphic() { return is_monomorphic_; }
   Handle<JSFunction> target() const { return target_; }
   ElementsKind elements_kind() const { return elements_kind_; }
-  Handle<JSGlobalPropertyCell> allocation_info_cell() const {
+  Handle<Cell> allocation_info_cell() const {
     return allocation_info_cell_;
   }
 
@@ -1792,7 +1784,7 @@
   bool is_monomorphic_;
   Handle<JSFunction> target_;
   ElementsKind elements_kind_;
-  Handle<JSGlobalPropertyCell> allocation_info_cell_;
+  Handle<Cell> allocation_info_cell_;
 
   const BailoutId return_id_;
 };
@@ -2003,11 +1995,10 @@
   // Type feedback information.
   TypeFeedbackId CompareOperationFeedbackId() const { return reuse(id()); }
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
-  TypeInfo left_type() const { return left_type_; }
-  TypeInfo right_type() const { return right_type_; }
-  TypeInfo overall_type() const { return overall_type_; }
-  byte compare_nil_types() const { return compare_nil_types_; }
-  Handle<Map> map() const { return map_; }
+  Handle<Type> left_type() const { return left_type_; }
+  Handle<Type> right_type() const { return right_type_; }
+  Handle<Type> overall_type() const { return overall_type_; }
+  Handle<Type> compare_nil_type() const { return compare_nil_type_; }
 
   // Match special cases.
   bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
@@ -2034,11 +2025,10 @@
   Expression* right_;
   int pos_;
 
-  TypeInfo left_type_;
-  TypeInfo right_type_;
-  TypeInfo overall_type_;
-  byte compare_nil_types_;
-  Handle<Map> map_;
+  Handle<Type> left_type_;
+  Handle<Type> right_type_;
+  Handle<Type> overall_type_;
+  Handle<Type> compare_nil_type_;
 };
 
 
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index a51a9b1..0b39faa 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -2499,6 +2499,7 @@
         Handle<Name> key = Handle<Name>(Name::cast(raw_key));
         Handle<Object> value = Handle<Object>(properties->ValueAt(i),
                                               isolate());
+        ASSERT(!value->IsCell());
         if (value->IsJSGlobalPropertyCell()) {
           value = Handle<Object>(JSGlobalPropertyCell::cast(*value)->value(),
                                  isolate());
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 99c4db5..e1e25fb 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -733,12 +733,13 @@
 
 template <>
 HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
+  Isolate* isolate = graph()->isolate();
   CompareNilICStub* stub = casted_stub();
   HIfContinuation continuation;
-  Handle<Map> sentinel_map(graph()->isolate()->heap()->meta_map());
-  BuildCompareNil(GetParameter(0),
-                  stub->GetTypes(), sentinel_map,
-                  RelocInfo::kNoPosition, &continuation);
+  Handle<Map> sentinel_map(isolate->heap()->meta_map());
+  Handle<Type> type =
+      CompareNilICStub::StateToType(isolate, stub->GetState(), sentinel_map);
+  BuildCompareNil(GetParameter(0), type, RelocInfo::kNoPosition, &continuation);
   IfBuilder if_nil(this, &continuation);
   if_nil.Then();
   if (continuation.IsFalseReachable()) {
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 6b6e250..5bec7e0 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -431,24 +431,24 @@
 
 
 void CompareNilICStub::Record(Handle<Object> object) {
-  ASSERT(types_ != Types::FullCompare());
+  ASSERT(state_ != State::Generic());
   if (object->IsNull()) {
-    types_.Add(NULL_TYPE);
+    state_.Add(NULL_TYPE);
   } else if (object->IsUndefined()) {
-    types_.Add(UNDEFINED);
+    state_.Add(UNDEFINED);
   } else if (object->IsUndetectableObject() ||
              object->IsOddball() ||
              !object->IsHeapObject()) {
-    types_ = Types::FullCompare();
+    state_ = State::Generic();
   } else if (IsMonomorphic()) {
-    types_ = Types::FullCompare();
+    state_ = State::Generic();
   } else {
-    types_.Add(MONOMORPHIC_MAP);
+    state_.Add(MONOMORPHIC_MAP);
   }
 }
 
 
-void CompareNilICStub::Types::TraceTransition(Types to) const {
+void CompareNilICStub::State::TraceTransition(State to) const {
   #ifdef DEBUG
   if (!FLAG_trace_ic) return;
   char buffer[100];
@@ -467,13 +467,13 @@
 
 void CompareNilICStub::PrintName(StringStream* stream) {
   stream->Add("CompareNilICStub_");
-  types_.Print(stream);
+  state_.Print(stream);
   stream->Add((nil_value_ == kNullValue) ? "(NullValue|":
                                            "(UndefinedValue|");
 }
 
 
-void CompareNilICStub::Types::Print(StringStream* stream) const {
+void CompareNilICStub::State::Print(StringStream* stream) const {
   stream->Add("(");
   SimpleListPrinter printer(stream);
   if (IsEmpty()) printer.Add("None");
@@ -481,10 +481,40 @@
   if (Contains(NULL_TYPE)) printer.Add("Null");
   if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap");
   if (Contains(UNDETECTABLE)) printer.Add("Undetectable");
+  if (Contains(GENERIC)) printer.Add("Generic");
   stream->Add(")");
 }
 
 
+Handle<Type> CompareNilICStub::StateToType(
+    Isolate* isolate,
+    State state,
+    Handle<Map> map) {
+  if (state.Contains(CompareNilICStub::GENERIC)) {
+    return handle(Type::Any(), isolate);
+  }
+
+  Handle<Type> result(Type::None(), isolate);
+  if (state.Contains(CompareNilICStub::UNDEFINED)) {
+    result = handle(Type::Union(result, handle(Type::Undefined(), isolate)),
+                    isolate);
+  }
+  if (state.Contains(CompareNilICStub::NULL_TYPE)) {
+    result = handle(Type::Union(result, handle(Type::Null(), isolate)),
+                    isolate);
+  }
+  if (state.Contains(CompareNilICStub::UNDETECTABLE)) {
+    result = handle(Type::Union(result, handle(Type::Undetectable(), isolate)),
+                    isolate);
+  } else if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
+    Type* type = map.is_null() ? Type::Detectable() : Type::Class(map);
+    result = handle(Type::Union(result, handle(type, isolate)), isolate);
+  }
+
+  return result;
+}
+
+
 void InstanceofStub::PrintName(StringStream* stream) {
   const char* args = "";
   if (HasArgsInRegisters()) {
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 0ea7ac9..edbc93d 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -1124,46 +1124,50 @@
 
 class CompareNilICStub : public HydrogenCodeStub  {
  public:
-  enum Type {
+  enum CompareNilType {
     UNDEFINED,
     NULL_TYPE,
     MONOMORPHIC_MAP,
     UNDETECTABLE,
+    GENERIC,
     NUMBER_OF_TYPES
   };
 
-  class Types : public EnumSet<Type, byte> {
+  class State : public EnumSet<CompareNilType, byte> {
    public:
-    Types() : EnumSet<Type, byte>(0) { }
-    explicit Types(byte bits) : EnumSet<Type, byte>(bits) { }
+    State() : EnumSet<CompareNilType, byte>(0) { }
+    explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
 
-    static Types FullCompare() {
-      Types set;
+    static State Generic() {
+      State set;
       set.Add(UNDEFINED);
       set.Add(NULL_TYPE);
       set.Add(UNDETECTABLE);
+      set.Add(GENERIC);
       return set;
     }
 
     void Print(StringStream* stream) const;
-    void TraceTransition(Types to) const;
+    void TraceTransition(State to) const;
   };
 
+  static Handle<Type> StateToType(
+      Isolate* isolate, State state, Handle<Map> map = Handle<Map>());
+
   // At most 6 different types can be distinguished, because the Code object
   // only has room for a single byte to hold a set and there are two more
   // boolean flags we need to store. :-P
   STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
 
-  CompareNilICStub(NilValue nil, Types types = Types())
-      : types_(types) {
-    nil_value_ = nil;
+  CompareNilICStub(NilValue nil, State state = State())
+      : nil_value_(nil), state_(state) {
   }
 
   CompareNilICStub(Code::ExtraICState ic_state,
                    InitializationState init_state = INITIALIZED)
       : HydrogenCodeStub(init_state) {
     nil_value_ = NilValueField::decode(ic_state);
-    types_ = Types(ExtractTypesFromExtraICState(ic_state));
+    state_ = State(ExtractTypesFromExtraICState(ic_state));
   }
 
   static Handle<Code> GetUninitialized(Isolate* isolate,
@@ -1183,9 +1187,9 @@
   }
 
   virtual InlineCacheState GetICState() {
-    if (types_ == Types::FullCompare()) {
+    if (state_ == State::Generic()) {
       return MEGAMORPHIC;
-    } else if (types_.Contains(MONOMORPHIC_MAP)) {
+    } else if (state_.Contains(MONOMORPHIC_MAP)) {
       return MONOMORPHIC;
     } else {
       return PREMONOMORPHIC;
@@ -1198,20 +1202,18 @@
 
   // extra ic state = nil_value | type_n-1 | ... | type_0
   virtual Code::ExtraICState GetExtraICState() {
-    return NilValueField::encode(nil_value_)         |
-           types_.ToIntegral();
+    return NilValueField::encode(nil_value_) | state_.ToIntegral();
   }
-  static byte ExtractTypesFromExtraICState(
-      Code::ExtraICState state) {
+  static byte ExtractTypesFromExtraICState(Code::ExtraICState state) {
     return state & ((1 << NUMBER_OF_TYPES) - 1);
   }
 
   void Record(Handle<Object> object);
 
-  bool IsMonomorphic() const { return types_.Contains(MONOMORPHIC_MAP); }
+  bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
   NilValue GetNilValue() const { return nil_value_; }
-  Types GetTypes() const { return types_; }
-  void ClearTypes() { types_.RemoveAll(); }
+  State GetState() const { return state_; }
+  void ClearState() { state_.RemoveAll(); }
 
   virtual void PrintName(StringStream* stream);
 
@@ -1229,7 +1231,7 @@
   virtual int NotMissMinorKey() { return GetExtraICState(); }
 
   NilValue nil_value_;
-  Types types_;
+  State state_;
 
   DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
 };
diff --git a/src/compiler.cc b/src/compiler.cc
index 5fc107f..5de9d96 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -106,6 +106,9 @@
   opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count();
   no_frame_ranges_ = isolate->cpu_profiler()->is_profiling()
                    ? new List<OffsetRange>(2) : NULL;
+  for (int i = 0; i < DependentCode::kGroupCount; i++) {
+    dependent_maps_[i] = NULL;
+  }
   if (mode == STUB) {
     mode_ = STUB;
     return;
@@ -125,6 +128,41 @@
 CompilationInfo::~CompilationInfo() {
   delete deferred_handles_;
   delete no_frame_ranges_;
+#ifdef DEBUG
+  // Check that no dependent maps have been added or added dependent maps have
+  // been rolled back or committed.
+  for (int i = 0; i < DependentCode::kGroupCount; i++) {
+    ASSERT_EQ(NULL, dependent_maps_[i]);
+  }
+#endif  // DEBUG
+}
+
+
+void CompilationInfo::CommitDependentMaps(Handle<Code> code) {
+  for (int i = 0; i < DependentCode::kGroupCount; i++) {
+    ZoneList<Handle<Map> >* group_maps = dependent_maps_[i];
+    if (group_maps == NULL) continue;
+    ASSERT(!object_wrapper_.is_null());
+    for (int j = 0; j < group_maps->length(); j++) {
+      group_maps->at(j)->dependent_code()->UpdateToFinishedCode(
+          static_cast<DependentCode::DependencyGroup>(i), this, *code);
+    }
+    dependent_maps_[i] = NULL;  // Zone-allocated, no need to delete.
+  }
+}
+
+
+void CompilationInfo::RollbackDependentMaps() {
+  // Unregister from all dependent maps if not yet committed.
+  for (int i = 0; i < DependentCode::kGroupCount; i++) {
+    ZoneList<Handle<Map> >* group_maps = dependent_maps_[i];
+    if (group_maps == NULL) continue;
+    for (int j = 0; j < group_maps->length(); j++) {
+      group_maps->at(j)->dependent_code()->RemoveCompilationInfo(
+          static_cast<DependentCode::DependencyGroup>(i), this);
+    }
+    dependent_maps_[i] = NULL;  // Zone-allocated, no need to delete.
+  }
 }
 
 
@@ -364,7 +402,7 @@
   }
 
   // Type-check the function.
-  AstTyper::Type(info());
+  AstTyper::Run(info());
 
   graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info());
 
@@ -982,7 +1020,7 @@
   // The function may have already been optimized by OSR.  Simply continue.
   // Except when OSR already disabled optimization for some reason.
   if (info->shared_info()->optimization_disabled()) {
-    info->SetCode(Handle<Code>(info->shared_info()->code()));
+    info->AbortOptimization();
     InstallFullCode(*info);
     if (FLAG_trace_parallel_recompilation) {
       PrintF("  ** aborting optimization for ");
@@ -1000,9 +1038,11 @@
   // If crankshaft succeeded, install the optimized code else install
   // the unoptimized code.
   OptimizingCompiler::Status status = optimizing_compiler->last_status();
-  if (status != OptimizingCompiler::SUCCEEDED) {
-    optimizing_compiler->info()->set_bailout_reason(
-        "failed/bailed out last time");
+  if (info->HasAbortedDueToDependentMap()) {
+    info->set_bailout_reason("bailed out due to dependent map");
+    status = optimizing_compiler->AbortOptimization();
+  } else if (status != OptimizingCompiler::SUCCEEDED) {
+    info->set_bailout_reason("failed/bailed out last time");
     status = optimizing_compiler->AbortOptimization();
   } else {
     status = optimizing_compiler->GenerateAndInstallCode();
@@ -1141,7 +1181,16 @@
     Handle<Code> code = info->code();
     if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
       return;
+    Handle<String> script_name;
     if (script->name()->IsString()) {
+      script_name = Handle<String>(String::cast(script->name()));
+    } else {
+      Handle<Object> name = GetScriptNameOrSourceURL(script);
+      if (!name.is_null() && name->IsString()) {
+        script_name = Handle<String>::cast(name);
+      }
+    }
+    if (!script_name.is_null()) {
       int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
       USE(line_num);
       PROFILE(info->isolate(),
@@ -1149,7 +1198,7 @@
                               *code,
                               *shared,
                               info,
-                              String::cast(script->name()),
+                              String::cast(*script_name),
                               line_num));
     } else {
       PROFILE(info->isolate(),
diff --git a/src/compiler.h b/src/compiler.h
index 8e6d295..f53feb9 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -57,12 +57,8 @@
 // is constructed based on the resources available at compile-time.
 class CompilationInfo {
  public:
-  CompilationInfo(Handle<Script> script, Zone* zone);
-  CompilationInfo(Handle<SharedFunctionInfo> shared_info, Zone* zone);
   CompilationInfo(Handle<JSFunction> closure, Zone* zone);
-  CompilationInfo(HydrogenCodeStub* stub, Isolate* isolate, Zone* zone);
-
-  ~CompilationInfo();
+  virtual ~CompilationInfo();
 
   Isolate* isolate() {
     ASSERT(Isolate::Current() == isolate_);
@@ -243,6 +239,17 @@
     deferred_handles_ = deferred_handles;
   }
 
+  ZoneList<Handle<Map> >* dependent_maps(DependentCode::DependencyGroup group) {
+    if (dependent_maps_[group] == NULL) {
+      dependent_maps_[group] = new(zone_) ZoneList<Handle<Map> >(2, zone_);
+    }
+    return dependent_maps_[group];
+  }
+
+  void CommitDependentMaps(Handle<Code> code);
+
+  void RollbackDependentMaps();
+
   void SaveHandles() {
     SaveHandle(&closure_);
     SaveHandle(&shared_info_);
@@ -276,6 +283,26 @@
     return result;
   }
 
+  Handle<Foreign> object_wrapper() {
+    if (object_wrapper_.is_null()) {
+      object_wrapper_ =
+          isolate()->factory()->NewForeign(reinterpret_cast<Address>(this));
+    }
+    return object_wrapper_;
+  }
+
+  void AbortDueToDependentMap() {
+    mode_ = DEPENDENT_MAP_ABORT;
+  }
+
+  bool HasAbortedDueToDependentMap() {
+    return mode_ == DEPENDENT_MAP_ABORT;
+  }
+
+ protected:
+  CompilationInfo(Handle<Script> script, Zone* zone);
+  CompilationInfo(Handle<SharedFunctionInfo> shared_info, Zone* zone);
+  CompilationInfo(HydrogenCodeStub* stub, Isolate* isolate, Zone* zone);
 
  private:
   Isolate* isolate_;
@@ -289,7 +316,8 @@
     BASE,
     OPTIMIZE,
     NONOPT,
-    STUB
+    STUB,
+    DEPENDENT_MAP_ABORT
   };
 
   void Initialize(Isolate* isolate, Mode mode, Zone* zone);
@@ -369,6 +397,8 @@
 
   DeferredHandles* deferred_handles_;
 
+  ZoneList<Handle<Map> >* dependent_maps_[DependentCode::kGroupCount];
+
   template<typename T>
   void SaveHandle(Handle<T> *object) {
     if (!object->is_null()) {
@@ -387,6 +417,8 @@
   // during graph optimization.
   int opt_count_;
 
+  Handle<Foreign> object_wrapper_;
+
   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
 };
 
@@ -407,11 +439,18 @@
       : CompilationInfo(closure, &zone_),
         zone_(closure->GetIsolate()),
         zone_scope_(&zone_, DELETE_ON_EXIT) {}
-  explicit CompilationInfoWithZone(HydrogenCodeStub* stub, Isolate* isolate)
+  CompilationInfoWithZone(HydrogenCodeStub* stub, Isolate* isolate)
       : CompilationInfo(stub, isolate, &zone_),
         zone_(isolate),
         zone_scope_(&zone_, DELETE_ON_EXIT) {}
 
+  // Virtual destructor because a CompilationInfoWithZone has to exit the
+  // zone scope and get rid of dependent maps even when the destructor is
+  // called when cast as a CompilationInfo.
+  virtual ~CompilationInfoWithZone() {
+    RollbackDependentMaps();
+  }
+
  private:
   Zone zone_;
   ZoneScope zone_scope_;
diff --git a/src/data-flow.h b/src/data-flow.h
index 7eeb794..8ceccf6 100644
--- a/src/data-flow.h
+++ b/src/data-flow.h
@@ -215,6 +215,8 @@
   };
 
   GrowableBitVector() : bits_(NULL) { }
+  GrowableBitVector(int length, Zone* zone)
+      : bits_(new(zone) BitVector(length, zone)) { }
 
   bool Contains(int value) const {
     if (!InBitsRange(value)) return false;
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 723d3f6..14c1d73 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -534,8 +534,9 @@
       output_count_(0),
       jsframe_count_(0),
       output_(NULL),
-      deferred_arguments_objects_values_(0),
-      deferred_arguments_objects_(0),
+      deferred_objects_tagged_values_(0),
+      deferred_objects_double_values_(0),
+      deferred_objects_(0),
       deferred_heap_numbers_(0),
       trace_(false) {
   // For COMPILED_STUBs called from builtins, the function pointer is a SMI
@@ -1566,15 +1567,14 @@
 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
   ASSERT_NE(DEBUGGER, bailout_type_);
 
-  // Handlify all argument object values before triggering any allocation.
-  List<Handle<Object> > values(deferred_arguments_objects_values_.length());
-  for (int i = 0; i < deferred_arguments_objects_values_.length(); ++i) {
-    values.Add(Handle<Object>(deferred_arguments_objects_values_[i],
-                              isolate_));
+  // Handlify all tagged object values before triggering any allocation.
+  List<Handle<Object> > values(deferred_objects_tagged_values_.length());
+  for (int i = 0; i < deferred_objects_tagged_values_.length(); ++i) {
+    values.Add(Handle<Object>(deferred_objects_tagged_values_[i], isolate_));
   }
 
   // Play it safe and clear all unhandlified values before we continue.
-  deferred_arguments_objects_values_.Clear();
+  deferred_objects_tagged_values_.Clear();
 
   // Materialize all heap numbers before looking at arguments because when the
   // output frames are used to materialize arguments objects later on they need
@@ -1591,6 +1591,18 @@
     Memory::Object_at(d.slot_address()) = *num;
   }
 
+  // Materialize all heap numbers required for arguments objects.
+  for (int i = 0; i < values.length(); i++) {
+    if (!values.at(i)->IsTheHole()) continue;
+    double double_value = deferred_objects_double_values_[i];
+    Handle<Object> num = isolate_->factory()->NewNumber(double_value);
+    if (trace_) {
+      PrintF("Materializing a new heap number %p [%e] for arguments object\n",
+             reinterpret_cast<void*>(*num), double_value);
+    }
+    values.Set(i, num);
+  }
+
   // Materialize arguments objects one frame at a time.
   for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
     if (frame_index != 0) it->Advance();
@@ -1599,9 +1611,9 @@
     Handle<JSObject> arguments;
     for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
       if (frame->GetExpression(i) == isolate_->heap()->arguments_marker()) {
-        ArgumentsObjectMaterializationDescriptor descriptor =
-            deferred_arguments_objects_.RemoveLast();
-        const int length = descriptor.arguments_length();
+        ObjectMaterializationDescriptor descriptor =
+            deferred_objects_.RemoveLast();
+        const int length = descriptor.object_length();
         if (arguments.is_null()) {
           if (frame->has_adapted_arguments()) {
             // Use the arguments adapter frame we just built to materialize the
@@ -1695,7 +1707,7 @@
 #endif
 
 
-static const char* TraceValueType(bool is_smi, bool is_native) {
+static const char* TraceValueType(bool is_smi, bool is_native = false) {
   if (is_native) {
     return "native";
   } else if (is_smi) {
@@ -1706,6 +1718,204 @@
 }
 
 
+void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
+                                    int object_opcode,
+                                    int field_index) {
+  disasm::NameConverter converter;
+  Address object_slot = deferred_objects_.last().slot_address();
+
+  // Ignore commands marked as duplicate and act on the first non-duplicate.
+  Translation::Opcode opcode =
+      static_cast<Translation::Opcode>(iterator->Next());
+  while (opcode == Translation::DUPLICATE) {
+    opcode = static_cast<Translation::Opcode>(iterator->Next());
+    iterator->Skip(Translation::NumberOfOperandsFor(opcode));
+    opcode = static_cast<Translation::Opcode>(iterator->Next());
+  }
+
+  switch (opcode) {
+    case Translation::BEGIN:
+    case Translation::JS_FRAME:
+    case Translation::ARGUMENTS_ADAPTOR_FRAME:
+    case Translation::CONSTRUCT_STUB_FRAME:
+    case Translation::GETTER_STUB_FRAME:
+    case Translation::SETTER_STUB_FRAME:
+    case Translation::COMPILED_STUB_FRAME:
+    case Translation::ARGUMENTS_OBJECT:
+    case Translation::DUPLICATE:
+      UNREACHABLE();
+      return;
+
+    case Translation::REGISTER: {
+      int input_reg = iterator->Next();
+      intptr_t input_value = input_->GetRegister(input_reg);
+      if (trace_) {
+        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+               reinterpret_cast<intptr_t>(object_slot),
+               field_index);
+        PrintF("0x%08" V8PRIxPTR " ; %s ", input_value,
+               converter.NameOfCPURegister(input_reg));
+        reinterpret_cast<Object*>(input_value)->ShortPrint();
+        PrintF("\n");
+      }
+      AddObjectTaggedValue(input_value);
+      return;
+    }
+
+    case Translation::INT32_REGISTER: {
+      int input_reg = iterator->Next();
+      intptr_t value = input_->GetRegister(input_reg);
+      bool is_smi = Smi::IsValid(value);
+      if (trace_) {
+        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+               reinterpret_cast<intptr_t>(object_slot),
+               field_index);
+        PrintF("%" V8PRIdPTR " ; %s (%s)\n", value,
+               converter.NameOfCPURegister(input_reg),
+               TraceValueType(is_smi));
+      }
+      if (is_smi) {
+        intptr_t tagged_value =
+            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
+        AddObjectTaggedValue(tagged_value);
+      } else {
+        double double_value = static_cast<double>(static_cast<int32_t>(value));
+        AddObjectDoubleValue(double_value);
+      }
+      return;
+    }
+
+    case Translation::UINT32_REGISTER: {
+      int input_reg = iterator->Next();
+      uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
+      bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
+      if (trace_) {
+        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+               reinterpret_cast<intptr_t>(object_slot),
+               field_index);
+        PrintF("%" V8PRIdPTR " ; uint %s (%s)\n", value,
+               converter.NameOfCPURegister(input_reg),
+               TraceValueType(is_smi));
+      }
+      if (is_smi) {
+        intptr_t tagged_value =
+            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
+        AddObjectTaggedValue(tagged_value);
+      } else {
+        double double_value = static_cast<double>(static_cast<uint32_t>(value));
+        AddObjectDoubleValue(double_value);
+      }
+      return;
+    }
+
+    case Translation::DOUBLE_REGISTER: {
+      int input_reg = iterator->Next();
+      double value = input_->GetDoubleRegister(input_reg);
+      if (trace_) {
+        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+               reinterpret_cast<intptr_t>(object_slot),
+               field_index);
+        PrintF("%e ; %s\n", value,
+               DoubleRegister::AllocationIndexToString(input_reg));
+      }
+      AddObjectDoubleValue(value);
+      return;
+    }
+
+    case Translation::STACK_SLOT: {
+      int input_slot_index = iterator->Next();
+      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+      intptr_t input_value = input_->GetFrameSlot(input_offset);
+      if (trace_) {
+        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+               reinterpret_cast<intptr_t>(object_slot),
+               field_index);
+        PrintF("0x%08" V8PRIxPTR " ; [sp + %d] ", input_value, input_offset);
+        reinterpret_cast<Object*>(input_value)->ShortPrint();
+        PrintF("\n");
+      }
+      AddObjectTaggedValue(input_value);
+      return;
+    }
+
+    case Translation::INT32_STACK_SLOT: {
+      int input_slot_index = iterator->Next();
+      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+      intptr_t value = input_->GetFrameSlot(input_offset);
+      bool is_smi = Smi::IsValid(value);
+      if (trace_) {
+        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+               reinterpret_cast<intptr_t>(object_slot),
+               field_index);
+        PrintF("%" V8PRIdPTR " ; [sp + %d] (%s)\n",
+               value, input_offset, TraceValueType(is_smi));
+      }
+      if (is_smi) {
+        intptr_t tagged_value =
+            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
+        AddObjectTaggedValue(tagged_value);
+      } else {
+        double double_value = static_cast<double>(static_cast<int32_t>(value));
+        AddObjectDoubleValue(double_value);
+      }
+      return;
+    }
+
+    case Translation::UINT32_STACK_SLOT: {
+      int input_slot_index = iterator->Next();
+      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+      uintptr_t value =
+          static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
+      bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
+      if (trace_) {
+        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+               reinterpret_cast<intptr_t>(object_slot),
+               field_index);
+        PrintF("%" V8PRIdPTR " ; [sp + %d] (uint %s)\n",
+               value, input_offset, TraceValueType(is_smi));
+      }
+      if (is_smi) {
+        intptr_t tagged_value =
+            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
+        AddObjectTaggedValue(tagged_value);
+      } else {
+        double double_value = static_cast<double>(static_cast<uint32_t>(value));
+        AddObjectDoubleValue(double_value);
+      }
+      return;
+    }
+
+    case Translation::DOUBLE_STACK_SLOT: {
+      int input_slot_index = iterator->Next();
+      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+      double value = input_->GetDoubleFrameSlot(input_offset);
+      if (trace_) {
+        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+               reinterpret_cast<intptr_t>(object_slot),
+               field_index);
+        PrintF("%e ; [sp + %d]\n", value, input_offset);
+      }
+      AddObjectDoubleValue(value);
+      return;
+    }
+
+    case Translation::LITERAL: {
+      Object* literal = ComputeLiteral(iterator->Next());
+      if (trace_) {
+        PrintF("      object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+               reinterpret_cast<intptr_t>(object_slot),
+               field_index);
+        literal->ShortPrint();
+        PrintF(" ; literal\n");
+      }
+      intptr_t value = reinterpret_cast<intptr_t>(literal);
+      AddObjectTaggedValue(value);
+      return;
+    }
+  }
+}
+
+
 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
     int frame_index,
     unsigned output_offset,
@@ -1758,7 +1968,6 @@
       intptr_t value = input_->GetRegister(input_reg);
       bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
           Smi::IsValid(value);
-
       if (trace_) {
         PrintF(
             "    0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
@@ -1836,8 +2045,7 @@
 
     case Translation::STACK_SLOT: {
       int input_slot_index = iterator->Next();
-      unsigned input_offset =
-          input_->GetOffsetFromSlotIndex(input_slot_index);
+      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
       intptr_t input_value = input_->GetFrameSlot(input_offset);
       if (trace_) {
         PrintF("    0x%08" V8PRIxPTR ": ",
@@ -1855,8 +2063,7 @@
 
     case Translation::INT32_STACK_SLOT: {
       int input_slot_index = iterator->Next();
-      unsigned input_offset =
-          input_->GetOffsetFromSlotIndex(input_slot_index);
+      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
       intptr_t value = input_->GetFrameSlot(input_offset);
       bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
           Smi::IsValid(value);
@@ -1888,8 +2095,7 @@
 
     case Translation::UINT32_STACK_SLOT: {
       int input_slot_index = iterator->Next();
-      unsigned input_offset =
-          input_->GetOffsetFromSlotIndex(input_slot_index);
+      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
       uintptr_t value =
           static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
       bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
@@ -1922,8 +2128,7 @@
 
     case Translation::DOUBLE_STACK_SLOT: {
       int input_slot_index = iterator->Next();
-      unsigned input_offset =
-          input_->GetOffsetFromSlotIndex(input_slot_index);
+      unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
       double value = input_->GetDoubleFrameSlot(input_offset);
       if (trace_) {
         PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- %e ; [sp + %d]\n",
@@ -1954,31 +2159,24 @@
     }
 
     case Translation::ARGUMENTS_OBJECT: {
-      bool args_known = iterator->Next();
-      int args_index = iterator->Next() + 1;  // Skip receiver.
-      int args_length = iterator->Next() - 1;  // Skip receiver.
+      int length = iterator->Next();
       if (trace_) {
         PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- ",
                output_[frame_index]->GetTop() + output_offset,
                output_offset);
         isolate_->heap()->arguments_marker()->ShortPrint();
-        PrintF(" ; %sarguments object\n", args_known ? "" : "dummy ");
+        PrintF(" ; arguments object (length = %d)\n", length);
       }
       // Use the arguments marker value as a sentinel and fill in the arguments
       // object after the deoptimized frame is built.
       intptr_t value = reinterpret_cast<intptr_t>(
           isolate_->heap()->arguments_marker());
-      AddArgumentsObject(
-          output_[frame_index]->GetTop() + output_offset, args_length);
+      AddObjectStart(output_[frame_index]->GetTop() + output_offset, length);
       output_[frame_index]->SetFrameSlot(output_offset, value);
-      // We save the tagged argument values on the side and materialize the
-      // actual arguments object after the deoptimized frame is built.
-      for (int i = 0; i < args_length; i++) {
-        unsigned input_offset = input_->GetOffsetFromSlotIndex(args_index + i);
-        intptr_t input_value = args_known
-            ? input_->GetFrameSlot(input_offset)
-            : reinterpret_cast<intptr_t>(isolate_->heap()->the_hole_value());
-        AddArgumentsObjectValue(input_value);
+      // We save the argument values on the side and materialize the actual
+      // arguments object after the deoptimized frame is built.
+      for (int i = 0; i < length; i++) {
+        DoTranslateObject(iterator, Translation::ARGUMENTS_OBJECT, i);
       }
       return;
     }
@@ -2324,15 +2522,22 @@
 }
 
 
-void Deoptimizer::AddArgumentsObject(intptr_t slot_address, int argc) {
-  ArgumentsObjectMaterializationDescriptor object_desc(
-      reinterpret_cast<Address>(slot_address), argc);
-  deferred_arguments_objects_.Add(object_desc);
+void Deoptimizer::AddObjectStart(intptr_t slot_address, int length) {
+  ObjectMaterializationDescriptor object_desc(
+      reinterpret_cast<Address>(slot_address), length);
+  deferred_objects_.Add(object_desc);
 }
 
 
-void Deoptimizer::AddArgumentsObjectValue(intptr_t value) {
-  deferred_arguments_objects_values_.Add(reinterpret_cast<Object*>(value));
+void Deoptimizer::AddObjectTaggedValue(intptr_t value) {
+  deferred_objects_tagged_values_.Add(reinterpret_cast<Object*>(value));
+  deferred_objects_double_values_.Add(isolate()->heap()->nan_value()->value());
+}
+
+
+void Deoptimizer::AddObjectDoubleValue(double value) {
+  deferred_objects_tagged_values_.Add(isolate()->heap()->the_hole_value());
+  deferred_objects_double_values_.Add(value);
 }
 
 
@@ -2556,6 +2761,12 @@
 }
 
 
+void Translation::BeginArgumentsObject(int args_length) {
+  buffer_->Add(ARGUMENTS_OBJECT, zone());
+  buffer_->Add(args_length, zone());
+}
+
+
 void Translation::StoreRegister(Register reg) {
   buffer_->Add(REGISTER, zone());
   buffer_->Add(reg.code(), zone());
@@ -2610,16 +2821,6 @@
 }
 
 
-void Translation::StoreArgumentsObject(bool args_known,
-                                       int args_index,
-                                       int args_length) {
-  buffer_->Add(ARGUMENTS_OBJECT, zone());
-  buffer_->Add(args_known, zone());
-  buffer_->Add(args_index, zone());
-  buffer_->Add(args_length, zone());
-}
-
-
 void Translation::MarkDuplicate() {
   buffer_->Add(DUPLICATE, zone());
 }
@@ -2631,6 +2832,7 @@
       return 0;
     case GETTER_STUB_FRAME:
     case SETTER_STUB_FRAME:
+    case ARGUMENTS_OBJECT:
     case REGISTER:
     case INT32_REGISTER:
     case UINT32_REGISTER:
@@ -2647,7 +2849,6 @@
     case CONSTRUCT_STUB_FRAME:
       return 2;
     case JS_FRAME:
-    case ARGUMENTS_OBJECT:
       return 3;
   }
   UNREACHABLE();
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 5569f7f..5ca635c 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -75,17 +75,17 @@
 };
 
 
-class ArgumentsObjectMaterializationDescriptor BASE_EMBEDDED {
+class ObjectMaterializationDescriptor BASE_EMBEDDED {
  public:
-  ArgumentsObjectMaterializationDescriptor(Address slot_address, int argc)
-      : slot_address_(slot_address), arguments_length_(argc) { }
+  ObjectMaterializationDescriptor(Address slot_address, int length)
+      : slot_address_(slot_address), object_length_(length) { }
 
   Address slot_address() const { return slot_address_; }
-  int arguments_length() const { return arguments_length_; }
+  int object_length() const { return object_length_; }
 
  private:
   Address slot_address_;
-  int arguments_length_;
+  int object_length_;
 };
 
 
@@ -369,6 +369,10 @@
   void DoComputeCompiledStubFrame(TranslationIterator* iterator,
                                   int frame_index);
 
+  void DoTranslateObject(TranslationIterator* iterator,
+                         int object_opcode,
+                         int field_index);
+
   enum DeoptimizerTranslatedValueType {
     TRANSLATED_VALUE_IS_NATIVE,
     TRANSLATED_VALUE_IS_TAGGED
@@ -394,8 +398,9 @@
 
   Object* ComputeLiteral(int index) const;
 
-  void AddArgumentsObject(intptr_t slot_address, int argc);
-  void AddArgumentsObjectValue(intptr_t value);
+  void AddObjectStart(intptr_t slot_address, int argc);
+  void AddObjectTaggedValue(intptr_t value);
+  void AddObjectDoubleValue(double value);
   void AddDoubleValue(intptr_t slot_address, double value);
 
   static void GenerateDeoptimizationEntries(
@@ -446,8 +451,9 @@
   // Array of output frame descriptions.
   FrameDescription** output_;
 
-  List<Object*> deferred_arguments_objects_values_;
-  List<ArgumentsObjectMaterializationDescriptor> deferred_arguments_objects_;
+  List<Object*> deferred_objects_tagged_values_;
+  List<double> deferred_objects_double_values_;
+  List<ObjectMaterializationDescriptor> deferred_objects_;
   List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_;
 #ifdef DEBUG
   DisallowHeapAllocation* disallow_heap_allocation_;
@@ -698,6 +704,7 @@
     SETTER_STUB_FRAME,
     ARGUMENTS_ADAPTOR_FRAME,
     COMPILED_STUB_FRAME,
+    ARGUMENTS_OBJECT,
     REGISTER,
     INT32_REGISTER,
     UINT32_REGISTER,
@@ -707,7 +714,6 @@
     UINT32_STACK_SLOT,
     DOUBLE_STACK_SLOT,
     LITERAL,
-    ARGUMENTS_OBJECT,
 
     // A prefix indicating that the next command is a duplicate of the one
     // that follows it.
@@ -733,6 +739,7 @@
   void BeginConstructStubFrame(int literal_id, unsigned height);
   void BeginGetterStubFrame(int literal_id);
   void BeginSetterStubFrame(int literal_id);
+  void BeginArgumentsObject(int args_length);
   void StoreRegister(Register reg);
   void StoreInt32Register(Register reg);
   void StoreUint32Register(Register reg);
@@ -742,7 +749,6 @@
   void StoreUint32StackSlot(int index);
   void StoreDoubleStackSlot(int index);
   void StoreLiteral(int literal_id);
-  void StoreArgumentsObject(bool args_known, int args_index, int args_length);
   void MarkDuplicate();
 
   Zone* zone() const { return zone_; }
diff --git a/src/extensions/statistics-extension.cc b/src/extensions/statistics-extension.cc
index e5a3009..32bc07d 100644
--- a/src/extensions/statistics-extension.cc
+++ b/src/extensions/statistics-extension.cc
@@ -133,6 +133,12 @@
             "cell_space_available_bytes");
   AddNumber(result, heap->cell_space()->CommittedMemory(),
             "cell_space_commited_bytes");
+  AddNumber(result, heap->property_cell_space()->Size(),
+            "property_cell_space_live_bytes");
+  AddNumber(result, heap->property_cell_space()->Available(),
+            "property_cell_space_available_bytes");
+  AddNumber(result, heap->property_cell_space()->CommittedMemory(),
+            "property_cell_space_commited_bytes");
   AddNumber(result, heap->lo_space()->Size(),
             "lo_space_live_bytes");
   AddNumber(result, heap->lo_space()->Available(),
diff --git a/src/factory.cc b/src/factory.cc
index c47b57d..fbe6cb8 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -482,6 +482,15 @@
 }
 
 
+Handle<Cell> Factory::NewCell(Handle<Object> value) {
+  AllowDeferredHandleDereference convert_to_cell;
+  CALL_HEAP_FUNCTION(
+      isolate(),
+      isolate()->heap()->AllocateCell(*value),
+      Cell);
+}
+
+
 Handle<JSGlobalPropertyCell> Factory::NewJSGlobalPropertyCell(
     Handle<Object> value) {
   AllowDeferredHandleDereference convert_to_cell;
diff --git a/src/factory.h b/src/factory.h
index d59d742..07ce96e 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -235,6 +235,8 @@
       void* external_pointer,
       PretenureFlag pretenure = NOT_TENURED);
 
+  Handle<Cell> NewCell(Handle<Object> value);
+
   Handle<JSGlobalPropertyCell> NewJSGlobalPropertyCell(
       Handle<Object> value);
 
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index b70a532..49dac4a 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -178,8 +178,7 @@
 DEFINE_implication(harmony, harmony_proxies)
 DEFINE_implication(harmony, harmony_collections)
 DEFINE_implication(harmony, harmony_observation)
-// TODO(wingo): Re-enable when GC bug that appeared in r15060 is gone.
-// DEFINE_implication(harmony, harmony_generators)
+DEFINE_implication(harmony, harmony_generators)
 DEFINE_implication(harmony, harmony_iteration)
 DEFINE_implication(harmony_modules, harmony_scoping)
 DEFINE_implication(harmony_observation, harmony_collections)
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index bad634c..49a3194 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -473,7 +473,7 @@
 
 
 void FullCodeGenerator::RecordTypeFeedbackCell(
-    TypeFeedbackId id, Handle<JSGlobalPropertyCell> cell) {
+    TypeFeedbackId id, Handle<Cell> cell) {
   TypeFeedbackCellEntry entry = { id, cell };
   type_feedback_cells_.Add(entry, zone());
 }
@@ -1230,13 +1230,7 @@
 }
 
 
-void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
-  Comment cmnt(masm_, "[ ReturnStatement");
-  SetStatementPosition(stmt);
-  Expression* expr = stmt->expression();
-  VisitForAccumulatorValue(expr);
-
-  // Exit all nested statements.
+void FullCodeGenerator::EmitUnwindBeforeReturn() {
   NestedStatement* current = nesting_stack_;
   int stack_depth = 0;
   int context_length = 0;
@@ -1244,7 +1238,15 @@
     current = current->Exit(&stack_depth, &context_length);
   }
   __ Drop(stack_depth);
+}
 
+
+void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
+  Comment cmnt(masm_, "[ ReturnStatement");
+  SetStatementPosition(stmt);
+  Expression* expr = stmt->expression();
+  VisitForAccumulatorValue(expr);
+  EmitUnwindBeforeReturn();
   EmitReturnSequence();
 }
 
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 68263a5..969a98d 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -410,10 +410,10 @@
   // this has to be a separate pass _before_ populating or executing any module.
   void AllocateModules(ZoneList<Declaration*>* declarations);
 
-  // Generator code to return a fresh iterator result object.  The "value"
-  // property is set to a value popped from the stack, and "done" is set
-  // according to the argument.
-  void EmitReturnIteratorResult(bool done);
+  // Generate code to create an iterator result object.  The "value" property is
+  // set to a value popped from the stack, and "done" is set according to the
+  // argument.  The result object is left in the result register.
+  void EmitCreateIteratorResult(bool done);
 
   // Try to perform a comparison as a fast inlined literal compare if
   // the operands allow it.  Returns true if the compare operations
@@ -437,8 +437,7 @@
 
   // Cache cell support.  This associates AST ids with global property cells
   // that will be cleared during GC and collected by the type-feedback oracle.
-  void RecordTypeFeedbackCell(TypeFeedbackId id,
-                              Handle<JSGlobalPropertyCell> cell);
+  void RecordTypeFeedbackCell(TypeFeedbackId id, Handle<Cell> cell);
 
   // Record a call's return site offset, used to rebuild the frame if the
   // called function was inlined at the site.
@@ -472,6 +471,11 @@
   void EmitProfilingCounterDecrement(int delta);
   void EmitProfilingCounterReset();
 
+  // Emit code to pop values from the stack associated with nested statements
+  // like try/catch, try/finally, etc, running the finallies and unwinding the
+  // handlers as needed.
+  void EmitUnwindBeforeReturn();
+
   // Platform-specific return sequence
   void EmitReturnSequence();
 
@@ -648,7 +652,7 @@
 
   struct TypeFeedbackCellEntry {
     TypeFeedbackId ast_id;
-    Handle<JSGlobalPropertyCell> cell;
+    Handle<Cell> cell;
   };
 
 
@@ -844,7 +848,7 @@
   ZoneList<TypeFeedbackCellEntry> type_feedback_cells_;
   int ic_total_count_;
   Handle<FixedArray> handler_table_;
-  Handle<JSGlobalPropertyCell> profiling_counter_;
+  Handle<Cell> profiling_counter_;
   bool generate_debug_code_;
   Zone* zone_;
 
diff --git a/src/generator.js b/src/generator.js
index cc31a44..3c8ea6f 100644
--- a/src/generator.js
+++ b/src/generator.js
@@ -55,6 +55,23 @@
   return %_GeneratorThrow(this, exn);
 }
 
+function GeneratorFunctionPrototypeConstructor(x) {
+  if (%_IsConstructCall()) {
+    throw MakeTypeError('not_constructor', ['GeneratorFunctionPrototype']);
+  }
+}
+
+function GeneratorFunctionConstructor(arg1) {  // length == 1
+  var source = NewFunctionString(arguments, 'function*');
+  var global_receiver = %GlobalReceiver(global);
+  // Compile the string in the constructor and not a helper so that errors
+  // appear to come from here.
+  var f = %_CallFunction(global_receiver, %CompileString(source, true));
+  %FunctionMarkNameShouldPrintAsAnonymous(f);
+  return f;
+}
+
+
 function SetUpGenerators() {
   %CheckIsBootstrapping();
   var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype;
@@ -65,9 +82,11 @@
   %SetProperty(GeneratorObjectPrototype, "constructor",
                GeneratorFunctionPrototype, DONT_ENUM | DONT_DELETE | READ_ONLY);
   %SetPrototype(GeneratorFunctionPrototype, $Function.prototype);
+  %SetCode(GeneratorFunctionPrototype, GeneratorFunctionPrototypeConstructor);
   %SetProperty(GeneratorFunctionPrototype, "constructor",
                GeneratorFunction, DONT_ENUM | DONT_DELETE | READ_ONLY);
   %SetPrototype(GeneratorFunction, $Function);
+  %SetCode(GeneratorFunction, GeneratorFunctionConstructor);
 }
 
 SetUpGenerators();
diff --git a/src/handles.cc b/src/handles.cc
index 81828d9..658bb2a 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -599,6 +599,9 @@
 
 Handle<Object> GetScriptNameOrSourceURL(Handle<Script> script) {
   Isolate* isolate = script->GetIsolate();
+  if (!isolate->IsInitialized()) {
+    return isolate->factory()->undefined_value();
+  }
   Handle<String> name_or_source_url_key =
       isolate->factory()->InternalizeOneByteString(
           STATIC_ASCII_VECTOR("nameOrSourceURL"));
diff --git a/src/heap-inl.h b/src/heap-inl.h
index f0861b2..208b1ad 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -245,6 +245,8 @@
     result = lo_space_->AllocateRaw(size_in_bytes, NOT_EXECUTABLE);
   } else if (CELL_SPACE == space) {
     result = cell_space_->AllocateRaw(size_in_bytes);
+  } else if (PROPERTY_CELL_SPACE == space) {
+    result = property_cell_space_->AllocateRaw(size_in_bytes);
   } else {
     ASSERT(MAP_SPACE == space);
     result = map_space_->AllocateRaw(size_in_bytes);
@@ -305,7 +307,19 @@
   isolate_->counters()->objs_since_last_full()->Increment();
   isolate_->counters()->objs_since_last_young()->Increment();
 #endif
-  MaybeObject* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize);
+  MaybeObject* result = cell_space_->AllocateRaw(Cell::kSize);
+  if (result->IsFailure()) old_gen_exhausted_ = true;
+  return result;
+}
+
+
+MaybeObject* Heap::AllocateRawJSGlobalPropertyCell() {
+#ifdef DEBUG
+  isolate_->counters()->objs_since_last_full()->Increment();
+  isolate_->counters()->objs_since_last_young()->Increment();
+#endif
+  MaybeObject* result =
+      property_cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize);
   if (result->IsFailure()) old_gen_exhausted_ = true;
   return result;
 }
@@ -407,7 +421,8 @@
   ASSERT(type != MAP_TYPE);
   ASSERT(type != CODE_TYPE);
   ASSERT(type != ODDBALL_TYPE);
-  ASSERT(type != JS_GLOBAL_PROPERTY_CELL_TYPE);
+  ASSERT(type != CELL_TYPE);
+  ASSERT(type != PROPERTY_CELL_TYPE);
 
   if (type <= LAST_NAME_TYPE) {
     if (type == SYMBOL_TYPE) return OLD_POINTER_SPACE;
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index b8237a6..611f6a7 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -31,6 +31,7 @@
 
 #include "heap-profiler.h"
 #include "debug.h"
+#include "types.h"
 
 namespace v8 {
 namespace internal {
@@ -888,7 +889,8 @@
 #undef MAKE_STRING_MAP_CASE
         default: return "system / Map";
       }
-    case JS_GLOBAL_PROPERTY_CELL_TYPE: return "system / JSGlobalPropertyCell";
+    case CELL_TYPE: return "system / Cell";
+    case PROPERTY_CELL_TYPE: return "system / JSGlobalPropertyCell";
     case FOREIGN_TYPE: return "system / Foreign";
     case ODDBALL_TYPE: return "system / Oddball";
 #define MAKE_STRUCT_CASE(NAME, Name, name) \
@@ -976,6 +978,9 @@
     ExtractCodeCacheReferences(entry, CodeCache::cast(obj));
   } else if (obj->IsCode()) {
     ExtractCodeReferences(entry, Code::cast(obj));
+  } else if (obj->IsCell()) {
+    ExtractCellReferences(entry, Cell::cast(obj));
+    extract_indexed_refs = false;
   } else if (obj->IsJSGlobalPropertyCell()) {
     ExtractJSGlobalPropertyCellReferences(
         entry, JSGlobalPropertyCell::cast(obj));
@@ -1273,9 +1278,15 @@
 }
 
 
+void V8HeapExplorer::ExtractCellReferences(int entry, Cell* cell) {
+  SetInternalReference(cell, entry, "value", cell->value());
+}
+
+
 void V8HeapExplorer::ExtractJSGlobalPropertyCellReferences(
     int entry, JSGlobalPropertyCell* cell) {
   SetInternalReference(cell, entry, "value", cell->value());
+  SetInternalReference(cell, entry, "type", cell->type());
 }
 
 
@@ -1562,6 +1573,7 @@
       && object != heap_->empty_fixed_array()
       && object != heap_->empty_descriptor_array()
       && object != heap_->fixed_array_map()
+      && object != heap_->cell_map()
       && object != heap_->global_property_cell_map()
       && object != heap_->shared_function_info_map()
       && object != heap_->free_space_map()
@@ -2210,6 +2222,8 @@
   CHECK(!debug_heap->old_pointer_space()->was_swept_conservatively());
   CHECK(!debug_heap->code_space()->was_swept_conservatively());
   CHECK(!debug_heap->cell_space()->was_swept_conservatively());
+  CHECK(!debug_heap->property_cell_space()->
+        was_swept_conservatively());
   CHECK(!debug_heap->map_space()->was_swept_conservatively());
 #endif
 
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index 223b240..3a91f74 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -464,6 +464,7 @@
   void ExtractScriptReferences(int entry, Script* script);
   void ExtractCodeCacheReferences(int entry, CodeCache* code_cache);
   void ExtractCodeReferences(int entry, Code* code);
+  void ExtractCellReferences(int entry, Cell* cell);
   void ExtractJSGlobalPropertyCellReferences(int entry,
                                              JSGlobalPropertyCell* cell);
   void ExtractClosureReferences(JSObject* js_obj, int entry);
diff --git a/src/heap.cc b/src/heap.cc
index 2817fcb..1df9fa1 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -105,6 +105,7 @@
       code_space_(NULL),
       map_space_(NULL),
       cell_space_(NULL),
+      property_cell_space_(NULL),
       lo_space_(NULL),
       gc_state_(NOT_IN_GC),
       gc_post_processing_depth_(0),
@@ -199,7 +200,8 @@
       old_data_space_->Capacity() +
       code_space_->Capacity() +
       map_space_->Capacity() +
-      cell_space_->Capacity();
+      cell_space_->Capacity() +
+      property_cell_space_->Capacity();
 }
 
 
@@ -212,6 +214,7 @@
       code_space_->CommittedMemory() +
       map_space_->CommittedMemory() +
       cell_space_->CommittedMemory() +
+      property_cell_space_->CommittedMemory() +
       lo_space_->Size();
 }
 
@@ -225,6 +228,7 @@
       code_space_->CommittedPhysicalMemory() +
       map_space_->CommittedPhysicalMemory() +
       cell_space_->CommittedPhysicalMemory() +
+      property_cell_space_->CommittedPhysicalMemory() +
       lo_space_->CommittedPhysicalMemory();
 }
 
@@ -244,7 +248,8 @@
       old_data_space_->Available() +
       code_space_->Available() +
       map_space_->Available() +
-      cell_space_->Available();
+      cell_space_->Available() +
+      property_cell_space_->Available();
 }
 
 
@@ -254,6 +259,7 @@
          code_space_ != NULL &&
          map_space_ != NULL &&
          cell_space_ != NULL &&
+         property_cell_space_ != NULL &&
          lo_space_ != NULL;
 }
 
@@ -383,6 +389,12 @@
            cell_space_->SizeOfObjects() / KB,
            cell_space_->Available() / KB,
            cell_space_->CommittedMemory() / KB);
+  PrintPID("PropertyCell space, used: %6" V8_PTR_PREFIX "d KB"
+               ", available: %6" V8_PTR_PREFIX "d KB"
+               ", committed: %6" V8_PTR_PREFIX "d KB\n",
+           property_cell_space_->SizeOfObjects() / KB,
+           property_cell_space_->Available() / KB,
+           property_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",
@@ -514,6 +526,10 @@
     isolate_->counters()->heap_fraction_cell_space()->AddSample(
         static_cast<int>(
             (cell_space()->CommittedMemory() * 100.0) / CommittedMemory()));
+    isolate_->counters()->heap_fraction_property_cell_space()->
+        AddSample(static_cast<int>(
+            (property_cell_space()->CommittedMemory() * 100.0) /
+            CommittedMemory()));
 
     isolate_->counters()->heap_sample_total_committed()->AddSample(
         static_cast<int>(CommittedMemory() / KB));
@@ -523,6 +539,10 @@
         static_cast<int>(map_space()->CommittedMemory() / KB));
     isolate_->counters()->heap_sample_cell_space_committed()->AddSample(
         static_cast<int>(cell_space()->CommittedMemory() / KB));
+    isolate_->counters()->
+        heap_sample_property_cell_space_committed()->
+            AddSample(static_cast<int>(
+                property_cell_space()->CommittedMemory() / KB));
   }
 
 #define UPDATE_COUNTERS_FOR_SPACE(space)                                       \
@@ -548,6 +568,7 @@
   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(code_space)
   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(map_space)
   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(cell_space)
+  UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(property_cell_space)
   UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(lo_space)
 #undef UPDATE_COUNTERS_FOR_SPACE
 #undef UPDATE_FRAGMENTATION_FOR_SPACE
@@ -1212,7 +1233,7 @@
       // Store Buffer overflowed while scanning promoted objects.  These are not
       // in any particular page, though they are likely to be clustered by the
       // allocation routines.
-      store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize);
+      store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize / 2);
     } else {
       // Store Buffer overflowed while scanning a particular old space page for
       // pointers to new space.
@@ -1353,15 +1374,31 @@
     store_buffer()->IteratePointersToNewSpace(&ScavengeObject);
   }
 
-  // Copy objects reachable from cells by scavenging cell values directly.
+  // Copy objects reachable from simple cells by scavenging cell values
+  // directly.
   HeapObjectIterator cell_iterator(cell_space_);
   for (HeapObject* heap_object = cell_iterator.Next();
        heap_object != NULL;
        heap_object = cell_iterator.Next()) {
+    if (heap_object->IsCell()) {
+      Cell* cell = Cell::cast(heap_object);
+      Address value_address = cell->ValueAddress();
+      scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
+    }
+  }
+
+  // Copy objects reachable from global property cells by scavenging global
+  // property cell values directly.
+  HeapObjectIterator js_global_property_cell_iterator(property_cell_space_);
+  for (HeapObject* heap_object = js_global_property_cell_iterator.Next();
+       heap_object != NULL;
+       heap_object = js_global_property_cell_iterator.Next()) {
     if (heap_object->IsJSGlobalPropertyCell()) {
       JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(heap_object);
       Address value_address = cell->ValueAddress();
       scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
+      Address type_address = cell->TypeAddress();
+      scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(type_address));
     }
   }
 
@@ -1490,55 +1527,121 @@
 }
 
 
-static Object* ProcessFunctionWeakReferences(Heap* heap,
-                                             Object* function,
-                                             WeakObjectRetainer* retainer,
-                                             bool record_slots) {
+template <class T>
+struct WeakListVisitor;
+
+
+template <class T>
+static Object* VisitWeakList(Heap* heap,
+                             Object* list,
+                             WeakObjectRetainer* retainer,
+                             bool record_slots) {
   Object* undefined = heap->undefined_value();
   Object* head = undefined;
-  JSFunction* tail = NULL;
-  Object* candidate = function;
-  while (candidate != undefined) {
+  T* tail = NULL;
+  MarkCompactCollector* collector = heap->mark_compact_collector();
+  while (list != undefined) {
     // Check whether to keep the candidate in the list.
-    JSFunction* candidate_function = reinterpret_cast<JSFunction*>(candidate);
-    Object* retain = retainer->RetainAs(candidate);
-    if (retain != NULL) {
+    T* candidate = reinterpret_cast<T*>(list);
+    Object* retained = retainer->RetainAs(list);
+    if (retained != NULL) {
       if (head == undefined) {
         // First element in the list.
-        head = retain;
+        head = retained;
       } else {
         // Subsequent elements in the list.
         ASSERT(tail != NULL);
-        tail->set_next_function_link(retain);
+        WeakListVisitor<T>::SetWeakNext(tail, retained);
         if (record_slots) {
-          Object** next_function =
-              HeapObject::RawField(tail, JSFunction::kNextFunctionLinkOffset);
-          heap->mark_compact_collector()->RecordSlot(
-              next_function, next_function, retain);
+          Object** next_slot =
+            HeapObject::RawField(tail, WeakListVisitor<T>::WeakNextOffset());
+          collector->RecordSlot(next_slot, next_slot, retained);
         }
       }
-      // Retained function is new tail.
-      candidate_function = reinterpret_cast<JSFunction*>(retain);
-      tail = candidate_function;
+      // Retained object is new tail.
+      ASSERT(!retained->IsUndefined());
+      candidate = reinterpret_cast<T*>(retained);
+      tail = candidate;
 
-      ASSERT(retain->IsUndefined() || retain->IsJSFunction());
 
-      if (retain == undefined) break;
+      // tail is a live object, visit it.
+      WeakListVisitor<T>::VisitLiveObject(
+          heap, tail, retainer, record_slots);
     }
 
     // Move to next element in the list.
-    candidate = candidate_function->next_function_link();
+    list = WeakListVisitor<T>::WeakNext(candidate);
   }
 
   // Terminate the list if there is one or more elements.
   if (tail != NULL) {
-    tail->set_next_function_link(undefined);
+    WeakListVisitor<T>::SetWeakNext(tail, undefined);
   }
-
   return head;
 }
 
 
+template<>
+struct WeakListVisitor<JSFunction> {
+  static void SetWeakNext(JSFunction* function, Object* next) {
+    function->set_next_function_link(next);
+  }
+
+  static Object* WeakNext(JSFunction* function) {
+    return function->next_function_link();
+  }
+
+  static int WeakNextOffset() {
+    return JSFunction::kNextFunctionLinkOffset;
+  }
+
+  static void VisitLiveObject(Heap*, JSFunction*,
+                              WeakObjectRetainer*, bool) {
+  }
+};
+
+
+template<>
+struct WeakListVisitor<Context> {
+  static void SetWeakNext(Context* context, Object* next) {
+    context->set(Context::NEXT_CONTEXT_LINK,
+                 next,
+                 UPDATE_WRITE_BARRIER);
+  }
+
+  static Object* WeakNext(Context* context) {
+    return context->get(Context::NEXT_CONTEXT_LINK);
+  }
+
+  static void VisitLiveObject(Heap* heap,
+                              Context* context,
+                              WeakObjectRetainer* retainer,
+                              bool record_slots) {
+    // Process the weak list of optimized functions for the context.
+    Object* function_list_head =
+        VisitWeakList<JSFunction>(
+            heap,
+            context->get(Context::OPTIMIZED_FUNCTIONS_LIST),
+            retainer,
+            record_slots);
+    context->set(Context::OPTIMIZED_FUNCTIONS_LIST,
+                 function_list_head,
+                 UPDATE_WRITE_BARRIER);
+    if (record_slots) {
+      Object** optimized_functions =
+          HeapObject::RawField(
+              context, FixedArray::SizeFor(Context::OPTIMIZED_FUNCTIONS_LIST));
+      heap->mark_compact_collector()->RecordSlot(
+          optimized_functions, optimized_functions, function_list_head);
+    }
+  }
+
+  static int WeakNextOffset() {
+    return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK);
+  }
+};
+
+
 void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
   // We don't record weak slots during marking or scavenges.
   // Instead we do it once when we complete mark-compact cycle.
@@ -1553,168 +1656,73 @@
 
 void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer,
                                  bool record_slots) {
-  Object* undefined = undefined_value();
-  Object* head = undefined;
-  Context* tail = NULL;
-  Object* candidate = native_contexts_list_;
-
-  while (candidate != undefined) {
-    // Check whether to keep the candidate in the list.
-    Context* candidate_context = reinterpret_cast<Context*>(candidate);
-    Object* retain = retainer->RetainAs(candidate);
-    if (retain != NULL) {
-      if (head == undefined) {
-        // First element in the list.
-        head = retain;
-      } else {
-        // Subsequent elements in the list.
-        ASSERT(tail != NULL);
-        tail->set_unchecked(this,
-                            Context::NEXT_CONTEXT_LINK,
-                            retain,
-                            UPDATE_WRITE_BARRIER);
-
-        if (record_slots) {
-          Object** next_context =
-              HeapObject::RawField(
-                  tail, FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK));
-          mark_compact_collector()->RecordSlot(
-              next_context, next_context, retain);
-        }
-      }
-      // Retained context is new tail.
-      candidate_context = reinterpret_cast<Context*>(retain);
-      tail = candidate_context;
-
-      if (retain == undefined) break;
-
-      // Process the weak list of optimized functions for the context.
-      Object* function_list_head =
-          ProcessFunctionWeakReferences(
-              this,
-              candidate_context->get(Context::OPTIMIZED_FUNCTIONS_LIST),
-              retainer,
-              record_slots);
-      candidate_context->set_unchecked(this,
-                                       Context::OPTIMIZED_FUNCTIONS_LIST,
-                                       function_list_head,
-                                       UPDATE_WRITE_BARRIER);
-      if (record_slots) {
-        Object** optimized_functions =
-            HeapObject::RawField(
-                tail, FixedArray::SizeFor(Context::OPTIMIZED_FUNCTIONS_LIST));
-        mark_compact_collector()->RecordSlot(
-            optimized_functions, optimized_functions, function_list_head);
-      }
-    }
-
-    // Move to next element in the list.
-    candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK);
-  }
-
-  // Terminate the list if there is one or more elements.
-  if (tail != NULL) {
-    tail->set_unchecked(this,
-                        Context::NEXT_CONTEXT_LINK,
-                        Heap::undefined_value(),
-                        UPDATE_WRITE_BARRIER);
-  }
-
+  Object* head =
+      VisitWeakList<Context>(
+          this, native_contexts_list(), retainer, record_slots);
   // Update the head of the list of contexts.
   native_contexts_list_ = head;
 }
 
 
-template <class T>
-struct WeakListVisitor;
-
-
-template <class T>
-static Object* VisitWeakList(Object* list,
-                      MarkCompactCollector* collector,
-                      WeakObjectRetainer* retainer, bool record_slots) {
-  Object* head = Smi::FromInt(0);
-  T* tail = NULL;
-  while (list != Smi::FromInt(0)) {
-    Object* retained = retainer->RetainAs(list);
-    if (retained != NULL) {
-      if (head == Smi::FromInt(0)) {
-        head = retained;
-      } else {
-        ASSERT(tail != NULL);
-        WeakListVisitor<T>::set_weak_next(tail, retained);
-        if (record_slots) {
-          Object** next_slot =
-            HeapObject::RawField(tail, WeakListVisitor<T>::kWeakNextOffset);
-          collector->RecordSlot(next_slot, next_slot, retained);
-        }
-      }
-      tail = reinterpret_cast<T*>(retained);
-      WeakListVisitor<T>::VisitLiveObject(
-          tail, collector, retainer, record_slots);
-    }
-    list = WeakListVisitor<T>::get_weak_next(reinterpret_cast<T*>(list));
-  }
-  if (tail != NULL) {
-    tail->set_weak_next(Smi::FromInt(0));
-  }
-  return head;
-}
-
-
 template<>
 struct WeakListVisitor<JSTypedArray> {
-  static void set_weak_next(JSTypedArray* obj, Object* next) {
+  static void SetWeakNext(JSTypedArray* obj, Object* next) {
     obj->set_weak_next(next);
   }
 
-  static Object* get_weak_next(JSTypedArray* obj) {
+  static Object* WeakNext(JSTypedArray* obj) {
     return obj->weak_next();
   }
 
-  static void VisitLiveObject(JSTypedArray* obj,
-                              MarkCompactCollector* collector,
+  static void VisitLiveObject(Heap*,
+                              JSTypedArray* obj,
                               WeakObjectRetainer* retainer,
                               bool record_slots) {}
 
-  static const int kWeakNextOffset = JSTypedArray::kWeakNextOffset;
+  static int WeakNextOffset() {
+    return JSTypedArray::kWeakNextOffset;
+  }
 };
 
 
 template<>
 struct WeakListVisitor<JSArrayBuffer> {
-  static void set_weak_next(JSArrayBuffer* obj, Object* next) {
+  static void SetWeakNext(JSArrayBuffer* obj, Object* next) {
     obj->set_weak_next(next);
   }
 
-  static Object* get_weak_next(JSArrayBuffer* obj) {
+  static Object* WeakNext(JSArrayBuffer* obj) {
     return obj->weak_next();
   }
 
-  static void VisitLiveObject(JSArrayBuffer* array_buffer,
-                              MarkCompactCollector* collector,
+  static void VisitLiveObject(Heap* heap,
+                              JSArrayBuffer* array_buffer,
                               WeakObjectRetainer* retainer,
                               bool record_slots) {
     Object* typed_array_obj =
-        VisitWeakList<JSTypedArray>(array_buffer->weak_first_array(),
-                                    collector, retainer, record_slots);
+        VisitWeakList<JSTypedArray>(
+            heap,
+            array_buffer->weak_first_array(),
+            retainer, record_slots);
     array_buffer->set_weak_first_array(typed_array_obj);
-    if (typed_array_obj != Smi::FromInt(0) && record_slots) {
+    if (typed_array_obj != heap->undefined_value() && record_slots) {
       Object** slot = HeapObject::RawField(
           array_buffer, JSArrayBuffer::kWeakFirstArrayOffset);
-      collector->RecordSlot(slot, slot, typed_array_obj);
+      heap->mark_compact_collector()->RecordSlot(slot, slot, typed_array_obj);
     }
   }
 
-  static const int kWeakNextOffset = JSArrayBuffer::kWeakNextOffset;
+  static int WeakNextOffset() {
+    return JSArrayBuffer::kWeakNextOffset;
+  }
 };
 
 
 void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer,
                                bool record_slots) {
   Object* array_buffer_obj =
-      VisitWeakList<JSArrayBuffer>(array_buffers_list(),
-                                   mark_compact_collector(),
+      VisitWeakList<JSArrayBuffer>(this,
+                                   array_buffers_list(),
                                    retainer, record_slots);
   set_array_buffers_list(array_buffer_obj);
 }
@@ -2663,7 +2671,12 @@
   }
   set_code_map(Map::cast(obj));
 
-  { MaybeObject* maybe_obj = AllocateMap(JS_GLOBAL_PROPERTY_CELL_TYPE,
+  { MaybeObject* maybe_obj = AllocateMap(CELL_TYPE, Cell::kSize);
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_cell_map(Map::cast(obj));
+
+  { MaybeObject* maybe_obj = AllocateMap(PROPERTY_CELL_TYPE,
                                          JSGlobalPropertyCell::kSize);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
@@ -2798,14 +2811,26 @@
 }
 
 
-MaybeObject* Heap::AllocateJSGlobalPropertyCell(Object* value) {
+MaybeObject* Heap::AllocateCell(Object* value) {
   Object* result;
   { MaybeObject* maybe_result = AllocateRawCell();
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
+  HeapObject::cast(result)->set_map_no_write_barrier(cell_map());
+  Cell::cast(result)->set_value(value);
+  return result;
+}
+
+
+MaybeObject* Heap::AllocateJSGlobalPropertyCell(Object* value) {
+  Object* result;
+  { MaybeObject* maybe_result = AllocateRawJSGlobalPropertyCell();
+    if (!maybe_result->ToObject(&result)) return maybe_result;
+  }
   HeapObject::cast(result)->set_map_no_write_barrier(
       global_property_cell_map());
   JSGlobalPropertyCell::cast(result)->set_value(value);
+  JSGlobalPropertyCell::cast(result)->set_type(Type::None());
   return result;
 }
 
@@ -4469,8 +4494,7 @@
   // advice
   Map* initial_map = constructor->initial_map();
 
-  JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
-      *allocation_site_info_payload);
+  Cell* cell = Cell::cast(*allocation_site_info_payload);
   Smi* smi = Smi::cast(cell->value());
   ElementsKind to_kind = static_cast<ElementsKind>(smi->value());
   AllocationSiteMode mode = TRACK_ALLOCATION_SITE;
@@ -6052,6 +6076,8 @@
   map_space_->ReportStatistics();
   PrintF("Cell space : ");
   cell_space_->ReportStatistics();
+  PrintF("JSGlobalPropertyCell space : ");
+  property_cell_space_->ReportStatistics();
   PrintF("Large object space : ");
   lo_space_->ReportStatistics();
   PrintF(">>>>>> ========================================= >>>>>>\n");
@@ -6073,6 +6099,7 @@
      code_space_->Contains(addr) ||
      map_space_->Contains(addr) ||
      cell_space_->Contains(addr) ||
+     property_cell_space_->Contains(addr) ||
      lo_space_->SlowContains(addr));
 }
 
@@ -6099,6 +6126,8 @@
       return map_space_->Contains(addr);
     case CELL_SPACE:
       return cell_space_->Contains(addr);
+    case PROPERTY_CELL_SPACE:
+      return property_cell_space_->Contains(addr);
     case LO_SPACE:
       return lo_space_->SlowContains(addr);
   }
@@ -6125,6 +6154,7 @@
   old_data_space_->Verify(&no_dirty_regions_visitor);
   code_space_->Verify(&no_dirty_regions_visitor);
   cell_space_->Verify(&no_dirty_regions_visitor);
+  property_cell_space_->Verify(&no_dirty_regions_visitor);
 
   lo_space_->Verify();
 }
@@ -6624,6 +6654,8 @@
   *stats->map_space_capacity = map_space_->Capacity();
   *stats->cell_space_size = cell_space_->SizeOfObjects();
   *stats->cell_space_capacity = cell_space_->Capacity();
+  *stats->property_cell_space_size = property_cell_space_->SizeOfObjects();
+  *stats->property_cell_space_capacity = property_cell_space_->Capacity();
   *stats->lo_space_size = lo_space_->Size();
   isolate_->global_handles()->RecordStats(stats);
   *stats->memory_allocator_size = isolate()->memory_allocator()->Size();
@@ -6652,6 +6684,7 @@
       + code_space_->SizeOfObjects()
       + map_space_->SizeOfObjects()
       + cell_space_->SizeOfObjects()
+      + property_cell_space_->SizeOfObjects()
       + lo_space_->SizeOfObjects();
 }
 
@@ -6740,11 +6773,17 @@
   if (map_space_ == NULL) return false;
   if (!map_space_->SetUp()) return false;
 
-  // Initialize global property cell space.
+  // Initialize simple cell space.
   cell_space_ = new CellSpace(this, max_old_generation_size_, CELL_SPACE);
   if (cell_space_ == NULL) return false;
   if (!cell_space_->SetUp()) return false;
 
+  // Initialize global property cell space.
+  property_cell_space_ = new PropertyCellSpace(this, max_old_generation_size_,
+                                               PROPERTY_CELL_SPACE);
+  if (property_cell_space_ == NULL) return false;
+  if (!property_cell_space_->SetUp()) return false;
+
   // The large object code space may contain code or data.  We set the memory
   // to be non-executable here for safety, but this means we need to enable it
   // explicitly when allocating large code objects.
@@ -6785,6 +6824,7 @@
   if (!CreateInitialObjects()) return false;
 
   native_contexts_list_ = undefined_value();
+  array_buffers_list_ = undefined_value();
   return true;
 }
 
@@ -6865,6 +6905,12 @@
     cell_space_ = NULL;
   }
 
+  if (property_cell_space_ != NULL) {
+    property_cell_space_->TearDown();
+    delete property_cell_space_;
+    property_cell_space_ = NULL;
+  }
+
   if (lo_space_ != NULL) {
     lo_space_->TearDown();
     delete lo_space_;
@@ -6955,6 +7001,8 @@
       return heap_->map_space();
     case CELL_SPACE:
       return heap_->cell_space();
+    case PROPERTY_CELL_SPACE:
+      return heap_->property_cell_space();
     case LO_SPACE:
       return heap_->lo_space();
     default:
@@ -6975,6 +7023,8 @@
       return heap_->map_space();
     case CELL_SPACE:
       return heap_->cell_space();
+    case PROPERTY_CELL_SPACE:
+      return heap_->property_cell_space();
     default:
       return NULL;
   }
@@ -7064,6 +7114,10 @@
     case CELL_SPACE:
       iterator_ = new HeapObjectIterator(heap_->cell_space(), size_func_);
       break;
+    case PROPERTY_CELL_SPACE:
+      iterator_ = new HeapObjectIterator(heap_->property_cell_space(),
+                                         size_func_);
+      break;
     case LO_SPACE:
       iterator_ = new LargeObjectIterator(heap_->lo_space(), size_func_);
       break;
diff --git a/src/heap.h b/src/heap.h
index da10efc..70d1ccb 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -60,6 +60,7 @@
   V(Oddball, true_value, TrueValue)                                            \
   V(Oddball, false_value, FalseValue)                                          \
   V(Oddball, uninitialized_value, UninitializedValue)                          \
+  V(Map, cell_map, CellMap)                                                    \
   V(Map, global_property_cell_map, GlobalPropertyCellMap)                      \
   V(Map, shared_function_info_map, SharedFunctionInfoMap)                      \
   V(Map, meta_map, MetaMap)                                                    \
@@ -588,6 +589,9 @@
   OldSpace* code_space() { return code_space_; }
   MapSpace* map_space() { return map_space_; }
   CellSpace* cell_space() { return cell_space_; }
+  PropertyCellSpace* property_cell_space() {
+    return property_cell_space_;
+  }
   LargeObjectSpace* lo_space() { return lo_space_; }
   PagedSpace* paged_space(int idx) {
     switch (idx) {
@@ -599,6 +603,8 @@
         return map_space();
       case CELL_SPACE:
         return cell_space();
+      case PROPERTY_CELL_SPACE:
+        return property_cell_space();
       case CODE_SPACE:
         return code_space();
       case NEW_SPACE:
@@ -933,6 +939,12 @@
   // Please note this does not perform a garbage collection.
   MUST_USE_RESULT MaybeObject* AllocateSymbol();
 
+  // Allocate a tenured simple cell.
+  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  MUST_USE_RESULT MaybeObject* AllocateCell(Object* value);
+
   // Allocate a tenured JS global property cell.
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
@@ -1958,6 +1970,7 @@
   OldSpace* code_space_;
   MapSpace* map_space_;
   CellSpace* cell_space_;
+  PropertyCellSpace* property_cell_space_;
   LargeObjectSpace* lo_space_;
   HeapState gc_state_;
   int gc_post_processing_depth_;
@@ -2114,9 +2127,12 @@
   // (since both AllocateRaw and AllocateRawMap are inlined).
   MUST_USE_RESULT inline MaybeObject* AllocateRawMap();
 
-  // Allocate an uninitialized object in the global property cell space.
+  // Allocate an uninitialized object in the simple cell space.
   MUST_USE_RESULT inline MaybeObject* AllocateRawCell();
 
+  // Allocate an uninitialized object in the global property cell space.
+  MUST_USE_RESULT inline MaybeObject* AllocateRawJSGlobalPropertyCell();
+
   // Initializes a JSObject based on its map.
   void InitializeJSObjectFromMap(JSObject* obj,
                                  FixedArray* properties,
@@ -2437,6 +2453,8 @@
   int* size_per_type;                   // 22
   int* os_error;                        // 23
   int* end_marker;                      // 24
+  intptr_t* property_cell_space_size;   // 25
+  intptr_t* property_cell_space_capacity;    // 26
 };
 
 
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 82ed261..d13a31b 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -2016,6 +2016,9 @@
 };
 
 
+class HArgumentsObject;
+
+
 class HEnterInlined: public HTemplateInstruction<0> {
  public:
   HEnterInlined(Handle<JSFunction> closure,
@@ -2023,7 +2026,7 @@
                 FunctionLiteral* function,
                 InliningKind inlining_kind,
                 Variable* arguments_var,
-                ZoneList<HValue*>* arguments_values,
+                HArgumentsObject* arguments_object,
                 bool undefined_receiver,
                 Zone* zone)
       : closure_(closure),
@@ -2032,7 +2035,7 @@
         function_(function),
         inlining_kind_(inlining_kind),
         arguments_var_(arguments_var),
-        arguments_values_(arguments_values),
+        arguments_object_(arguments_object),
         undefined_receiver_(undefined_receiver),
         return_targets_(2, zone) {
   }
@@ -2055,7 +2058,7 @@
   }
 
   Variable* arguments_var() { return arguments_var_; }
-  ZoneList<HValue*>* arguments_values() { return arguments_values_; }
+  HArgumentsObject* arguments_object() { return arguments_object_; }
 
   DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
 
@@ -2066,7 +2069,7 @@
   FunctionLiteral* function_;
   InliningKind inlining_kind_;
   Variable* arguments_var_;
-  ZoneList<HValue*>* arguments_values_;
+  HArgumentsObject* arguments_object_;
   bool undefined_receiver_;
   ZoneList<HBasicBlock*> return_targets_;
 };
@@ -2473,14 +2476,14 @@
 class HCallNewArray: public HCallNew {
  public:
   HCallNewArray(HValue* context, HValue* constructor, int argument_count,
-              Handle<JSGlobalPropertyCell> type_cell)
+                Handle<Cell> type_cell)
       : HCallNew(context, constructor, argument_count),
         type_cell_(type_cell) {
     elements_kind_ = static_cast<ElementsKind>(
         Smi::cast(type_cell->value())->value());
   }
 
-  Handle<JSGlobalPropertyCell> property_cell() const {
+  Handle<Cell> property_cell() const {
     return type_cell_;
   }
 
@@ -2490,7 +2493,7 @@
 
  private:
   ElementsKind elements_kind_;
-  Handle<JSGlobalPropertyCell> type_cell_;
+  Handle<Cell> type_cell_;
 };
 
 
@@ -2977,21 +2980,33 @@
  public:
   HCheckPrototypeMaps(Handle<JSObject> prototype,
                       Handle<JSObject> holder,
-                      Zone* zone)
+                      Zone* zone,
+                      CompilationInfo* info)
       : prototypes_(2, zone),
         maps_(2, zone),
         first_prototype_unique_id_(),
-        last_prototype_unique_id_() {
+        last_prototype_unique_id_(),
+        can_omit_prototype_maps_(true) {
     SetFlag(kUseGVN);
     SetGVNFlag(kDependsOnMaps);
     // Keep a list of all objects on the prototype chain up to the holder
     // and the expected maps.
     while (true) {
       prototypes_.Add(prototype, zone);
-      maps_.Add(Handle<Map>(prototype->map()), zone);
+      Handle<Map> map(prototype->map());
+      maps_.Add(map, zone);
+      can_omit_prototype_maps_ &= map->CanOmitPrototypeChecks();
       if (prototype.is_identical_to(holder)) break;
       prototype = Handle<JSObject>(JSObject::cast(prototype->GetPrototype()));
     }
+    if (can_omit_prototype_maps_) {
+      // Mark in-flight compilation as dependent on those maps.
+      for (int i = 0; i < maps()->length(); i++) {
+        Handle<Map> map = maps()->at(i);
+        map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup,
+                                         info);
+      }
+    }
   }
 
   ZoneList<Handle<JSObject> >* prototypes() { return &prototypes_; }
@@ -3016,12 +3031,7 @@
     last_prototype_unique_id_ = UniqueValueId(prototypes_.last());
   }
 
-  bool CanOmitPrototypeChecks() {
-    for (int i = 0; i < maps()->length(); i++) {
-      if (!maps()->at(i)->CanOmitPrototypeChecks()) return false;
-    }
-    return true;
-  }
+  bool CanOmitPrototypeChecks() { return can_omit_prototype_maps_; }
 
  protected:
   virtual bool DataEquals(HValue* other) {
@@ -3035,6 +3045,7 @@
   ZoneList<Handle<Map> > maps_;
   UniqueValueId first_prototype_unique_id_;
   UniqueValueId last_prototype_unique_id_;
+  bool can_omit_prototype_maps_;
 };
 
 
@@ -3194,19 +3205,37 @@
 
 class HArgumentsObject: public HTemplateInstruction<0> {
  public:
-  HArgumentsObject() {
+  HArgumentsObject(int count, Zone* zone) : values_(count, zone) {
     set_representation(Representation::Tagged());
     SetFlag(kIsArguments);
   }
 
+  const ZoneList<HValue*>* arguments_values() const { return &values_; }
+  int arguments_count() const { return values_.length(); }
+
+  void AddArgument(HValue* argument, Zone* zone) {
+    values_.Add(NULL, zone);  // Resize list.
+    SetOperandAt(values_.length() - 1, argument);
+  }
+
+  virtual int OperandCount() { return values_.length(); }
+  virtual HValue* OperandAt(int index) const { return values_[index]; }
+
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
   }
 
   DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
 
+ protected:
+  virtual void InternalSetOperandAt(int index, HValue* value) {
+    values_[index] = value;
+  }
+
  private:
   virtual bool IsDeletable() const { return true; }
+
+  ZoneList<HValue*> values_;
 };
 
 
@@ -4824,14 +4853,14 @@
 
 class HLoadGlobalCell: public HTemplateInstruction<0> {
  public:
-  HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
+  HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
       : cell_(cell), details_(details), unique_id_() {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
     SetGVNFlag(kDependsOnGlobalVars);
   }
 
-  Handle<JSGlobalPropertyCell> cell() const { return cell_; }
+  Handle<Cell> cell() const { return cell_; }
   bool RequiresHoleCheck() const;
 
   virtual void PrintDataTo(StringStream* stream);
@@ -4859,7 +4888,7 @@
  private:
   virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
 
-  Handle<JSGlobalPropertyCell> cell_;
+  Handle<Cell> cell_;
   PropertyDetails details_;
   UniqueValueId unique_id_;
 };
@@ -5691,6 +5720,7 @@
                        = Representation::Tagged())
       : access_(access),
         field_representation_(field_representation),
+        transition_(),
         transition_unique_id_(),
         new_space_dominator_(NULL) {
     SetOperandAt(0, obj);
@@ -5722,7 +5752,13 @@
   HObjectAccess access() const { return access_; }
   Handle<Map> transition() const { return transition_; }
   UniqueValueId transition_unique_id() const { return transition_unique_id_; }
-  void set_transition(Handle<Map> map) { transition_ = map; }
+  void SetTransition(Handle<Map> map, CompilationInfo* info) {
+    ASSERT(transition_.is_null());  // Only set once.
+    if (map->CanBeDeprecated()) {
+      map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
+    }
+    transition_ = map;
+  }
   HValue* new_space_dominator() const { return new_space_dominator_; }
 
   bool NeedsWriteBarrier() {
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index b2badcd..3d0d550 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1698,39 +1698,35 @@
 
 void HGraphBuilder::BuildCompareNil(
     HValue* value,
-    CompareNilICStub::Types types,
-    Handle<Map> map,
+    Handle<Type> type,
     int position,
     HIfContinuation* continuation) {
   IfBuilder if_nil(this, position);
   bool needs_or = false;
-  if (types.Contains(CompareNilICStub::NULL_TYPE)) {
+  if (type->Maybe(Type::Null())) {
     if (needs_or) if_nil.Or();
     if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
     needs_or = true;
   }
-  if (types.Contains(CompareNilICStub::UNDEFINED)) {
+  if (type->Maybe(Type::Undefined())) {
     if (needs_or) if_nil.Or();
     if_nil.If<HCompareObjectEqAndBranch>(value,
                                          graph()->GetConstantUndefined());
     needs_or = true;
   }
-  // Handle either undetectable or monomorphic, not both.
-  ASSERT(!types.Contains(CompareNilICStub::UNDETECTABLE) ||
-         !types.Contains(CompareNilICStub::MONOMORPHIC_MAP));
-  if (types.Contains(CompareNilICStub::UNDETECTABLE)) {
+  if (type->Maybe(Type::Undetectable())) {
     if (needs_or) if_nil.Or();
     if_nil.If<HIsUndetectableAndBranch>(value);
   } else {
     if_nil.Then();
     if_nil.Else();
-    if (!map.is_null() && types.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
+    if (type->NumClasses() == 1) {
       BuildCheckNonSmi(value);
       // For ICs, the map checked below is a sentinel map that gets replaced by
       // the monomorphic map when the code is used as a template to generate a
       // new IC. For optimized functions, there is no sentinel map, the map
       // emitted below is the actual monomorphic map.
-      BuildCheckMap(value, map);
+      BuildCheckMap(value, type->Classes().Current());
     } else {
       if_nil.Deopt();
     }
@@ -3550,6 +3546,7 @@
       function_return_(NULL),
       test_context_(NULL),
       entry_(NULL),
+      arguments_object_(NULL),
       arguments_elements_(NULL),
       outer_(owner->function_state()) {
   if (outer_ != NULL) {
@@ -3823,7 +3820,7 @@
 
 
 void HOptimizedGraphBuilder::Bailout(const char* reason) {
-  info()->set_bailout_reason(reason);
+  current_info()->set_bailout_reason(reason);
   SetStackOverflow();
 }
 
@@ -3880,11 +3877,11 @@
 
 
 bool HOptimizedGraphBuilder::BuildGraph() {
-  if (info()->function()->is_generator()) {
+  if (current_info()->function()->is_generator()) {
     Bailout("function is a generator");
     return false;
   }
-  Scope* scope = info()->scope();
+  Scope* scope = current_info()->scope();
   if (scope->HasIllegalRedeclaration()) {
     Bailout("function with illegal redeclaration");
     return false;
@@ -3928,7 +3925,7 @@
   AddInstruction(
       new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
 
-  VisitStatements(info()->function()->body());
+  VisitStatements(current_info()->function()->body());
   if (HasStackOverflow()) return false;
 
   if (current_block() != NULL) {
@@ -3940,7 +3937,7 @@
   // last time this function was compiled, then this recompile is likely not
   // due to missing/inadequate type feedback, but rather too aggressive
   // optimization. Disable optimistic LICM in that case.
-  Handle<Code> unoptimized_code(info()->shared_info()->code());
+  Handle<Code> unoptimized_code(current_info()->shared_info()->code());
   ASSERT(unoptimized_code->kind() == Code::FUNCTION);
   Handle<TypeFeedbackInfo> type_info(
       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
@@ -4701,18 +4698,18 @@
   AddInstruction(undefined_constant);
   graph()->set_undefined_constant(undefined_constant);
 
-  HArgumentsObject* object = new(zone()) HArgumentsObject;
-  AddInstruction(object);
-  graph()->SetArgumentsObject(object);
-
-  // Set the initial values of parameters including "this".  "This" has
-  // parameter index 0.
+  // Create an arguments object containing the initial parameters.  Set the
+  // initial values of parameters including "this" having parameter index 0.
   ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
-
+  HArgumentsObject* arguments_object =
+      new(zone()) HArgumentsObject(environment()->parameter_count(), zone());
   for (int i = 0; i < environment()->parameter_count(); ++i) {
     HInstruction* parameter = AddInstruction(new(zone()) HParameter(i));
+    arguments_object->AddArgument(parameter, zone());
     environment()->Bind(i, parameter);
   }
+  AddInstruction(arguments_object);
+  graph()->SetArgumentsObject(arguments_object);
 
   // First special is HContext.
   HInstruction* context = AddInstruction(new(zone()) HContext);
@@ -5027,7 +5024,7 @@
     HControlInstruction* compare;
 
     if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
-      if (!clause->IsSmiCompare()) {
+      if (!clause->compare_type()->Is(Type::Integer31())) {
         AddSoftDeoptimize();
       }
 
@@ -5129,7 +5126,7 @@
 
 
 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
-  return statement->OsrEntryId() == info()->osr_ast_id();
+  return statement->OsrEntryId() == current_info()->osr_ast_id();
 }
 
 
@@ -5516,9 +5513,9 @@
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   Handle<SharedFunctionInfo> shared_info =
-      SearchSharedFunctionInfo(info()->shared_info()->code(), expr);
+      SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr);
   if (shared_info.is_null()) {
-    shared_info = Compiler::BuildFunctionInfo(expr, info()->script());
+    shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script());
   }
   // We also have a stack overflow if the recursive compilation did.
   if (HasStackOverflow()) return;
@@ -5579,10 +5576,10 @@
 HOptimizedGraphBuilder::GlobalPropertyAccess
     HOptimizedGraphBuilder::LookupGlobalProperty(
         Variable* var, LookupResult* lookup, bool is_store) {
-  if (var->is_this() || !info()->has_global_object()) {
+  if (var->is_this() || !current_info()->has_global_object()) {
     return kUseGeneric;
   }
-  Handle<GlobalObject> global(info()->global_object());
+  Handle<GlobalObject> global(current_info()->global_object());
   global->Lookup(*var->name(), lookup);
   if (!lookup->IsNormal() ||
       (is_store && lookup->IsReadOnly()) ||
@@ -5597,7 +5594,7 @@
 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
   ASSERT(var->IsContextSlot());
   HValue* context = environment()->LookupContext();
-  int length = info()->scope()->ContextChainLength(var->scope());
+  int length = current_info()->scope()->ContextChainLength(var->scope());
   while (length-- > 0) {
     HInstruction* context_instruction = new(zone()) HOuterContext(context);
     AddInstruction(context_instruction);
@@ -5633,12 +5630,12 @@
           LookupGlobalProperty(variable, &lookup, false);
 
       if (type == kUseCell &&
-          info()->global_object()->IsAccessCheckNeeded()) {
+          current_info()->global_object()->IsAccessCheckNeeded()) {
         type = kUseGeneric;
       }
 
       if (type == kUseCell) {
-        Handle<GlobalObject> global(info()->global_object());
+        Handle<GlobalObject> global(current_info()->global_object());
         Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
         HLoadGlobalCell* instr =
             new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
@@ -6229,7 +6226,8 @@
     AddInstruction(new(zone()) HCheckPrototypeMaps(
         Handle<JSObject>(JSObject::cast(map->prototype())),
         Handle<JSObject>(JSObject::cast(proto)),
-        zone()));
+        zone(),
+        top_info()));
   }
 
   HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
@@ -6265,7 +6263,7 @@
 
   if (transition_to_field) {
     Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
-    instr->set_transition(transition);
+    instr->SetTransition(transition, top_info());
     // TODO(fschneider): Record the new map type of the object in the IR to
     // enable elimination of redundant checks after the transition store.
     instr->SetGVNFlag(kChangesMaps);
@@ -6568,7 +6566,7 @@
   LookupResult lookup(isolate());
   GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
   if (type == kUseCell) {
-    Handle<GlobalObject> global(info()->global_object());
+    Handle<GlobalObject> global(current_info()->global_object());
     Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
     HInstruction* instr =
         new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails());
@@ -6633,13 +6631,13 @@
         // Bail out if we try to mutate a parameter value in a function
         // using the arguments object.  We do not (yet) correctly handle the
         // arguments property of the function.
-        if (info()->scope()->arguments() != NULL) {
+        if (current_info()->scope()->arguments() != NULL) {
           // Parameters will be allocated to context slots.  We have no
           // direct way to detect that the variable is a parameter so we do
           // a linear search of the parameter variables.
-          int count = info()->scope()->num_parameters();
+          int count = current_info()->scope()->num_parameters();
           for (int i = 0; i < count; ++i) {
-            if (var == info()->scope()->parameter(i)) {
+            if (var == current_info()->scope()->parameter(i)) {
               Bailout(
                   "assignment to parameter, function uses arguments object");
             }
@@ -6859,12 +6857,12 @@
         // Bail out if we try to mutate a parameter value in a function using
         // the arguments object.  We do not (yet) correctly handle the
         // arguments property of the function.
-        if (info()->scope()->arguments() != NULL) {
+        if (current_info()->scope()->arguments() != NULL) {
           // Parameters will rewrite to context slots.  We have no direct way
           // to detect that the variable is a parameter.
-          int count = info()->scope()->num_parameters();
+          int count = current_info()->scope()->num_parameters();
           for (int i = 0; i < count; ++i) {
-            if (var == info()->scope()->parameter(i)) {
+            if (var == current_info()->scope()->parameter(i)) {
               return Bailout("assignment to parameter in arguments object");
             }
           }
@@ -7026,8 +7024,8 @@
     Handle<JSObject> holder(lookup.holder());
     Handle<Map> holder_map(holder->map());
     AddCheckMap(object, map);
-    AddInstruction(
-        new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
+    AddInstruction(new(zone()) HCheckPrototypeMaps(
+        prototype, holder, zone(), top_info()));
     HValue* holder_value = AddInstruction(new(zone())
         HConstant(holder, Representation::Tagged()));
     return BuildLoadNamedField(holder_value,
@@ -7041,7 +7039,8 @@
     Handle<JSObject> holder(lookup.holder());
     Handle<Map> holder_map(holder->map());
     AddCheckMap(object, map);
-    AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
+    AddInstruction(new(zone()) HCheckPrototypeMaps(
+        prototype, holder, zone(), top_info()));
     Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map));
     return new(zone()) HConstant(function, Representation::Tagged());
   }
@@ -7078,8 +7077,8 @@
       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
-    AddInstruction(
-        new(zone()) HCheckPrototypeMaps(prototype, object_prototype, zone()));
+    AddInstruction(new(zone()) HCheckPrototypeMaps(
+        prototype, object_prototype, zone(), top_info()));
     load_mode = ALLOW_RETURN_HOLE;
     graph()->MarkDependsOnEmptyArrayProtoElements();
   }
@@ -7430,7 +7429,8 @@
   HEnterInlined* entry = function_state()->entry();
   entry->set_arguments_pushed();
 
-  ZoneList<HValue*>* arguments_values = entry->arguments_values();
+  HArgumentsObject* arguments = entry->arguments_object();
+  const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
 
   HInstruction* insert_after = entry;
   for (int i = 0; i < arguments_values->length(); i++) {
@@ -7594,8 +7594,8 @@
                                                    Handle<Map> receiver_map) {
   if (!holder.is_null()) {
     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
-    AddInstruction(
-        new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
+    AddInstruction(new(zone()) HCheckPrototypeMaps(
+        prototype, holder, zone(), top_info()));
   }
 }
 
@@ -7740,7 +7740,7 @@
     expr->ComputeTarget(map, name);
     AddCheckPrototypeMaps(expr->holder(), map);
     if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
-      Handle<JSFunction> caller = info()->closure();
+      Handle<JSFunction> caller = current_info()->closure();
       SmartArrayPointer<char> caller_name =
           caller->shared()->DebugName()->ToCString();
       PrintF("Trying to inline the polymorphic call to %s from %s\n",
@@ -7824,7 +7824,7 @@
 
   // Precondition: call is monomorphic and we have found a target with the
   // appropriate arity.
-  Handle<JSFunction> caller = info()->closure();
+  Handle<JSFunction> caller = current_info()->closure();
   Handle<SharedFunctionInfo> target_shared(target->shared());
 
   // Do a quick check on source code length to avoid parsing large
@@ -7860,7 +7860,7 @@
   int nodes_added = InliningAstSize(target);
   if (nodes_added == kNotInlinable) return false;
 
-  Handle<JSFunction> caller = info()->closure();
+  Handle<JSFunction> caller = current_info()->closure();
 
   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
     TraceInline(target, caller, "target AST is too large [early]");
@@ -7869,7 +7869,7 @@
 
 #if !defined(V8_TARGET_ARCH_IA32)
   // Target must be able to use caller's context.
-  CompilationInfo* outer_info = info();
+  CompilationInfo* outer_info = current_info();
   if (target->context() != outer_info->closure()->context() ||
       outer_info->scope()->contains_with() ||
       outer_info->scope()->num_heap_slots() > 0) {
@@ -7998,7 +7998,7 @@
 
   // Type-check the inlined function.
   ASSERT(target_shared->has_deoptimization_support());
-  AstTyper::Type(&target_info);
+  AstTyper::Run(&target_info);
 
   // Save the pending call context. Set up new one for the inlined function.
   // The function state is new-allocated because we need to delete it
@@ -8031,17 +8031,20 @@
 
   AddSimulate(return_id);
   current_block()->UpdateEnvironment(inner_env);
-  ZoneList<HValue*>* arguments_values = NULL;
+  HArgumentsObject* arguments_object = NULL;
 
-  // If the function uses arguments copy current arguments values
-  // to use them for materialization.
+  // If the function uses arguments object create and bind one, also copy
+  // current arguments values to use them for materialization.
   if (function->scope()->arguments() != NULL) {
+    ASSERT(function->scope()->arguments()->IsStackAllocated());
     HEnvironment* arguments_env = inner_env->arguments_environment();
     int arguments_count = arguments_env->parameter_count();
-    arguments_values = new(zone()) ZoneList<HValue*>(arguments_count, zone());
+    arguments_object = new(zone()) HArgumentsObject(arguments_count, zone());
+    inner_env->Bind(function->scope()->arguments(), arguments_object);
     for (int i = 0; i < arguments_count; i++) {
-      arguments_values->Add(arguments_env->Lookup(i), zone());
+      arguments_object->AddArgument(arguments_env->Lookup(i), zone());
     }
+    AddInstruction(arguments_object);
   }
 
   HEnterInlined* enter_inlined =
@@ -8050,20 +8053,12 @@
                                 function,
                                 function_state()->inlining_kind(),
                                 function->scope()->arguments(),
-                                arguments_values,
+                                arguments_object,
                                 undefined_receiver,
                                 zone());
   function_state()->set_entry(enter_inlined);
   AddInstruction(enter_inlined);
 
-  // If the function uses arguments object create and bind one.
-  if (function->scope()->arguments() != NULL) {
-    ASSERT(function->scope()->arguments()->IsStackAllocated());
-    inner_env->Bind(function->scope()->arguments(),
-                    graph()->GetArgumentsObject());
-  }
-
-
   VisitDeclarations(target_info.scope()->declarations());
   VisitStatements(function->body());
   if (HasStackOverflow()) {
@@ -8304,7 +8299,8 @@
             Call::GetPrototypeForPrimitiveCheck(STRING_CHECK,
                 expr->holder()->GetIsolate()),
             expr->holder(),
-            zone()));
+            zone(),
+            top_info()));
         HInstruction* char_code =
             BuildStringCharCodeAt(context, string, index);
         if (id == kStringCharCodeAt) {
@@ -8455,7 +8451,7 @@
     return false;
   }
 
-  if (info()->scope()->arguments() == NULL) return false;
+  if (current_info()->scope()->arguments() == NULL) return false;
 
   ZoneList<Expression*>* args = expr->arguments();
   if (args->length() != 2) return false;
@@ -8494,13 +8490,10 @@
   } else {
     // We are inside inlined function and we know exactly what is inside
     // arguments object. But we need to be able to materialize at deopt.
-    // TODO(mstarzinger): For now we just ensure arguments are pushed
-    // right after HEnterInlined, but we could be smarter about this.
-    EnsureArgumentsArePushedForAccess();
     ASSERT_EQ(environment()->arguments_environment()->parameter_count(),
-              function_state()->entry()->arguments_values()->length());
-    HEnterInlined* entry = function_state()->entry();
-    ZoneList<HValue*>* arguments_values = entry->arguments_values();
+              function_state()->entry()->arguments_object()->arguments_count());
+    HArgumentsObject* args = function_state()->entry()->arguments_object();
+    const ZoneList<HValue*>* arguments_values = args->arguments_values();
     int arguments_count = arguments_values->length();
     PushAndAdd(new(zone()) HWrapReceiver(receiver, function));
     for (int i = 1; i < arguments_count; i++) {
@@ -8696,8 +8689,8 @@
       LookupResult lookup(isolate());
       GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
       if (type == kUseCell &&
-          !info()->global_object()->IsAccessCheckNeeded()) {
-        Handle<GlobalObject> global(info()->global_object());
+          !current_info()->global_object()->IsAccessCheckNeeded()) {
+        Handle<GlobalObject> global(current_info()->global_object());
         known_global_function = expr->ComputeGlobalTarget(global, &lookup);
       }
       if (known_global_function) {
@@ -8732,7 +8725,7 @@
         }
         if (TryInlineCall(expr)) return;
 
-        if (expr->target().is_identical_to(info()->closure())) {
+        if (expr->target().is_identical_to(current_info()->closure())) {
           graph()->MarkRecursive();
         }
 
@@ -8935,7 +8928,7 @@
     CHECK_ALIVE(VisitArgumentList(expr->arguments()));
     HCallNew* call;
     if (use_call_new_array) {
-      Handle<JSGlobalPropertyCell> cell = expr->allocation_info_cell();
+      Handle<Cell> cell = expr->allocation_info_cell();
       call = new(zone()) HCallNewArray(context, constructor, argument_count,
                                        cell);
     } else {
@@ -9231,13 +9224,13 @@
         // Bail out if we try to mutate a parameter value in a function
         // using the arguments object.  We do not (yet) correctly handle the
         // arguments property of the function.
-        if (info()->scope()->arguments() != NULL) {
+        if (current_info()->scope()->arguments() != NULL) {
           // Parameters will rewrite to context slots.  We have no direct
           // way to detect that the variable is a parameter so we use a
           // linear search of the parameter list.
-          int count = info()->scope()->num_parameters();
+          int count = current_info()->scope()->num_parameters();
           for (int i = 0; i < count; ++i) {
-            if (var == info()->scope()->parameter(i)) {
+            if (var == current_info()->scope()->parameter(i)) {
               return Bailout("assignment to parameter in arguments object");
             }
           }
@@ -9688,6 +9681,7 @@
 }
 
 
+// TODO(rossberg): this should die eventually.
 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) {
   if (info.IsUninitialized()) return Representation::None();
   if (info.IsSmi()) return Representation::Integer32();
@@ -9698,6 +9692,14 @@
 }
 
 
+Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) {
+  if (type->Is(Type::None())) return Representation::None();
+  if (type->Is(Type::Integer32())) return Representation::Integer32();
+  if (type->Is(Type::Number())) return Representation::Double();
+  return Representation::Tagged();
+}
+
+
 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
                                                         HTypeof* typeof_expr,
                                                         Handle<String> check) {
@@ -9787,17 +9789,17 @@
     return ast_context()->ReturnControl(instr, expr->id());
   }
 
-  TypeInfo left_type = expr->left_type();
-  TypeInfo right_type = expr->right_type();
-  TypeInfo overall_type = expr->overall_type();
+  Handle<Type> left_type = expr->left_type();
+  Handle<Type> right_type = expr->right_type();
+  Handle<Type> overall_type = expr->overall_type();
   Representation combined_rep = ToRepresentation(overall_type);
   Representation left_rep = ToRepresentation(left_type);
   Representation right_rep = ToRepresentation(right_type);
   // Check if this expression was ever executed according to type feedback.
   // Note that for the special typeof/null/undefined cases we get unknown here.
-  if (overall_type.IsUninitialized()) {
+  if (overall_type->Is(Type::None())) {
     AddSoftDeoptimize();
-    overall_type = left_type = right_type = TypeInfo::Unknown();
+    overall_type = left_type = right_type = handle(Type::Any(), isolate());
   }
 
   CHECK_ALIVE(VisitForValue(expr->left()));
@@ -9836,10 +9838,10 @@
     VariableProxy* proxy = expr->right()->AsVariableProxy();
     bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
     if (global_function &&
-        info()->has_global_object() &&
-        !info()->global_object()->IsAccessCheckNeeded()) {
+        current_info()->has_global_object() &&
+        !current_info()->global_object()->IsAccessCheckNeeded()) {
       Handle<String> name = proxy->name();
-      Handle<GlobalObject> global(info()->global_object());
+      Handle<GlobalObject> global(current_info()->global_object());
       LookupResult lookup(isolate());
       global->Lookup(*name, &lookup);
       if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) {
@@ -9869,13 +9871,13 @@
     HIn* result = new(zone()) HIn(context, left, right);
     result->set_position(expr->position());
     return ast_context()->ReturnInstruction(result, expr->id());
-  } else if (overall_type.IsNonPrimitive()) {
+  } else if (overall_type->Is(Type::Receiver())) {
     switch (op) {
       case Token::EQ:
       case Token::EQ_STRICT: {
         // Can we get away with map check and not instance type check?
-        Handle<Map> map = expr->map();
-        if (!map.is_null()) {
+        if (overall_type->IsClass()) {
+          Handle<Map> map = overall_type->AsClass();
           AddCheckMapsWithTransitions(left, map);
           AddCheckMapsWithTransitions(right, map);
           HCompareObjectEqAndBranch* result =
@@ -9896,7 +9898,7 @@
       default:
         return Bailout("Unsupported non-primitive compare");
     }
-  } else if (overall_type.IsInternalizedString() &&
+  } else if (overall_type->Is(Type::InternalizedString()) &&
              Token::IsEqualityOp(op)) {
     BuildCheckNonSmi(left);
     AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
@@ -9931,8 +9933,8 @@
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
+  ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
   HIfContinuation continuation;
-  CompareNilICStub::Types types;
   if (expr->op() == Token::EQ_STRICT) {
     IfBuilder if_nil(this);
     if_nil.If<HCompareObjectEqAndBranch>(
@@ -9943,11 +9945,9 @@
     if_nil.CaptureContinuation(&continuation);
     return ast_context()->ReturnContinuation(&continuation, expr->id());
   }
-  types = CompareNilICStub::Types(expr->compare_nil_types());
-  if (types.IsEmpty()) types = CompareNilICStub::Types::FullCompare();
-  Handle<Map> map_handle = expr->map();
-  BuildCompareNil(value, types, map_handle,
-                  expr->position(), &continuation);
+  Handle<Type> type = expr->compare_nil_type()->Is(Type::None())
+      ? handle(Type::Any(), isolate_) : expr->compare_nil_type();
+  BuildCompareNil(value, type, expr->position(), &continuation);
   return ast_context()->ReturnContinuation(&continuation, expr->id());
 }
 
@@ -10282,9 +10282,9 @@
     Handle<FixedArray> array =
        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
-    int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
-                DeclareGlobalsNativeFlag::encode(info()->is_native()) |
-                DeclareGlobalsLanguageMode::encode(info()->language_mode());
+    int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
+        DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
+        DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
     HInstruction* result = new(zone()) HDeclareGlobals(
         environment()->LookupContext(), array, flags);
     AddInstruction(result);
@@ -10338,8 +10338,8 @@
   switch (variable->location()) {
     case Variable::UNALLOCATED: {
       globals_.Add(variable->name(), zone());
-      Handle<SharedFunctionInfo> function =
-          Compiler::BuildFunctionInfo(declaration->fun(), info()->script());
+      Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo(
+          declaration->fun(), current_info()->script());
       // Check for stack-overflow exception.
       if (function.is_null()) return SetStackOverflow();
       globals_.Add(function, zone());
@@ -11005,6 +11005,7 @@
       values_(arguments, zone),
       frame_type_(frame_type),
       parameter_count_(arguments),
+      specials_count_(0),
       local_count_(0),
       outer_(outer),
       entry_(NULL),
diff --git a/src/hydrogen.h b/src/hydrogen.h
index ad89e50..3680775 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -260,6 +260,7 @@
   HStackCheck* stack_check_;
 };
 
+
 class BoundsCheckTable;
 class HGraph: public ZoneObject {
  public:
@@ -402,6 +403,12 @@
   }
 
   void MarkDependsOnEmptyArrayProtoElements() {
+    // Add map dependency if not already added.
+    if (depends_on_empty_array_proto_elements_) return;
+    isolate()->initial_object_prototype()->map()->AddDependentCompilationInfo(
+        DependentCode::kElementsCantBeAddedGroup, info());
+    isolate()->initial_array_prototype()->map()->AddDependentCompilationInfo(
+        DependentCode::kElementsCantBeAddedGroup, info());
     depends_on_empty_array_proto_elements_ = true;
   }
 
@@ -874,6 +881,11 @@
   HEnterInlined* entry() { return entry_; }
   void set_entry(HEnterInlined* entry) { entry_ = entry; }
 
+  HArgumentsObject* arguments_object() { return arguments_object_; }
+  void set_arguments_object(HArgumentsObject* arguments_object) {
+    arguments_object_ = arguments_object;
+  }
+
   HArgumentsElements* arguments_elements() { return arguments_elements_; }
   void set_arguments_elements(HArgumentsElements* arguments_elements) {
     arguments_elements_ = arguments_elements;
@@ -907,6 +919,7 @@
   // entry.
   HEnterInlined* entry_;
 
+  HArgumentsObject* arguments_object_;
   HArgumentsElements* arguments_elements_;
 
   FunctionState* outer_;
@@ -968,6 +981,7 @@
   Zone* zone() const { return info_->zone(); }
   HGraph* graph() const { return graph_; }
   Isolate* isolate() const { return graph_->isolate(); }
+  CompilationInfo* top_info() { return info_; }
 
   HGraph* CreateGraph();
 
@@ -1350,8 +1364,7 @@
 
   void BuildCompareNil(
       HValue* value,
-      CompareNilICStub::Types types,
-      Handle<Map> map,
+      Handle<Type> type,
       int position,
       HIfContinuation* continuation);
 
@@ -1488,7 +1501,7 @@
   void set_ast_context(AstContext* context) { ast_context_ = context; }
 
   // Accessors forwarded to the function state.
-  CompilationInfo* info() const {
+  CompilationInfo* current_info() const {
     return function_state()->compilation_info();
   }
   AstContext* call_context() const {
@@ -1622,6 +1635,7 @@
   template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
 
   static Representation ToRepresentation(TypeInfo info);
+  static Representation ToRepresentation(Handle<Type> type);
 
   void SetUpScope(Scope* scope);
   virtual void VisitStatements(ZoneList<Statement*>* statements);
diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h
index 2a0c920..0c737ac 100644
--- a/src/ia32/assembler-ia32-inl.h
+++ b/src/ia32/assembler-ia32-inl.h
@@ -162,24 +162,22 @@
 }
 
 
-Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
-  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+Handle<Cell> RelocInfo::target_cell_handle() {
+  ASSERT(rmode_ == RelocInfo::CELL);
   Address address = Memory::Address_at(pc_);
-  return Handle<JSGlobalPropertyCell>(
-      reinterpret_cast<JSGlobalPropertyCell**>(address));
+  return Handle<Cell>(reinterpret_cast<Cell**>(address));
 }
 
 
-JSGlobalPropertyCell* RelocInfo::target_cell() {
-  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
-  return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
+Cell* RelocInfo::target_cell() {
+  ASSERT(rmode_ == RelocInfo::CELL);
+  return Cell::FromValueAddress(Memory::Address_at(pc_));
 }
 
 
-void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
-                                WriteBarrierMode mode) {
-  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
-  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
+void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
+  ASSERT(rmode_ == RelocInfo::CELL);
+  Address address = cell->address() + Cell::kValueOffset;
   Memory::Address_at(pc_) = address;
   CPU::FlushICache(pc_, sizeof(Address));
   if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
@@ -259,8 +257,8 @@
     CPU::FlushICache(pc_, sizeof(Address));
   } else if (RelocInfo::IsCodeTarget(mode)) {
     visitor->VisitCodeTarget(this);
-  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
-    visitor->VisitGlobalPropertyCell(this);
+  } else if (mode == RelocInfo::CELL) {
+    visitor->VisitCell(this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     visitor->VisitExternalReference(this);
     CPU::FlushICache(pc_, sizeof(Address));
@@ -289,8 +287,8 @@
     CPU::FlushICache(pc_, sizeof(Address));
   } else if (RelocInfo::IsCodeTarget(mode)) {
     StaticVisitor::VisitCodeTarget(heap, this);
-  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
-    StaticVisitor::VisitGlobalPropertyCell(heap, this);
+  } else if (mode == RelocInfo::CELL) {
+    StaticVisitor::VisitCell(heap, this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     StaticVisitor::VisitExternalReference(this);
     CPU::FlushICache(pc_, sizeof(Address));
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 5d11452..353f265 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -410,10 +410,10 @@
                    RelocInfo::EXTERNAL_REFERENCE);
   }
 
-  static Operand Cell(Handle<JSGlobalPropertyCell> cell) {
+  static Operand ForCell(Handle<Cell> cell) {
     AllowDeferredHandleDereference embedding_raw_address;
     return Operand(reinterpret_cast<int32_t>(cell.location()),
-                   RelocInfo::GLOBAL_PROPERTY_CELL);
+                   RelocInfo::CELL);
   }
 
   // Returns true if this Operand is a wrapper for the specified register.
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index ad1c65d..aa4b8a2 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -4703,13 +4703,13 @@
   __ j(equal, &initialize, Label::kNear);
   // MegamorphicSentinel is an immortal immovable object (undefined) so no
   // write-barrier is needed.
-  __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+  __ mov(FieldOperand(ebx, Cell::kValueOffset),
          Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
   __ jmp(&done, Label::kNear);
 
   // An uninitialized cache is patched with the function.
   __ bind(&initialize);
-  __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi);
+  __ mov(FieldOperand(ebx, Cell::kValueOffset), edi);
   // No need for a write barrier here - cells are rescanned.
 
   __ bind(&done);
@@ -4727,7 +4727,7 @@
   Label initialize, done, miss, megamorphic, not_array_function;
 
   // Load the cache state into ecx.
-  __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
+  __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset));
 
   // A monomorphic cache hit or an already megamorphic state: invoke the
   // function without changing the state.
@@ -4762,7 +4762,7 @@
   // MegamorphicSentinel is an immortal immovable object (undefined) so no
   // write-barrier is needed.
   __ bind(&megamorphic);
-  __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+  __ mov(FieldOperand(ebx, Cell::kValueOffset),
          Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
   __ jmp(&done, Label::kNear);
 
@@ -4781,12 +4781,12 @@
   Handle<Object> initial_kind_sentinel =
       TypeFeedbackCells::MonomorphicArraySentinel(isolate,
           GetInitialFastElementsKind());
-  __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+  __ mov(FieldOperand(ebx, Cell::kValueOffset),
          Immediate(initial_kind_sentinel));
   __ jmp(&done);
 
   __ bind(&not_array_function);
-  __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi);
+  __ mov(FieldOperand(ebx, Cell::kValueOffset), edi);
   // No need for a write barrier here - cells are rescanned.
 
   __ bind(&done);
@@ -4857,7 +4857,7 @@
     // If there is a call target cache, mark it megamorphic in the
     // non-function case.  MegamorphicSentinel is an immortal immovable
     // object (undefined) so no write barrier is needed.
-    __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+    __ mov(FieldOperand(ebx, Cell::kValueOffset),
            Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
   }
   // Check for function proxy.
@@ -7930,13 +7930,12 @@
     __ CmpObjectType(ecx, MAP_TYPE, ecx);
     __ Assert(equal, "Unexpected initial map for Array function");
 
-    // We should either have undefined in ebx or a valid jsglobalpropertycell
+    // We should either have undefined in ebx or a valid cell
     Label okay_here;
-    Handle<Map> global_property_cell_map(
-        masm->isolate()->heap()->global_property_cell_map());
+    Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
     __ cmp(ebx, Immediate(undefined_sentinel));
     __ j(equal, &okay_here);
-    __ cmp(FieldOperand(ebx, 0), Immediate(global_property_cell_map));
+    __ cmp(FieldOperand(ebx, 0), Immediate(cell_map));
     __ Assert(equal, "Expected property cell in register ebx");
     __ bind(&okay_here);
   }
@@ -7946,7 +7945,7 @@
     // Get the elements kind and case on that.
     __ cmp(ebx, Immediate(undefined_sentinel));
     __ j(equal, &no_info);
-    __ mov(edx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
+    __ mov(edx, FieldOperand(ebx, Cell::kValueOffset));
     __ JumpIfNotSmi(edx, &no_info);
     __ SmiUntag(edx);
     __ jmp(&switch_ready);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index c77faaa..8b01a8b 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -118,7 +118,7 @@
   CompilationInfo* info = info_;
   handler_table_ =
       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
-  profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
+  profiling_counter_ = isolate()->factory()->NewCell(
       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
   SetFunctionPosition(function());
   Comment cmnt(masm_, "[ function compiled by full code generator");
@@ -315,7 +315,7 @@
 
 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
   __ mov(ebx, Immediate(profiling_counter_));
-  __ sub(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+  __ sub(FieldOperand(ebx, Cell::kValueOffset),
          Immediate(Smi::FromInt(delta)));
 }
 
@@ -327,7 +327,7 @@
     reset_value = Smi::kMaxValue;
   }
   __ mov(ebx, Immediate(profiling_counter_));
-  __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+  __ mov(FieldOperand(ebx, Cell::kValueOffset),
          Immediate(Smi::FromInt(reset_value)));
 }
 
@@ -1105,14 +1105,12 @@
   Label non_proxy;
   __ bind(&fixed_array);
 
-  Handle<JSGlobalPropertyCell> cell =
-      isolate()->factory()->NewJSGlobalPropertyCell(
-          Handle<Object>(
-              Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
-              isolate()));
+  Handle<Cell> cell = isolate()->factory()->NewCell(
+      Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
+                     isolate()));
   RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
   __ LoadHeapObject(ebx, cell);
-  __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+  __ mov(FieldOperand(ebx, Cell::kValueOffset),
          Immediate(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
 
   __ mov(ebx, Immediate(Smi::FromInt(1)));  // Smi indicates slow check
@@ -1950,8 +1948,12 @@
   VisitForStackValue(expr->expression());
 
   switch (expr->yield_kind()) {
-    case Yield::INITIAL:
-    case Yield::SUSPEND: {
+    case Yield::SUSPEND:
+      // Pop value from top-of-stack slot; box result into result register.
+      EmitCreateIteratorResult(false);
+      __ push(result_register());
+      // Fall through.
+    case Yield::INITIAL: {
       VisitForStackValue(expr->generator_object());
       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
       __ mov(context_register(),
@@ -1960,12 +1962,8 @@
       Label resume;
       __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
       __ j(not_equal, &resume);
-      if (expr->yield_kind() == Yield::SUSPEND) {
-        EmitReturnIteratorResult(false);
-      } else {
-        __ pop(result_register());
-        EmitReturnSequence();
-      }
+      __ pop(result_register());
+      EmitReturnSequence();
 
       __ bind(&resume);
       context()->Plug(result_register());
@@ -1977,7 +1975,10 @@
       __ mov(FieldOperand(result_register(),
                           JSGeneratorObject::kContinuationOffset),
              Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
-      EmitReturnIteratorResult(true);
+      // Pop value from top-of-stack slot, box result into result register.
+      EmitCreateIteratorResult(true);
+      EmitUnwindBeforeReturn();
+      EmitReturnSequence();
       break;
     }
 
@@ -2006,17 +2007,18 @@
 
       // try { received = yield result.value }
       __ bind(&l_try);
-      __ pop(eax);                                       // result.value
+      EmitCreateIteratorResult(false);                    // pop and box to eax
       __ PushTryHandler(StackHandler::CATCH, expr->index());
       const int handler_size = StackHandlerConstants::kSize;
-      __ push(eax);                                      // result.value
+      __ push(eax);                                      // result
       __ push(Operand(esp, (0 + 1) * kPointerSize + handler_size));  // g
       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
       __ mov(context_register(),
              Operand(ebp, StandardFrameConstants::kContextOffset));
       __ CompareRoot(eax, Heap::kTheHoleValueRootIndex);
       __ j(not_equal, &l_resume);
-      EmitReturnIteratorResult(false);
+      __ pop(eax);                                       // result
+      EmitReturnSequence();
       __ bind(&l_resume);                                // received in eax
       __ PopTryHandler();
 
@@ -2169,13 +2171,20 @@
 }
 
 
-void FullCodeGenerator::EmitReturnIteratorResult(bool done) {
+void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label gc_required;
   Label allocated;
 
   Handle<Map> map(isolate()->native_context()->generator_result_map());
 
   __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT);
+  __ jmp(&allocated);
+
+  __ bind(&gc_required);
+  __ Push(Smi::FromInt(map->instance_size()));
+  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+  __ mov(context_register(),
+         Operand(ebp, StandardFrameConstants::kContextOffset));
 
   __ bind(&allocated);
   __ mov(ebx, map);
@@ -2194,26 +2203,6 @@
   // root set.
   __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset,
                       ecx, edx, kDontSaveFPRegs);
-
-  if (done) {
-    // Exit all nested statements.
-    NestedStatement* current = nesting_stack_;
-    int stack_depth = 0;
-    int context_length = 0;
-    while (current != NULL) {
-      current = current->Exit(&stack_depth, &context_length);
-    }
-    __ Drop(stack_depth);
-  }
-
-  EmitReturnSequence();
-
-  __ bind(&gc_required);
-  __ Push(Smi::FromInt(map->instance_size()));
-  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ mov(context_register(),
-         Operand(ebp, StandardFrameConstants::kContextOffset));
-  __ jmp(&allocated);
 }
 
 
@@ -2637,8 +2626,7 @@
   flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
   Handle<Object> uninitialized =
       TypeFeedbackCells::UninitializedSentinel(isolate());
-  Handle<JSGlobalPropertyCell> cell =
-      isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+  Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
   RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
   __ mov(ebx, cell);
 
@@ -2822,8 +2810,7 @@
   // Record call targets in unoptimized code.
   Handle<Object> uninitialized =
       TypeFeedbackCells::UninitializedSentinel(isolate());
-  Handle<JSGlobalPropertyCell> cell =
-      isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+  Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
   RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
   __ mov(ebx, cell);
 
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 7d685bf..cfda00a 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -109,20 +109,7 @@
   if (!info()->IsStub()) {
     Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
   }
-  for (int i = 0 ; i < prototype_maps_.length(); i++) {
-    prototype_maps_.at(i)->AddDependentCode(
-        DependentCode::kPrototypeCheckGroup, code);
-  }
-  for (int i = 0 ; i < transition_maps_.length(); i++) {
-    transition_maps_.at(i)->AddDependentCode(
-        DependentCode::kTransitionGroup, code);
-  }
-  if (graph()->depends_on_empty_array_proto_elements()) {
-    isolate()->initial_object_prototype()->map()->AddDependentCode(
-        DependentCode::kElementsCantBeAddedGroup, code);
-    isolate()->initial_array_prototype()->map()->AddDependentCode(
-        DependentCode::kElementsCantBeAddedGroup, code);
-  }
+  info()->CommitDependentMaps(code);
 }
 
 
@@ -627,27 +614,15 @@
 
 
 void LCodeGen::WriteTranslation(LEnvironment* environment,
-                                Translation* translation,
-                                int* pushed_arguments_index,
-                                int* pushed_arguments_count) {
+                                Translation* translation) {
   if (environment == NULL) return;
 
   // The translation includes one command per value in the environment.
-  int translation_size = environment->values()->length();
+  int translation_size = environment->translation_size();
   // The output frame height does not include the parameters.
   int height = translation_size - environment->parameter_count();
 
-  // Function parameters are arguments to the outermost environment. The
-  // arguments index points to the first element of a sequence of tagged
-  // values on the stack that represent the arguments. This needs to be
-  // kept in sync with the LArgumentsElements implementation.
-  *pushed_arguments_index = -environment->parameter_count();
-  *pushed_arguments_count = environment->parameter_count();
-
-  WriteTranslation(environment->outer(),
-                   translation,
-                   pushed_arguments_index,
-                   pushed_arguments_count);
+  WriteTranslation(environment->outer(), translation);
   bool has_closure_id = !info()->closure().is_null() &&
       !info()->closure().is_identical_to(environment->closure());
   int closure_id = has_closure_id
@@ -680,23 +655,6 @@
       UNREACHABLE();
   }
 
-  // Inlined frames which push their arguments cause the index to be
-  // bumped and another stack area to be used for materialization,
-  // otherwise actual argument values are unknown for inlined frames.
-  bool arguments_known = true;
-  int arguments_index = *pushed_arguments_index;
-  int arguments_count = *pushed_arguments_count;
-  if (environment->entry() != NULL) {
-    arguments_known = environment->entry()->arguments_pushed();
-    arguments_index = arguments_index < 0
-        ? GetStackSlotCount() : arguments_index + arguments_count;
-    arguments_count = environment->entry()->arguments_count() + 1;
-    if (environment->entry()->arguments_pushed()) {
-      *pushed_arguments_index = arguments_index;
-      *pushed_arguments_count = arguments_count;
-    }
-  }
-
   for (int i = 0; i < translation_size; ++i) {
     LOperand* value = environment->values()->at(i);
     // spilled_registers_ and spilled_double_registers_ are either
@@ -708,10 +666,7 @@
         AddToTranslation(translation,
                          environment->spilled_registers()[value->index()],
                          environment->HasTaggedValueAt(i),
-                         environment->HasUint32ValueAt(i),
-                         arguments_known,
-                         arguments_index,
-                         arguments_count);
+                         environment->HasUint32ValueAt(i));
       } else if (
           value->IsDoubleRegister() &&
           environment->spilled_double_registers()[value->index()] != NULL) {
@@ -720,20 +675,36 @@
             translation,
             environment->spilled_double_registers()[value->index()],
             false,
-            false,
-            arguments_known,
-            arguments_index,
-            arguments_count);
+            false);
       }
     }
 
+    // TODO(mstarzinger): Introduce marker operands to indicate that this value
+    // is not present and must be reconstructed from the deoptimizer. Currently
+    // this is only used for the arguments object.
+    if (value == NULL) {
+      int arguments_count = environment->values()->length() - translation_size;
+      translation->BeginArgumentsObject(arguments_count);
+      for (int i = 0; i < arguments_count; ++i) {
+        LOperand* value = environment->values()->at(translation_size + i);
+        ASSERT(environment->spilled_registers() == NULL ||
+               !value->IsRegister() ||
+               environment->spilled_registers()[value->index()] == NULL);
+        ASSERT(environment->spilled_registers() == NULL ||
+               !value->IsDoubleRegister() ||
+               environment->spilled_double_registers()[value->index()] == NULL);
+        AddToTranslation(translation,
+                         value,
+                         environment->HasTaggedValueAt(translation_size + i),
+                         environment->HasUint32ValueAt(translation_size + i));
+      }
+      continue;
+    }
+
     AddToTranslation(translation,
                      value,
                      environment->HasTaggedValueAt(i),
-                     environment->HasUint32ValueAt(i),
-                     arguments_known,
-                     arguments_index,
-                     arguments_count);
+                     environment->HasUint32ValueAt(i));
   }
 }
 
@@ -741,17 +712,8 @@
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged,
-                                bool is_uint32,
-                                bool arguments_known,
-                                int arguments_index,
-                                int arguments_count) {
-  if (op == NULL) {
-    // TODO(twuerthinger): Introduce marker operands to indicate that this value
-    // is not present and must be reconstructed from the deoptimizer. Currently
-    // this is only used for the arguments object.
-    translation->StoreArgumentsObject(
-        arguments_known, arguments_index, arguments_count);
-  } else if (op->IsStackSlot()) {
+                                bool is_uint32) {
+  if (op->IsStackSlot()) {
     if (is_tagged) {
       translation->StoreStackSlot(op->index());
     } else if (is_uint32) {
@@ -877,8 +839,6 @@
 
     int frame_count = 0;
     int jsframe_count = 0;
-    int args_index = 0;
-    int args_count = 0;
     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
       ++frame_count;
       if (e->frame_type() == JS_FUNCTION) {
@@ -886,7 +846,7 @@
       }
     }
     Translation translation(&translations_, frame_count, jsframe_count, zone());
-    WriteTranslation(environment, &translation, &args_index, &args_count);
+    WriteTranslation(environment, &translation);
     int deoptimization_index = deoptimizations_.length();
     int pc_offset = masm()->pc_offset();
     environment->Register(deoptimization_index,
@@ -2719,9 +2679,8 @@
   Register map = ToRegister(instr->temp());
   __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
   __ bind(deferred->map_check());  // Label for calculating code patching.
-  Handle<JSGlobalPropertyCell> cache_cell =
-      factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
-  __ cmp(map, Operand::Cell(cache_cell));  // Patched to cached map.
+  Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
+  __ cmp(map, Operand::ForCell(cache_cell));  // Patched to cached map.
   __ j(not_equal, &cache_miss, Label::kNear);
   __ mov(eax, factory()->the_hole_value());  // Patched to either true or false.
   __ jmp(&done);
@@ -2903,7 +2862,7 @@
 
 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
   Register result = ToRegister(instr->result());
-  __ mov(result, Operand::Cell(instr->hydrogen()->cell()));
+  __ mov(result, Operand::ForCell(instr->hydrogen()->cell()));
   if (instr->hydrogen()->RequiresHoleCheck()) {
     __ cmp(result, factory()->the_hole_value());
     DeoptimizeIf(equal, instr->environment());
@@ -2933,12 +2892,12 @@
   // to update the property details in the property dictionary to mark
   // it as no longer deleted. We deoptimize in that case.
   if (instr->hydrogen()->RequiresHoleCheck()) {
-    __ cmp(Operand::Cell(cell_handle), factory()->the_hole_value());
+    __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
     DeoptimizeIf(equal, instr->environment());
   }
 
   // Store the value.
-  __ mov(Operand::Cell(cell_handle), value);
+  __ mov(Operand::ForCell(cell_handle), value);
   // Cells are always rescanned, so no write barrier here.
 }
 
@@ -4266,8 +4225,26 @@
     ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
     CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
   } else if (instr->arity() == 1) {
+    Label done;
+    if (IsFastPackedElementsKind(kind)) {
+      Label packed_case;
+      // We might need a change here
+      // look at the first argument
+      __ mov(ecx, Operand(esp, 0));
+      __ test(ecx, ecx);
+      __ j(zero, &packed_case);
+
+      ElementsKind holey_kind = GetHoleyElementsKind(kind);
+      ArraySingleArgumentConstructorStub stub(holey_kind,
+                                              disable_allocation_sites);
+      CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+      __ jmp(&done);
+      __ bind(&packed_case);
+    }
+
     ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites);
     CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+    __ bind(&done);
   } else {
     ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites);
     CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
@@ -4331,9 +4308,6 @@
   }
 
   if (!transition.is_null()) {
-    if (transition->CanBeDeprecated()) {
-      transition_maps_.Add(transition, info()->zone());
-    }
     if (!instr->hydrogen()->NeedsWriteBarrierForMap()) {
       __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
     } else {
@@ -5790,9 +5764,8 @@
   Handle<JSFunction> target = instr->hydrogen()->target();
   if (instr->hydrogen()->target_in_new_space()) {
     Register reg = ToRegister(instr->value());
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(target);
-    __ cmp(reg, Operand::Cell(cell));
+    Handle<Cell> cell = isolate()->factory()->NewCell(target);
+    __ cmp(reg, Operand::ForCell(cell));
   } else {
     Operand operand = ToOperand(instr->value());
     __ cmp(operand, target);
@@ -6009,11 +5982,7 @@
 
   ASSERT(prototypes->length() == maps->length());
 
-  if (instr->hydrogen()->CanOmitPrototypeChecks()) {
-    for (int i = 0; i < maps->length(); i++) {
-      prototype_maps_.Add(maps->at(i), info()->zone());
-    }
-  } else {
+  if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
     for (int i = 0; i < prototypes->length(); i++) {
       __ LoadHeapObject(reg, prototypes->at(i));
       DoCheckMapCommon(reg, maps->at(i), instr);
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index 647dd0e..21f6076 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -58,8 +58,6 @@
         deoptimizations_(4, info->zone()),
         jump_table_(4, info->zone()),
         deoptimization_literals_(8, info->zone()),
-        prototype_maps_(0, info->zone()),
-        transition_maps_(0, info->zone()),
         inlined_function_count_(0),
         scope_(info->scope()),
         status_(UNUSED),
@@ -170,10 +168,7 @@
   void DoGap(LGap* instr);
 
   // Emit frame translation commands for an environment.
-  void WriteTranslation(LEnvironment* environment,
-                        Translation* translation,
-                        int* arguments_index,
-                        int* arguments_count);
+  void WriteTranslation(LEnvironment* environment, Translation* translation);
 
   void EnsureRelocSpaceForDeoptimization();
 
@@ -287,10 +282,7 @@
   void AddToTranslation(Translation* translation,
                         LOperand* op,
                         bool is_tagged,
-                        bool is_uint32,
-                        bool arguments_known,
-                        int arguments_index,
-                        int arguments_count);
+                        bool is_uint32);
   void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -409,8 +401,6 @@
   ZoneList<LEnvironment*> deoptimizations_;
   ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
   ZoneList<Handle<Object> > deoptimization_literals_;
-  ZoneList<Handle<Map> > prototype_maps_;
-  ZoneList<Handle<Map> > transition_maps_;
   int inlined_function_count_;
   Scope* const scope_;
   Status status_;
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 325ed2c..216872d 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -990,7 +990,7 @@
   BailoutId ast_id = hydrogen_env->ast_id();
   ASSERT(!ast_id.IsNone() ||
          hydrogen_env->frame_type() != JS_FUNCTION);
-  int value_count = hydrogen_env->length();
+  int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
   LEnvironment* result =
       new(zone()) LEnvironment(hydrogen_env->closure(),
                                hydrogen_env->frame_type(),
@@ -1001,13 +1001,15 @@
                                outer,
                                hydrogen_env->entry(),
                                zone());
+  bool needs_arguments_object_materialization = false;
   int argument_index = *argument_index_accumulator;
-  for (int i = 0; i < value_count; ++i) {
+  for (int i = 0; i < hydrogen_env->length(); ++i) {
     if (hydrogen_env->is_special_index(i)) continue;
 
     HValue* value = hydrogen_env->values()->at(i);
     LOperand* op = NULL;
     if (value->IsArgumentsObject()) {
+      needs_arguments_object_materialization = true;
       op = NULL;
     } else if (value->IsPushArgument()) {
       op = new(zone()) LArgument(argument_index++);
@@ -1019,6 +1021,22 @@
                      value->CheckFlag(HInstruction::kUint32));
   }
 
+  if (needs_arguments_object_materialization) {
+    HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+        ? graph()->GetArgumentsObject()
+        : hydrogen_env->entry()->arguments_object();
+    ASSERT(arguments->IsLinked());
+    for (int i = 1; i < arguments->arguments_count(); ++i) {
+      HValue* value = arguments->arguments_values()->at(i);
+      ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+      ASSERT(HInstruction::cast(value)->IsLinked());
+      LOperand* op = UseAny(value);
+      result->AddValue(op,
+                       value->representation(),
+                       value->CheckFlag(HInstruction::kUint32));
+    }
+  }
+
   if (hydrogen_env->frame_type() == JS_FUNCTION) {
     *argument_index_accumulator = argument_index;
   }
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 38b02a5..60c5c26 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -2495,9 +2495,8 @@
                                     Handle<HeapObject> object) {
   AllowDeferredHandleDereference embedding_raw_address;
   if (isolate()->heap()->InNewSpace(*object)) {
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(object);
-    mov(result, Operand::Cell(cell));
+    Handle<Cell> cell = isolate()->factory()->NewCell(object);
+    mov(result, Operand::ForCell(cell));
   } else {
     mov(result, object);
   }
@@ -2507,9 +2506,8 @@
 void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
   AllowDeferredHandleDereference using_raw_address;
   if (isolate()->heap()->InNewSpace(*object)) {
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(object);
-    cmp(reg, Operand::Cell(cell));
+    Handle<Cell> cell = isolate()->factory()->NewCell(object);
+    cmp(reg, Operand::ForCell(cell));
   } else {
     cmp(reg, object);
   }
@@ -2519,9 +2517,8 @@
 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
   AllowDeferredHandleDereference using_raw_address;
   if (isolate()->heap()->InNewSpace(*object)) {
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(object);
-    push(Operand::Cell(cell));
+    Handle<Cell> cell = isolate()->factory()->NewCell(object);
+    push(Operand::ForCell(cell));
   } else {
     Push(object);
   }
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 3906623..93923a7 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -762,7 +762,7 @@
     __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
            Immediate(the_hole));
   } else {
-    __ cmp(Operand::Cell(cell), Immediate(the_hole));
+    __ cmp(Operand::ForCell(cell), Immediate(the_hole));
   }
   __ j(not_equal, miss);
 }
@@ -1565,15 +1565,15 @@
 
 
 void CallStubCompiler::GenerateLoadFunctionFromCell(
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Label* miss) {
   // Get the value from the cell.
   if (Serializer::enabled()) {
     __ mov(edi, Immediate(cell));
-    __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
+    __ mov(edi, FieldOperand(edi, Cell::kValueOffset));
   } else {
-    __ mov(edi, Operand::Cell(cell));
+    __ mov(edi, Operand::ForCell(cell));
   }
 
   // Check that the cell contains the same function.
@@ -1667,7 +1667,7 @@
 Handle<Code> CallStubCompiler::CompileArrayPushCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -1925,7 +1925,7 @@
 Handle<Code> CallStubCompiler::CompileArrayPopCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2007,7 +2007,7 @@
 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2091,7 +2091,7 @@
 Handle<Code> CallStubCompiler::CompileStringCharAtCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2177,7 +2177,7 @@
 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2253,7 +2253,7 @@
 Handle<Code> CallStubCompiler::CompileMathFloorCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2384,7 +2384,7 @@
 Handle<Code> CallStubCompiler::CompileMathAbsCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2491,7 +2491,7 @@
     const CallOptimization& optimization,
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   ASSERT(optimization.is_simple_api_call());
@@ -2673,7 +2673,7 @@
 
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(object, holder,
-                                          Handle<JSGlobalPropertyCell>::null(),
+                                          Handle<Cell>::null(),
                                           function, Handle<String>::cast(name));
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
@@ -3121,7 +3121,7 @@
     __ mov(eax, Immediate(cell));
     __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset));
   } else {
-    __ mov(eax, Operand::Cell(cell));
+    __ mov(eax, Operand::ForCell(cell));
   }
 
   // Check for deleted property if property can actually be deleted.
diff --git a/src/ic.cc b/src/ic.cc
index 94e8773..095b614 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -2420,8 +2420,8 @@
 }
 
 UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) {
-  ::v8::internal::TypeInfo operand_type =
-      ::v8::internal::TypeInfo::TypeFromValue(operand);
+  v8::internal::TypeInfo operand_type =
+      v8::internal::TypeInfo::FromValue(operand);
   if (operand_type.IsSmi()) {
     return SMI;
   } else if (operand_type.IsNumber()) {
@@ -2545,8 +2545,7 @@
 
 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
                                               Token::Value op) {
-  ::v8::internal::TypeInfo type =
-      ::v8::internal::TypeInfo::TypeFromValue(value);
+  v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value);
   if (type.IsSmi()) return BinaryOpIC::SMI;
   if (type.IsInteger32()) {
     if (kSmiValueSize == 32) return BinaryOpIC::SMI;
@@ -2767,10 +2766,39 @@
     case OBJECT: return "OBJECT";
     case KNOWN_OBJECT: return "KNOWN_OBJECT";
     case GENERIC: return "GENERIC";
-    default:
-      UNREACHABLE();
-      return NULL;
   }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+Handle<Type> CompareIC::StateToType(
+    Isolate* isolate,
+    CompareIC::State state,
+    Handle<Map> map) {
+  switch (state) {
+    case CompareIC::UNINITIALIZED:
+      return handle(Type::None(), isolate);
+    case CompareIC::SMI:
+      return handle(Type::Integer31(), isolate);
+    case CompareIC::NUMBER:
+      return handle(Type::Number(), isolate);
+    case CompareIC::STRING:
+      return handle(Type::String(), isolate);
+    case CompareIC::INTERNALIZED_STRING:
+      return handle(Type::InternalizedString(), isolate);
+    case CompareIC::UNIQUE_NAME:
+      return handle(Type::UniqueName(), isolate);
+    case CompareIC::OBJECT:
+      return handle(Type::Receiver(), isolate);
+    case CompareIC::KNOWN_OBJECT:
+      return handle(
+          map.is_null() ? Type::Receiver() : Type::Class(map), isolate);
+    case CompareIC::GENERIC:
+      return handle(Type::Any(), isolate);
+  }
+  UNREACHABLE();
+  return Handle<Type>();
 }
 
 
@@ -2934,7 +2962,7 @@
   Code::ExtraICState state = target->extended_extra_ic_state();
 
   CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
-  stub.ClearTypes();
+  stub.ClearState();
 
   Code* code = NULL;
   CHECK(stub.FindCodeInCache(&code, target->GetIsolate()));
@@ -2961,9 +2989,9 @@
   // types must be supported as a result of the miss.
   bool already_monomorphic = stub.IsMonomorphic();
 
-  CompareNilICStub::Types old_types = stub.GetTypes();
+  CompareNilICStub::State old_state = stub.GetState();
   stub.Record(object);
-  old_types.TraceTransition(stub.GetTypes());
+  old_state.TraceTransition(stub.GetState());
 
   NilValue nil = stub.GetNilValue();
 
diff --git a/src/ic.h b/src/ic.h
index 8c448eb..fc869ad 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -741,6 +741,9 @@
     GENERIC
   };
 
+  static Handle<Type> StateToType(
+      Isolate* isolate, State state, Handle<Map> map = Handle<Map>());
+
   CompareIC(Isolate* isolate, Token::Value op)
       : IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
 
diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc
index e19d6e2..80dc8ea 100644
--- a/src/incremental-marking.cc
+++ b/src/incremental-marking.cc
@@ -394,6 +394,7 @@
       chunk->SetFlag(MemoryChunk::RESCAN_ON_EVACUATION);
     }
   } else if (chunk->owner()->identity() == CELL_SPACE ||
+             chunk->owner()->identity() == PROPERTY_CELL_SPACE ||
              chunk->scan_on_scavenge()) {
     chunk->ClearFlag(MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING);
     chunk->ClearFlag(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING);
@@ -440,6 +441,7 @@
   DeactivateIncrementalWriteBarrierForSpace(heap_->old_pointer_space());
   DeactivateIncrementalWriteBarrierForSpace(heap_->old_data_space());
   DeactivateIncrementalWriteBarrierForSpace(heap_->cell_space());
+  DeactivateIncrementalWriteBarrierForSpace(heap_->property_cell_space());
   DeactivateIncrementalWriteBarrierForSpace(heap_->map_space());
   DeactivateIncrementalWriteBarrierForSpace(heap_->code_space());
   DeactivateIncrementalWriteBarrierForSpace(heap_->new_space());
@@ -474,6 +476,7 @@
   ActivateIncrementalWriteBarrier(heap_->old_pointer_space());
   ActivateIncrementalWriteBarrier(heap_->old_data_space());
   ActivateIncrementalWriteBarrier(heap_->cell_space());
+  ActivateIncrementalWriteBarrier(heap_->property_cell_space());
   ActivateIncrementalWriteBarrier(heap_->map_space());
   ActivateIncrementalWriteBarrier(heap_->code_space());
   ActivateIncrementalWriteBarrier(heap_->new_space());
diff --git a/src/isolate.cc b/src/isolate.cc
index 7cce14a..6c797b2 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -2007,6 +2007,9 @@
   delete external_reference_table_;
   external_reference_table_ = NULL;
 
+  delete callback_table_;
+  callback_table_ = NULL;
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
   delete debugger_;
   debugger_ = NULL;
diff --git a/src/lithium.h b/src/lithium.h
index 170e5c8..ab34453 100644
--- a/src/lithium.h
+++ b/src/lithium.h
@@ -527,6 +527,7 @@
         deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
         translation_index_(-1),
         ast_id_(ast_id),
+        translation_size_(value_count),
         parameter_count_(parameter_count),
         pc_offset_(-1),
         values_(value_count, zone),
@@ -544,6 +545,7 @@
   int deoptimization_index() const { return deoptimization_index_; }
   int translation_index() const { return translation_index_; }
   BailoutId ast_id() const { return ast_id_; }
+  int translation_size() const { return translation_size_; }
   int parameter_count() const { return parameter_count_; }
   int pc_offset() const { return pc_offset_; }
   LOperand** spilled_registers() const { return spilled_registers_; }
@@ -553,6 +555,7 @@
   const ZoneList<LOperand*>* values() const { return &values_; }
   LEnvironment* outer() const { return outer_; }
   HEnterInlined* entry() { return entry_; }
+  Zone* zone() const { return zone_; }
 
   void AddValue(LOperand* operand,
                 Representation representation,
@@ -560,11 +563,11 @@
     values_.Add(operand, zone());
     if (representation.IsSmiOrTagged()) {
       ASSERT(!is_uint32);
-      is_tagged_.Add(values_.length() - 1);
+      is_tagged_.Add(values_.length() - 1, zone());
     }
 
     if (is_uint32) {
-      is_uint32_.Add(values_.length() - 1);
+      is_uint32_.Add(values_.length() - 1, zone());
     }
   }
 
@@ -596,8 +599,6 @@
 
   void PrintTo(StringStream* stream);
 
-  Zone* zone() const { return zone_; }
-
  private:
   Handle<JSFunction> closure_;
   FrameType frame_type_;
@@ -605,11 +606,15 @@
   int deoptimization_index_;
   int translation_index_;
   BailoutId ast_id_;
+  int translation_size_;
   int parameter_count_;
   int pc_offset_;
+
+  // Value array: [parameters] [locals] [expression stack] [de-materialized].
+  //              |>--------- translation_size ---------<|
   ZoneList<LOperand*> values_;
-  BitVector is_tagged_;
-  BitVector is_uint32_;
+  GrowableBitVector is_tagged_;
+  GrowableBitVector is_uint32_;
 
   // Allocation index indexed arrays of spill slot operands for registers
   // that are also in spill slots at an OSR entry.  NULL for environments
@@ -619,7 +624,6 @@
 
   LEnvironment* outer_;
   HEnterInlined* entry_;
-
   Zone* zone_;
 };
 
diff --git a/src/log.cc b/src/log.cc
index 610a63b..c653c14 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1728,10 +1728,18 @@
   Handle<String> func_name(shared->DebugName());
   if (shared->script()->IsScript()) {
     Handle<Script> script(Script::cast(shared->script()));
+    Handle<String> script_name;
     if (script->name()->IsString()) {
-      Handle<String> script_name(String::cast(script->name()));
+      script_name = Handle<String>(String::cast(script->name()));
+    } else {
+      Handle<Object> name = GetScriptNameOrSourceURL(script);
+      if (!name.is_null() && name->IsString()) {
+        script_name = Handle<String>::cast(name);
+      }
+    }
+    if (!script_name.is_null()) {
       int line_num = GetScriptLineNumber(script, shared->start_position());
-      if (line_num > 0) {
+      if (line_num > -1) {
         PROFILE(isolate_,
                 CodeCreateEvent(
                     Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index dc2db4b..0501ccf 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -148,6 +148,7 @@
   VerifyMarking(heap->old_data_space());
   VerifyMarking(heap->code_space());
   VerifyMarking(heap->cell_space());
+  VerifyMarking(heap->property_cell_space());
   VerifyMarking(heap->map_space());
   VerifyMarking(heap->new_space());
 
@@ -229,6 +230,7 @@
   VerifyEvacuation(heap->old_data_space());
   VerifyEvacuation(heap->code_space());
   VerifyEvacuation(heap->cell_space());
+  VerifyEvacuation(heap->property_cell_space());
   VerifyEvacuation(heap->map_space());
   VerifyEvacuation(heap->new_space());
 
@@ -283,7 +285,7 @@
               array->set_length(length);
             }
             break;
-          case JS_GLOBAL_PROPERTY_CELL_TYPE:
+          case CELL_TYPE:
           case JS_PROXY_TYPE:
           case JS_VALUE_TYPE:
           case TYPE_FEEDBACK_INFO_TYPE:
@@ -375,6 +377,7 @@
     if (FLAG_trace_fragmentation) {
       TraceFragmentation(heap()->map_space());
       TraceFragmentation(heap()->cell_space());
+      TraceFragmentation(heap()->property_cell_space());
     }
 
     heap()->old_pointer_space()->EvictEvacuationCandidatesFromFreeLists();
@@ -468,6 +471,7 @@
   VerifyMarkbitsAreClean(heap_->old_data_space());
   VerifyMarkbitsAreClean(heap_->code_space());
   VerifyMarkbitsAreClean(heap_->cell_space());
+  VerifyMarkbitsAreClean(heap_->property_cell_space());
   VerifyMarkbitsAreClean(heap_->map_space());
   VerifyMarkbitsAreClean(heap_->new_space());
 
@@ -529,6 +533,7 @@
   ClearMarkbitsInPagedSpace(heap_->old_pointer_space());
   ClearMarkbitsInPagedSpace(heap_->old_data_space());
   ClearMarkbitsInPagedSpace(heap_->cell_space());
+  ClearMarkbitsInPagedSpace(heap_->property_cell_space());
   ClearMarkbitsInNewSpace(heap_->new_space());
 
   LargeObjectIterator it(heap_->lo_space());
@@ -648,6 +653,8 @@
     case CODE_SPACE: return "CODE_SPACE";
     case MAP_SPACE: return "MAP_SPACE";
     case CELL_SPACE: return "CELL_SPACE";
+    case PROPERTY_CELL_SPACE:
+      return "PROPERTY_CELL_SPACE";
     case LO_SPACE: return "LO_SPACE";
     default:
       UNREACHABLE();
@@ -1004,7 +1011,7 @@
     if (!code_mark.Get()) {
       if (FLAG_trace_code_flushing && shared->is_compiled()) {
         SmartArrayPointer<char> name = shared->DebugName()->ToCString();
-        PrintF("[code-flushing clears: %s]\n", *name);
+        PrintF("[code-flushing clears: %s - age: %d]\n", *name, code->GetAge());
       }
       shared->set_code(lazy_compile);
       candidate->set_code(lazy_compile);
@@ -1045,7 +1052,7 @@
     if (!code_mark.Get()) {
       if (FLAG_trace_code_flushing && candidate->is_compiled()) {
         SmartArrayPointer<char> name = candidate->DebugName()->ToCString();
-        PrintF("[code-flushing clears: %s]\n", *name);
+        PrintF("[code-flushing clears: %s - age: %d]\n", *name, code->GetAge());
       }
       candidate->set_code(lazy_compile);
     }
@@ -2148,6 +2155,11 @@
                              heap()->cell_space());
   if (marking_deque_.IsFull()) return;
 
+  DiscoverGreyObjectsInSpace(heap(),
+                             &marking_deque_,
+                             heap()->property_cell_space());
+  if (marking_deque_.IsFull()) return;
+
   LargeObjectIterator lo_it(heap()->lo_space());
   DiscoverGreyObjectsWithIterator(heap(),
                                   &marking_deque_,
@@ -2241,12 +2253,30 @@
       HeapObjectIterator cell_iterator(heap()->cell_space());
       HeapObject* cell;
       while ((cell = cell_iterator.Next()) != NULL) {
+        ASSERT(cell->IsCell());
+        if (IsMarked(cell)) {
+          int offset = Cell::kValueOffset;
+          MarkCompactMarkingVisitor::VisitPointer(
+              heap(),
+              reinterpret_cast<Object**>(cell->address() + offset));
+        }
+      }
+    }
+    {
+      HeapObjectIterator js_global_property_cell_iterator(
+          heap()->property_cell_space());
+      HeapObject* cell;
+      while ((cell = js_global_property_cell_iterator.Next()) != NULL) {
         ASSERT(cell->IsJSGlobalPropertyCell());
         if (IsMarked(cell)) {
           int offset = JSGlobalPropertyCell::kValueOffset;
           MarkCompactMarkingVisitor::VisitPointer(
               heap(),
               reinterpret_cast<Object**>(cell->address() + offset));
+          offset = JSGlobalPropertyCell::kTypeOffset;
+          MarkCompactMarkingVisitor::VisitPointer(
+              heap(),
+              reinterpret_cast<Object**>(cell->address() + offset));
         }
       }
     }
@@ -2418,7 +2448,7 @@
       // This map is used for inobject slack tracking and has been detached
       // from SharedFunctionInfo during the mark phase.
       // Since it survived the GC, reattach it now.
-      map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map);
+      map->unchecked_constructor()->shared()->AttachInitialMap(map);
     }
 
     ClearNonLivePrototypeTransitions(map);
@@ -2504,11 +2534,14 @@
   int number_of_entries = starts.number_of_entries();
   if (number_of_entries == 0) return;
   for (int i = 0; i < number_of_entries; i++) {
+    // If the entry is compilation info then the map must be alive,
+    // and ClearAndDeoptimizeDependentCode shouldn't be called.
+    ASSERT(entries->is_code_at(i));
     Code* code = entries->code_at(i);
     if (IsMarked(code) && !code->marked_for_deoptimization()) {
       code->set_marked_for_deoptimization(true);
     }
-    entries->clear_code_at(i);
+    entries->clear_at(i);
   }
   map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array()));
 }
@@ -2525,15 +2558,17 @@
   for (int g = 0; g < DependentCode::kGroupCount; g++) {
     int group_number_of_entries = 0;
     for (int i = starts.at(g); i < starts.at(g + 1); i++) {
-      Code* code = entries->code_at(i);
-      if (IsMarked(code) && !code->marked_for_deoptimization()) {
+      Object* obj = entries->object_at(i);
+      ASSERT(obj->IsCode() || IsMarked(obj));
+      if (IsMarked(obj) &&
+          (!obj->IsCode() || !Code::cast(obj)->marked_for_deoptimization())) {
         if (new_number_of_entries + group_number_of_entries != i) {
-          entries->set_code_at(new_number_of_entries +
-                               group_number_of_entries, code);
+          entries->set_object_at(
+              new_number_of_entries + group_number_of_entries, obj);
         }
-        Object** slot = entries->code_slot_at(new_number_of_entries +
-                                              group_number_of_entries);
-        RecordSlot(slot, slot, code);
+        Object** slot = entries->slot_at(new_number_of_entries +
+                                         group_number_of_entries);
+        RecordSlot(slot, slot, obj);
         group_number_of_entries++;
       }
     }
@@ -2543,7 +2578,7 @@
     new_number_of_entries += group_number_of_entries;
   }
   for (int i = new_number_of_entries; i < number_of_entries; i++) {
-    entries->clear_code_at(i);
+    entries->clear_at(i);
   }
 }
 
@@ -3384,11 +3419,27 @@
   for (HeapObject* cell = cell_iterator.Next();
        cell != NULL;
        cell = cell_iterator.Next()) {
+    if (cell->IsCell()) {
+      Address value_address = reinterpret_cast<Address>(cell) +
+          (Cell::kValueOffset - kHeapObjectTag);
+      updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
+    }
+  }
+
+  HeapObjectIterator js_global_property_cell_iterator(
+      heap_->property_cell_space());
+  for (HeapObject* cell = js_global_property_cell_iterator.Next();
+       cell != NULL;
+       cell = js_global_property_cell_iterator.Next()) {
     if (cell->IsJSGlobalPropertyCell()) {
       Address value_address =
           reinterpret_cast<Address>(cell) +
           (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag);
       updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
+      Address type_address =
+          reinterpret_cast<Address>(cell) +
+          (JSGlobalPropertyCell::kTypeOffset - kHeapObjectTag);
+      updating_visitor.VisitPointer(reinterpret_cast<Object**>(type_address));
     }
   }
 
@@ -4050,6 +4101,7 @@
   SweepSpace(heap()->code_space(), PRECISE);
 
   SweepSpace(heap()->cell_space(), PRECISE);
+  SweepSpace(heap()->property_cell_space(), PRECISE);
 
   EvacuateNewSpaceAndCandidates();
 
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 7368ead..2a51b1c 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -1998,8 +1998,12 @@
   VisitForStackValue(expr->expression());
 
   switch (expr->yield_kind()) {
-    case Yield::INITIAL:
-    case Yield::SUSPEND: {
+    case Yield::SUSPEND:
+      // Pop value from top-of-stack slot; box result into result register.
+      EmitCreateIteratorResult(false);
+      __ push(result_register());
+      // Fall through.
+    case Yield::INITIAL: {
       VisitForStackValue(expr->generator_object());
       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
       __ lw(context_register(),
@@ -2008,12 +2012,8 @@
       Label resume;
       __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
       __ Branch(&resume, ne, result_register(), Operand(at));
-      if (expr->yield_kind() == Yield::SUSPEND) {
-        EmitReturnIteratorResult(false);
-      } else {
-        __ pop(result_register());
-        EmitReturnSequence();
-      }
+      __ pop(result_register());
+      EmitReturnSequence();
 
       __ bind(&resume);
       context()->Plug(result_register());
@@ -2025,7 +2025,10 @@
       __ li(a1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
       __ sw(a1, FieldMemOperand(result_register(),
                                 JSGeneratorObject::kContinuationOffset));
-      EmitReturnIteratorResult(true);
+      // Pop value from top-of-stack slot, box result into result register.
+      EmitCreateIteratorResult(true);
+      EmitUnwindBeforeReturn();
+      EmitReturnSequence();
       break;
     }
 
@@ -2057,10 +2060,10 @@
 
       // try { received = yield result.value }
       __ bind(&l_try);
-      __ pop(a0);                                        // result.value
+      EmitCreateIteratorResult(false);                   // pop and box to v0
       __ PushTryHandler(StackHandler::CATCH, expr->index());
       const int handler_size = StackHandlerConstants::kSize;
-      __ push(a0);                                       // result.value
+      __ push(a0);                                       // result
       __ lw(a3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size));  // g
       __ push(a3);                                       // g
       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
@@ -2069,7 +2072,8 @@
             MemOperand(fp, StandardFrameConstants::kContextOffset));
       __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
       __ Branch(&l_resume, ne, a0, Operand(at));
-      EmitReturnIteratorResult(false);
+      __ pop(v0);                                        // result
+      EmitReturnSequence();
       __ mov(a0, v0);
       __ bind(&l_resume);                                // received in a0
       __ PopTryHandler();
@@ -2226,13 +2230,20 @@
 }
 
 
-void FullCodeGenerator::EmitReturnIteratorResult(bool done) {
+void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label gc_required;
   Label allocated;
 
   Handle<Map> map(isolate()->native_context()->generator_result_map());
 
   __ Allocate(map->instance_size(), a0, a2, a3, &gc_required, TAG_OBJECT);
+  __ jmp(&allocated);
+
+  __ bind(&gc_required);
+  __ Push(Smi::FromInt(map->instance_size()));
+  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+  __ lw(context_register(),
+        MemOperand(fp, StandardFrameConstants::kContextOffset));
 
   __ bind(&allocated);
   __ li(a1, Operand(map));
@@ -2252,27 +2263,7 @@
   // root set.
   __ RecordWriteField(a0, JSGeneratorObject::kResultValuePropertyOffset,
                       a2, a3, kRAHasBeenSaved, kDontSaveFPRegs);
-
-  if (done) {
-    // Exit all nested statements.
-    NestedStatement* current = nesting_stack_;
-    int stack_depth = 0;
-    int context_length = 0;
-    while (current != NULL) {
-      current = current->Exit(&stack_depth, &context_length);
-    }
-    __ Drop(stack_depth);
-  }
-
   __ mov(result_register(), a0);
-  EmitReturnSequence();
-
-  __ bind(&gc_required);
-  __ Push(Smi::FromInt(map->instance_size()));
-  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ lw(context_register(),
-        MemOperand(fp, StandardFrameConstants::kContextOffset));
-  __ jmp(&allocated);
 }
 
 
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 1c8973f..f8d743e 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -87,20 +87,7 @@
     RegisterDependentCodeForEmbeddedMaps(code);
   }
   PopulateDeoptimizationData(code);
-  for (int i = 0 ; i < prototype_maps_.length(); i++) {
-    prototype_maps_.at(i)->AddDependentCode(
-        DependentCode::kPrototypeCheckGroup, code);
-  }
-  for (int i = 0 ; i < transition_maps_.length(); i++) {
-    transition_maps_.at(i)->AddDependentCode(
-        DependentCode::kTransitionGroup, code);
-  }
-  if (graph()->depends_on_empty_array_proto_elements()) {
-    isolate()->initial_object_prototype()->map()->AddDependentCode(
-        DependentCode::kElementsCantBeAddedGroup, code);
-    isolate()->initial_array_prototype()->map()->AddDependentCode(
-        DependentCode::kElementsCantBeAddedGroup, code);
-  }
+  info()->CommitDependentMaps(code);
 }
 
 
@@ -574,27 +561,15 @@
 
 
 void LCodeGen::WriteTranslation(LEnvironment* environment,
-                                Translation* translation,
-                                int* pushed_arguments_index,
-                                int* pushed_arguments_count) {
+                                Translation* translation) {
   if (environment == NULL) return;
 
   // The translation includes one command per value in the environment.
-  int translation_size = environment->values()->length();
+  int translation_size = environment->translation_size();
   // The output frame height does not include the parameters.
   int height = translation_size - environment->parameter_count();
 
-  // Function parameters are arguments to the outermost environment. The
-  // arguments index points to the first element of a sequence of tagged
-  // values on the stack that represent the arguments. This needs to be
-  // kept in sync with the LArgumentsElements implementation.
-  *pushed_arguments_index = -environment->parameter_count();
-  *pushed_arguments_count = environment->parameter_count();
-
-  WriteTranslation(environment->outer(),
-                   translation,
-                   pushed_arguments_index,
-                   pushed_arguments_count);
+  WriteTranslation(environment->outer(), translation);
   bool has_closure_id = !info()->closure().is_null() &&
       !info()->closure().is_identical_to(environment->closure());
   int closure_id = has_closure_id
@@ -626,23 +601,6 @@
       break;
   }
 
-  // Inlined frames which push their arguments cause the index to be
-  // bumped and another stack area to be used for materialization,
-  // otherwise actual argument values are unknown for inlined frames.
-  bool arguments_known = true;
-  int arguments_index = *pushed_arguments_index;
-  int arguments_count = *pushed_arguments_count;
-  if (environment->entry() != NULL) {
-    arguments_known = environment->entry()->arguments_pushed();
-    arguments_index = arguments_index < 0
-        ? GetStackSlotCount() : arguments_index + arguments_count;
-    arguments_count = environment->entry()->arguments_count() + 1;
-    if (environment->entry()->arguments_pushed()) {
-      *pushed_arguments_index = arguments_index;
-      *pushed_arguments_count = arguments_count;
-    }
-  }
-
   for (int i = 0; i < translation_size; ++i) {
     LOperand* value = environment->values()->at(i);
     // spilled_registers_ and spilled_double_registers_ are either
@@ -654,10 +612,7 @@
         AddToTranslation(translation,
                          environment->spilled_registers()[value->index()],
                          environment->HasTaggedValueAt(i),
-                         environment->HasUint32ValueAt(i),
-                         arguments_known,
-                         arguments_index,
-                         arguments_count);
+                         environment->HasUint32ValueAt(i));
       } else if (
           value->IsDoubleRegister() &&
           environment->spilled_double_registers()[value->index()] != NULL) {
@@ -666,20 +621,36 @@
             translation,
             environment->spilled_double_registers()[value->index()],
             false,
-            false,
-            arguments_known,
-            arguments_index,
-            arguments_count);
+            false);
       }
     }
 
+    // TODO(mstarzinger): Introduce marker operands to indicate that this value
+    // is not present and must be reconstructed from the deoptimizer. Currently
+    // this is only used for the arguments object.
+    if (value == NULL) {
+      int arguments_count = environment->values()->length() - translation_size;
+      translation->BeginArgumentsObject(arguments_count);
+      for (int i = 0; i < arguments_count; ++i) {
+        LOperand* value = environment->values()->at(translation_size + i);
+        ASSERT(environment->spilled_registers() == NULL ||
+               !value->IsRegister() ||
+               environment->spilled_registers()[value->index()] == NULL);
+        ASSERT(environment->spilled_registers() == NULL ||
+               !value->IsDoubleRegister() ||
+               environment->spilled_double_registers()[value->index()] == NULL);
+        AddToTranslation(translation,
+                         value,
+                         environment->HasTaggedValueAt(translation_size + i),
+                         environment->HasUint32ValueAt(translation_size + i));
+      }
+      continue;
+    }
+
     AddToTranslation(translation,
                      value,
                      environment->HasTaggedValueAt(i),
-                     environment->HasUint32ValueAt(i),
-                     arguments_known,
-                     arguments_index,
-                     arguments_count);
+                     environment->HasUint32ValueAt(i));
   }
 }
 
@@ -687,17 +658,8 @@
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged,
-                                bool is_uint32,
-                                bool arguments_known,
-                                int arguments_index,
-                                int arguments_count) {
-  if (op == NULL) {
-    // TODO(twuerthinger): Introduce marker operands to indicate that this value
-    // is not present and must be reconstructed from the deoptimizer. Currently
-    // this is only used for the arguments object.
-    translation->StoreArgumentsObject(
-        arguments_known, arguments_index, arguments_count);
-  } else if (op->IsStackSlot()) {
+                                bool is_uint32) {
+  if (op->IsStackSlot()) {
     if (is_tagged) {
       translation->StoreStackSlot(op->index());
     } else if (is_uint32) {
@@ -792,8 +754,6 @@
 
     int frame_count = 0;
     int jsframe_count = 0;
-    int args_index = 0;
-    int args_count = 0;
     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
       ++frame_count;
       if (e->frame_type() == JS_FUNCTION) {
@@ -801,7 +761,7 @@
       }
     }
     Translation translation(&translations_, frame_count, jsframe_count, zone());
-    WriteTranslation(environment, &translation, &args_index, &args_count);
+    WriteTranslation(environment, &translation);
     int deoptimization_index = deoptimizations_.length();
     int pc_offset = masm()->pc_offset();
     environment->Register(deoptimization_index,
@@ -1246,8 +1206,10 @@
     __ bind(&left_not_min_int);
   }
 
-  __ mfhi(result);
-  DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
+  if (!instr->hydrogen()->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
+    __ mfhi(result);
+    DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
+  }
   __ mflo(result);
 }
 
@@ -3989,9 +3951,6 @@
   }
 
   if (!transition.is_null()) {
-    if (transition->CanBeDeprecated()) {
-      transition_maps_.Add(transition, info()->zone());
-    }
     __ li(scratch, Operand(transition));
     __ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
     if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
@@ -5142,11 +5101,7 @@
 
   ASSERT(prototypes->length() == maps->length());
 
-  if (instr->hydrogen()->CanOmitPrototypeChecks()) {
-    for (int i = 0; i < maps->length(); i++) {
-      prototype_maps_.Add(maps->at(i), info()->zone());
-    }
-  } else {
+  if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
     for (int i = 0; i < prototypes->length(); i++) {
       __ LoadHeapObject(prototype_reg, prototypes->at(i));
       __ lw(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index a208c40..a8d7e04 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -55,8 +55,6 @@
         deoptimizations_(4, info->zone()),
         deopt_jump_table_(4, info->zone()),
         deoptimization_literals_(8, info->zone()),
-        prototype_maps_(0, info->zone()),
-        transition_maps_(0, info->zone()),
         inlined_function_count_(0),
         scope_(info->scope()),
         status_(UNUSED),
@@ -171,10 +169,7 @@
                                  int additional_offset);
 
   // Emit frame translation commands for an environment.
-  void WriteTranslation(LEnvironment* environment,
-                        Translation* translation,
-                        int* arguments_index,
-                        int* arguments_count);
+  void WriteTranslation(LEnvironment* environment, Translation* translation);
 
   // Declare methods that deal with the individual node types.
 #define DECLARE_DO(type) void Do##type(L##type* node);
@@ -297,10 +292,7 @@
   void AddToTranslation(Translation* translation,
                         LOperand* op,
                         bool is_tagged,
-                        bool is_uint32,
-                        bool arguments_known,
-                        int arguments_index,
-                        int arguments_count);
+                        bool is_uint32);
   void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -412,8 +404,6 @@
   ZoneList<LEnvironment*> deoptimizations_;
   ZoneList<Deoptimizer::JumpTableEntry> deopt_jump_table_;
   ZoneList<Handle<Object> > deoptimization_literals_;
-  ZoneList<Handle<Map> > prototype_maps_;
-  ZoneList<Handle<Map> > transition_maps_;
   int inlined_function_count_;
   Scope* const scope_;
   Status status_;
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index ad39c61..889e997 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -933,7 +933,7 @@
   BailoutId ast_id = hydrogen_env->ast_id();
   ASSERT(!ast_id.IsNone() ||
          hydrogen_env->frame_type() != JS_FUNCTION);
-  int value_count = hydrogen_env->length();
+  int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
   LEnvironment* result = new(zone()) LEnvironment(
       hydrogen_env->closure(),
       hydrogen_env->frame_type(),
@@ -944,13 +944,15 @@
       outer,
       hydrogen_env->entry(),
       zone());
+  bool needs_arguments_object_materialization = false;
   int argument_index = *argument_index_accumulator;
-  for (int i = 0; i < value_count; ++i) {
+  for (int i = 0; i < hydrogen_env->length(); ++i) {
     if (hydrogen_env->is_special_index(i)) continue;
 
     HValue* value = hydrogen_env->values()->at(i);
     LOperand* op = NULL;
     if (value->IsArgumentsObject()) {
+      needs_arguments_object_materialization = true;
       op = NULL;
     } else if (value->IsPushArgument()) {
       op = new(zone()) LArgument(argument_index++);
@@ -962,6 +964,22 @@
                      value->CheckFlag(HInstruction::kUint32));
   }
 
+  if (needs_arguments_object_materialization) {
+    HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+        ? graph()->GetArgumentsObject()
+        : hydrogen_env->entry()->arguments_object();
+    ASSERT(arguments->IsLinked());
+    for (int i = 1; i < arguments->arguments_count(); ++i) {
+      HValue* value = arguments->arguments_values()->at(i);
+      ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+      ASSERT(HInstruction::cast(value)->IsLinked());
+      LOperand* op = UseAny(value);
+      result->AddValue(op,
+                       value->representation(),
+                       value->CheckFlag(HInstruction::kUint32));
+    }
+  }
+
   if (hydrogen_env->frame_type() == JS_FUNCTION) {
     *argument_index_accumulator = argument_index;
   }
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index 978ea21..71e9e69 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -172,7 +172,8 @@
       int data_space_used,
       int code_space_used,
       int map_space_used,
-      int cell_space_used) {
+      int cell_space_used,
+      int property_cell_space_used) {
     fprintf(fp_,
             "const int Snapshot::%snew_space_used_ = %d;\n",
             prefix,
@@ -197,6 +198,10 @@
             "const int Snapshot::%scell_space_used_ = %d;\n",
             prefix,
             cell_space_used);
+    fprintf(fp_,
+            "const int Snapshot::%sproperty_cell_space_used_ = %d;\n",
+            prefix,
+            property_cell_space_used);
   }
 
   void WritePartialSnapshot() {
@@ -417,7 +422,8 @@
       partial_ser.CurrentAllocationAddress(i::OLD_DATA_SPACE),
       partial_ser.CurrentAllocationAddress(i::CODE_SPACE),
       partial_ser.CurrentAllocationAddress(i::MAP_SPACE),
-      partial_ser.CurrentAllocationAddress(i::CELL_SPACE));
+      partial_ser.CurrentAllocationAddress(i::CELL_SPACE),
+      partial_ser.CurrentAllocationAddress(i::PROPERTY_CELL_SPACE));
   sink.WriteSpaceUsed(
       "",
       ser.CurrentAllocationAddress(i::NEW_SPACE),
@@ -425,6 +431,7 @@
       ser.CurrentAllocationAddress(i::OLD_DATA_SPACE),
       ser.CurrentAllocationAddress(i::CODE_SPACE),
       ser.CurrentAllocationAddress(i::MAP_SPACE),
-      ser.CurrentAllocationAddress(i::CELL_SPACE));
+      ser.CurrentAllocationAddress(i::CELL_SPACE),
+      ser.CurrentAllocationAddress(i::PROPERTY_CELL_SPACE));
   return 0;
 }
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 4008181..3b561ee 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -163,7 +163,10 @@
     case JS_BUILTINS_OBJECT_TYPE:
       JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
       break;
-    case JS_GLOBAL_PROPERTY_CELL_TYPE:
+    case CELL_TYPE:
+      Cell::cast(this)->CellVerify();
+      break;
+    case PROPERTY_CELL_TYPE:
       JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellVerify();
       break;
     case JS_ARRAY_TYPE:
@@ -615,9 +618,16 @@
 }
 
 
+void Cell::CellVerify() {
+  CHECK(IsCell());
+  VerifyObjectField(kValueOffset);
+}
+
+
 void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() {
   CHECK(IsJSGlobalPropertyCell());
   VerifyObjectField(kValueOffset);
+  VerifyObjectField(kTypeOffset);
 }
 
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index e60f0f3..24af123 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -668,7 +668,8 @@
 
 TYPE_CHECKER(Code, CODE_TYPE)
 TYPE_CHECKER(Oddball, ODDBALL_TYPE)
-TYPE_CHECKER(JSGlobalPropertyCell, JS_GLOBAL_PROPERTY_CELL_TYPE)
+TYPE_CHECKER(Cell, CELL_TYPE)
+TYPE_CHECKER(JSGlobalPropertyCell, PROPERTY_CELL_TYPE)
 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
 TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
 TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
@@ -1621,18 +1622,28 @@
 }
 
 
-Object* JSGlobalPropertyCell::value() {
+Object* Cell::value() {
   return READ_FIELD(this, kValueOffset);
 }
 
 
-void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
+void Cell::set_value(Object* val, WriteBarrierMode ignored) {
   // The write barrier is not used for global property cells.
-  ASSERT(!val->IsJSGlobalPropertyCell());
+  ASSERT(!val->IsJSGlobalPropertyCell() && !val->IsCell());
   WRITE_FIELD(this, kValueOffset, val);
 }
 
 
+Object* JSGlobalPropertyCell::type_raw() {
+  return READ_FIELD(this, kTypeOffset);
+}
+
+
+void JSGlobalPropertyCell::set_type_raw(Object* val, WriteBarrierMode ignored) {
+  WRITE_FIELD(this, kTypeOffset, val);
+}
+
+
 int JSObject::GetHeaderSize() {
   InstanceType type = map()->instance_type();
   // Check for the most common kind of JavaScript object before
@@ -2552,6 +2563,7 @@
 CAST_ACCESSOR(HeapObject)
 CAST_ACCESSOR(HeapNumber)
 CAST_ACCESSOR(Oddball)
+CAST_ACCESSOR(Cell)
 CAST_ACCESSOR(JSGlobalPropertyCell)
 CAST_ACCESSOR(SharedFunctionInfo)
 CAST_ACCESSOR(Map)
@@ -3659,17 +3671,6 @@
 }
 
 
-void Map::AddDependentCode(DependentCode::DependencyGroup group,
-                           Handle<Code> code) {
-  Handle<DependentCode> codes =
-      DependentCode::Insert(Handle<DependentCode>(dependent_code()),
-                             group, code);
-  if (*codes != dependent_code()) {
-    set_dependent_code(*codes);
-  }
-}
-
-
 int DependentCode::number_of_entries(DependencyGroup group) {
   if (length() == 0) return 0;
   return Smi::cast(get(group))->value();
@@ -3681,32 +3682,52 @@
 }
 
 
+bool DependentCode::is_code_at(int i) {
+  return get(kCodesStartIndex + i)->IsCode();
+}
+
 Code* DependentCode::code_at(int i) {
   return Code::cast(get(kCodesStartIndex + i));
 }
 
 
-void DependentCode::set_code_at(int i, Code* value) {
-  set(kCodesStartIndex + i, value);
+CompilationInfo* DependentCode::compilation_info_at(int i) {
+  return reinterpret_cast<CompilationInfo*>(
+      Foreign::cast(get(kCodesStartIndex + i))->foreign_address());
 }
 
 
-Object** DependentCode::code_slot_at(int i) {
+void DependentCode::set_object_at(int i, Object* object) {
+  set(kCodesStartIndex + i, object);
+}
+
+
+Object* DependentCode::object_at(int i) {
+  return get(kCodesStartIndex + i);
+}
+
+
+Object** DependentCode::slot_at(int i) {
   return HeapObject::RawField(
       this, FixedArray::OffsetOfElementAt(kCodesStartIndex + i));
 }
 
 
-void DependentCode::clear_code_at(int i) {
+void DependentCode::clear_at(int i) {
   set_undefined(kCodesStartIndex + i);
 }
 
 
+void DependentCode::copy(int from, int to) {
+  set(kCodesStartIndex + to, get(kCodesStartIndex + from));
+}
+
+
 void DependentCode::ExtendGroup(DependencyGroup group) {
   GroupStartIndexes starts(this);
   for (int g = kGroupCount - 1; g > group; g--) {
     if (starts.at(g) < starts.at(g + 1)) {
-      set_code_at(starts.at(g + 1), code_at(starts.at(g)));
+      copy(starts.at(g), starts.at(g + 1));
     }
   }
 }
@@ -4960,12 +4981,6 @@
 }
 
 
-SharedFunctionInfo* JSFunction::unchecked_shared() {
-  return reinterpret_cast<SharedFunctionInfo*>(
-      READ_FIELD(this, kSharedFunctionInfoOffset));
-}
-
-
 void JSFunction::set_context(Object* value) {
   ASSERT(value->IsUndefined() || value->IsContext());
   WRITE_FIELD(this, kContextOffset, value);
@@ -6011,13 +6026,13 @@
 }
 
 
-void TypeFeedbackCells::SetCell(int index, JSGlobalPropertyCell* cell) {
+void TypeFeedbackCells::SetCell(int index, Cell* cell) {
   set(index * 2, cell);
 }
 
 
-JSGlobalPropertyCell* TypeFeedbackCells::Cell(int index) {
-  return JSGlobalPropertyCell::cast(get(index * 2));
+Cell* TypeFeedbackCells::GetCell(int index) {
+  return Cell::cast(get(index * 2));
 }
 
 
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 357d984..33aa404 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -182,7 +182,10 @@
     case JS_MESSAGE_OBJECT_TYPE:
       JSMessageObject::cast(this)->JSMessageObjectPrint(out);
       break;
-    case JS_GLOBAL_PROPERTY_CELL_TYPE:
+    case CELL_TYPE:
+      Cell::cast(this)->CellPrint(out);
+      break;
+    case PROPERTY_CELL_TYPE:
       JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
       break;
     case JS_ARRAY_BUFFER_TYPE:
@@ -533,7 +536,8 @@
     case JS_OBJECT_TYPE: return "JS_OBJECT";
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT";
     case ODDBALL_TYPE: return "ODDBALL";
-    case JS_GLOBAL_PROPERTY_CELL_TYPE: return "JS_GLOBAL_PROPERTY_CELL";
+    case CELL_TYPE: return "CELL";
+    case PROPERTY_CELL_TYPE: return "PROPERTY_CELL";
     case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
     case JS_GENERATOR_OBJECT_TYPE: return "JS_GENERATOR_OBJECT";
     case JS_MODULE_TYPE: return "JS_MODULE";
@@ -917,6 +921,11 @@
 }
 
 
+void Cell::CellPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "Cell");
+}
+
+
 void JSGlobalPropertyCell::JSGlobalPropertyCellPrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSGlobalPropertyCell");
 }
@@ -1093,8 +1102,8 @@
 void AllocationSiteInfo::AllocationSiteInfoPrint(FILE* out) {
   HeapObject::PrintHeader(out, "AllocationSiteInfo");
   PrintF(out, " - payload: ");
-  if (payload()->IsJSGlobalPropertyCell()) {
-    JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(payload());
+  if (payload()->IsCell()) {
+    Cell* cell = Cell::cast(payload());
     Object* cell_contents = cell->value();
     if (cell_contents->IsSmi()) {
       ElementsKind kind = static_cast<ElementsKind>(
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index 829eab8..c138fdd 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -196,6 +196,11 @@
 
   // Registration for kVisitJSRegExp is done by StaticVisitor.
 
+  table_.Register(kVisitCell,
+                  &FixedBodyVisitor<StaticVisitor,
+                  Cell::BodyDescriptor,
+                  void>::Visit);
+
   table_.Register(kVisitPropertyCell,
                   &FixedBodyVisitor<StaticVisitor,
                   JSGlobalPropertyCell::BodyDescriptor,
@@ -240,10 +245,10 @@
 
 
 template<typename StaticVisitor>
-void StaticMarkingVisitor<StaticVisitor>::VisitGlobalPropertyCell(
+void StaticMarkingVisitor<StaticVisitor>::VisitCell(
     Heap* heap, RelocInfo* rinfo) {
-  ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
-  JSGlobalPropertyCell* cell = rinfo->target_cell();
+  ASSERT(rinfo->rmode() == RelocInfo::CELL);
+  Cell* cell = rinfo->target_cell();
   StaticVisitor::MarkObject(heap, cell);
 }
 
@@ -414,7 +419,7 @@
       // Visit shared function info immediately to avoid double checking
       // of its flushability later. This is just an optimization because
       // the shared function info would eventually be visited.
-      SharedFunctionInfo* shared = function->unchecked_shared();
+      SharedFunctionInfo* shared = function->shared();
       if (StaticVisitor::MarkObjectWithoutPush(heap, shared)) {
         StaticVisitor::MarkObject(heap, shared->map());
         VisitSharedFunctionInfoWeakCode(heap, shared);
@@ -595,7 +600,7 @@
 template<typename StaticVisitor>
 bool StaticMarkingVisitor<StaticVisitor>::IsFlushable(
     Heap* heap, JSFunction* function) {
-  SharedFunctionInfo* shared_info = function->unchecked_shared();
+  SharedFunctionInfo* shared_info = function->shared();
 
   // Code is either on stack, in compilation cache or referenced
   // by optimized version of function.
@@ -777,7 +782,7 @@
 void Code::CodeIterateBody(ObjectVisitor* v) {
   int mode_mask = RelocInfo::kCodeTargetMask |
                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
-                  RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
+                  RelocInfo::ModeMask(RelocInfo::CELL) |
                   RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
                   RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
                   RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
@@ -801,7 +806,7 @@
 void Code::CodeIterateBody(Heap* heap) {
   int mode_mask = RelocInfo::kCodeTargetMask |
                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
-                  RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
+                  RelocInfo::ModeMask(RelocInfo::CELL) |
                   RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
                   RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
                   RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc
index 4bf2804..686cacf 100644
--- a/src/objects-visiting.cc
+++ b/src/objects-visiting.cc
@@ -91,7 +91,10 @@
     case CODE_TYPE:
       return kVisitCode;
 
-    case JS_GLOBAL_PROPERTY_CELL_TYPE:
+    case CELL_TYPE:
+      return kVisitCell;
+
+    case PROPERTY_CELL_TYPE:
       return kVisitPropertyCell;
 
     case JS_SET_TYPE:
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index c4d1cc3..f347c87 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -88,6 +88,7 @@
   V(Oddball)                  \
   V(Code)                     \
   V(Map)                      \
+  V(Cell)                     \
   V(PropertyCell)             \
   V(SharedFunctionInfo)       \
   V(JSFunction)               \
@@ -394,7 +395,7 @@
 
   INLINE(static void VisitCodeEntry(Heap* heap, Address entry_address));
   INLINE(static void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo));
-  INLINE(static void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo));
+  INLINE(static void VisitCell(Heap* heap, RelocInfo* rinfo));
   INLINE(static void VisitDebugTarget(Heap* heap, RelocInfo* rinfo));
   INLINE(static void VisitCodeTarget(Heap* heap, RelocInfo* rinfo));
   INLINE(static void VisitCodeAgeSequence(Heap* heap, RelocInfo* rinfo));
diff --git a/src/objects.cc b/src/objects.cc
index 6512c60..5459679 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -631,7 +631,7 @@
   if (IsGlobalObject()) {
     value = JSGlobalPropertyCell::cast(value)->value();
   }
-  ASSERT(!value->IsJSGlobalPropertyCell());
+  ASSERT(!value->IsJSGlobalPropertyCell() && !value->IsCell());
   return value;
 }
 
@@ -639,9 +639,8 @@
 Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
   ASSERT(!HasFastProperties());
   if (IsGlobalObject()) {
-    JSGlobalPropertyCell* cell =
-        JSGlobalPropertyCell::cast(
-            property_dictionary()->ValueAt(result->GetDictionaryEntry()));
+    JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
+        property_dictionary()->ValueAt(result->GetDictionaryEntry()));
     cell->set_value(value);
   } else {
     property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
@@ -1385,7 +1384,7 @@
                        global_object ? "Global Object: " : "",
                        vowel ? "n" : "");
                 accumulator->Put(str);
-                accumulator->Add(" with %smap 0x%p",
+                accumulator->Add(" with %smap %p",
                     map_of_this->is_deprecated() ? "deprecated " : "",
                     map_of_this);
                 printed = true;
@@ -1567,8 +1566,12 @@
     case FOREIGN_TYPE:
       accumulator->Add("<Foreign>");
       break;
-    case JS_GLOBAL_PROPERTY_CELL_TYPE:
+    case CELL_TYPE:
       accumulator->Add("Cell for ");
+      Cell::cast(this)->value()->ShortPrint(accumulator);
+      break;
+    case PROPERTY_CELL_TYPE:
+      accumulator->Add("PropertyCell for ");
       JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
       break;
     default:
@@ -1661,7 +1664,10 @@
     case CODE_TYPE:
       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
       break;
-    case JS_GLOBAL_PROPERTY_CELL_TYPE:
+    case CELL_TYPE:
+      Cell::BodyDescriptor::IterateBody(this, v);
+      break;
+    case PROPERTY_CELL_TYPE:
       JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v);
       break;
     case SYMBOL_TYPE:
@@ -8905,8 +8911,8 @@
 
 bool AllocationSiteInfo::GetElementsKindPayload(ElementsKind* kind) {
   ASSERT(kind != NULL);
-  if (payload()->IsJSGlobalPropertyCell()) {
-    JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(payload());
+  if (payload()->IsCell()) {
+    Cell* cell = Cell::cast(payload());
     Object* cell_contents = cell->value();
     if (cell_contents->IsSmi()) {
       *kind = static_cast<ElementsKind>(
@@ -9980,13 +9986,13 @@
 }
 
 
-void ObjectVisitor::VisitGlobalPropertyCell(RelocInfo* rinfo) {
-  ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
+void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
+  ASSERT(rinfo->rmode() == RelocInfo::CELL);
   Object* cell = rinfo->target_cell();
   Object* old_cell = cell;
   VisitPointer(&cell);
   if (cell != old_cell) {
-    rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
+    rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
   }
 }
 
@@ -10012,7 +10018,7 @@
   VisitExternalReferences(p, p + 1);
 }
 
-byte Code::compare_nil_types() {
+byte Code::compare_nil_state() {
   ASSERT(is_compare_nil_ic_stub());
   return CompareNilICStub::ExtractTypesFromExtraICState(
       extended_extra_ic_state());
@@ -10048,7 +10054,7 @@
   intptr_t delta = instruction_start() - desc.buffer;
   int mode_mask = RelocInfo::kCodeTargetMask |
                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
-                  RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
+                  RelocInfo::ModeMask(RelocInfo::CELL) |
                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
                   RelocInfo::kApplyMask;
   // Needed to find target_object and runtime_entry on X64
@@ -10059,8 +10065,8 @@
     if (mode == RelocInfo::EMBEDDED_OBJECT) {
       Handle<Object> p = it.rinfo()->target_object_handle(origin);
       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
-    } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
-      Handle<JSGlobalPropertyCell> cell  = it.rinfo()->target_cell_handle();
+    } else if (mode == RelocInfo::CELL) {
+      Handle<Cell> cell  = it.rinfo()->target_cell_handle();
       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
     } else if (RelocInfo::IsCodeTarget(mode)) {
       // rewrite code handles in inline cache targets to direct
@@ -10246,7 +10252,7 @@
     TypeFeedbackCells* type_feedback_cells =
         TypeFeedbackInfo::cast(raw_info)->type_feedback_cells();
     for (int i = 0; i < type_feedback_cells->CellCount(); i++) {
-      JSGlobalPropertyCell* cell = type_feedback_cells->Cell(i);
+      Cell* cell = type_feedback_cells->GetCell(i);
       cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap));
     }
   }
@@ -10299,6 +10305,18 @@
 }
 
 
+int Code::GetAge() {
+  byte* sequence = FindCodeAgeSequence();
+  if (sequence == NULL) {
+    return Code::kNoAge;
+  }
+  Age age;
+  MarkingParity parity;
+  GetCodeAgeAndParity(sequence, &age, &parity);
+  return age;
+}
+
+
 void Code::GetCodeAgeAndParity(Code* code, Age* age,
                                MarkingParity* parity) {
   Isolate* isolate = Isolate::Current();
@@ -10538,11 +10556,8 @@
         }
 
         case Translation::ARGUMENTS_OBJECT: {
-          bool args_known = iterator.Next();
-          int args_index = iterator.Next();
           int args_length = iterator.Next();
-          PrintF(out, "{index=%d, length=%d, known=%d}",
-                 args_index, args_length, args_known);
+          PrintF(out, "{length=%d}", args_length);
           break;
         }
       }
@@ -11091,6 +11106,24 @@
 }
 
 
+void Map::AddDependentCompilationInfo(DependentCode::DependencyGroup group,
+                                      CompilationInfo* info) {
+  Handle<DependentCode> dep(dependent_code());
+  Handle<DependentCode> codes =
+      DependentCode::Insert(dep, group, info->object_wrapper());
+  if (*codes != dependent_code()) set_dependent_code(*codes);
+  info->dependent_maps(group)->Add(Handle<Map>(this), info->zone());
+}
+
+
+void Map::AddDependentCode(DependentCode::DependencyGroup group,
+                           Handle<Code> code) {
+  Handle<DependentCode> codes = DependentCode::Insert(
+      Handle<DependentCode>(dependent_code()), group, code);
+  if (*codes != dependent_code()) set_dependent_code(*codes);
+}
+
+
 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
   Recompute(entries);
 }
@@ -11107,13 +11140,13 @@
 
 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
                                             DependencyGroup group,
-                                            Handle<Code> value) {
+                                            Handle<Object> object) {
   GroupStartIndexes starts(*entries);
   int start = starts.at(group);
   int end = starts.at(group + 1);
   int number_of_entries = starts.number_of_entries();
-  if (start < end && entries->code_at(end - 1) == *value) {
-    // Do not append the code if it is already in the array.
+  if (start < end && entries->object_at(end - 1) == *object) {
+    // Do not append the compilation info if it is already in the array.
     // It is sufficient to just check only the last element because
     // we process embedded maps of an optimized code in one batch.
     return entries;
@@ -11130,7 +11163,7 @@
     end = starts.at(group + 1);
     number_of_entries = starts.number_of_entries();
     for (int i = 0; i < number_of_entries; i++) {
-      entries->clear_code_at(i);
+      entries->clear_at(i);
     }
     // If the old fixed array was empty, we need to reset counters of the
     // new array.
@@ -11142,17 +11175,79 @@
     entries = new_entries;
   }
   entries->ExtendGroup(group);
-  entries->set_code_at(end, *value);
+  entries->set_object_at(end, *object);
   entries->set_number_of_entries(group, end + 1 - start);
   return entries;
 }
 
 
+void DependentCode::UpdateToFinishedCode(DependencyGroup group,
+                                         CompilationInfo* info,
+                                         Code* code) {
+  DisallowHeapAllocation no_gc;
+  AllowDeferredHandleDereference get_object_wrapper;
+  Foreign* info_wrapper = *info->object_wrapper();
+  GroupStartIndexes starts(this);
+  int start = starts.at(group);
+  int end = starts.at(group + 1);
+  for (int i = start; i < end; i++) {
+    if (object_at(i) == info_wrapper) {
+      set_object_at(i, code);
+      break;
+    }
+  }
+
+#ifdef DEBUG
+  for (int i = start; i < end; i++) {
+    ASSERT(is_code_at(i) || compilation_info_at(i) != info);
+  }
+#endif
+}
+
+
+void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
+                                          CompilationInfo* info) {
+  DisallowHeapAllocation no_allocation;
+  AllowDeferredHandleDereference get_object_wrapper;
+  Foreign* info_wrapper = *info->object_wrapper();
+  GroupStartIndexes starts(this);
+  int start = starts.at(group);
+  int end = starts.at(group + 1);
+  // Find compilation info wrapper.
+  int info_pos = -1;
+  for (int i = start; i < end; i++) {
+    if (object_at(i) == info_wrapper) {
+      info_pos = i;
+      break;
+    }
+  }
+  if (info_pos == -1) return;  // Not found.
+  int gap = info_pos;
+  // Use the last of each group to fill the gap in the previous group.
+  for (int i = group; i < kGroupCount; i++) {
+    int last_of_group = starts.at(i + 1) - 1;
+    ASSERT(last_of_group >= gap);
+    if (last_of_group == gap) continue;
+    copy(last_of_group, gap);
+    gap = last_of_group;
+  }
+  ASSERT(gap == starts.number_of_entries() - 1);
+  clear_at(gap);  // Clear last gap.
+  set_number_of_entries(group, end - start - 1);
+
+#ifdef DEBUG
+  for (int i = start; i < end - 1; i++) {
+    ASSERT(is_code_at(i) || compilation_info_at(i) != info);
+  }
+#endif
+}
+
+
 bool DependentCode::Contains(DependencyGroup group, Code* code) {
   GroupStartIndexes starts(this);
-  int number_of_entries = starts.at(kGroupCount);
+  int number_of_entries = starts.number_of_entries();
   for (int i = 0; i < number_of_entries; i++) {
-    if (code_at(i) == code) return true;
+    if (object_at(i) == code) return true;
   }
   return false;
 }
@@ -11173,20 +11268,25 @@
   DependentCode::GroupStartIndexes starts(this);
   int start = starts.at(group);
   int end = starts.at(group + 1);
-  int number_of_entries = starts.at(DependentCode::kGroupCount);
+  int code_entries = starts.number_of_entries();
   if (start == end) return;
   for (int i = start; i < end; i++) {
-    Code* code = code_at(i);
-    code->set_marked_for_deoptimization(true);
+    if (is_code_at(i)) {
+      Code* code = code_at(i);
+      code->set_marked_for_deoptimization(true);
+    } else {
+      CompilationInfo* info = compilation_info_at(i);
+      info->AbortDueToDependentMap();
+    }
   }
   // Compact the array by moving all subsequent groups to fill in the new holes.
-  for (int src = end, dst = start; src < number_of_entries; src++, dst++) {
-    set_code_at(dst, code_at(src));
+  for (int src = end, dst = start; src < code_entries; src++, dst++) {
+    copy(src, dst);
   }
   // Now the holes are at the end of the array, zap them for heap-verifier.
   int removed = end - start;
-  for (int i = number_of_entries - removed; i < number_of_entries; i++) {
-    clear_code_at(i);
+  for (int i = code_entries - removed; i < code_entries; i++) {
+    clear_at(i);
   }
   set_number_of_entries(group, 0);
   DeoptimizeDependentCodeFilter filter;
@@ -12236,8 +12336,8 @@
         return payload->TransitionElementsKind(to_kind);
       }
     }
-  } else if (info->payload()->IsJSGlobalPropertyCell()) {
-    JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(info->payload());
+  } else if (info->payload()->IsCell()) {
+    Cell* cell = Cell::cast(info->payload());
     Object* cell_contents = cell->value();
     if (cell_contents->IsSmi()) {
       ElementsKind kind = static_cast<ElementsKind>(
@@ -15710,4 +15810,15 @@
   set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
 }
 
+
+Type* JSGlobalPropertyCell::type() {
+  return static_cast<Type*>(type_raw());
+}
+
+
+void JSGlobalPropertyCell::set_type(Type* type, WriteBarrierMode ignored) {
+  set_type_raw(type, ignored);
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/objects.h b/src/objects.h
index 1ee31b6..7771eb4 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -119,6 +119,8 @@
 //               - ExternalTwoByteInternalizedString
 //         - Symbol
 //       - HeapNumber
+//       - Cell
+//         - JSGlobalPropertyCell
 //       - Code
 //       - Map
 //       - Oddball
@@ -348,7 +350,8 @@
   V(MAP_TYPE)                                                                  \
   V(CODE_TYPE)                                                                 \
   V(ODDBALL_TYPE)                                                              \
-  V(JS_GLOBAL_PROPERTY_CELL_TYPE)                                              \
+  V(CELL_TYPE)                                                                 \
+  V(PROPERTY_CELL_TYPE)                                                        \
   V(BOX_TYPE)                                                                  \
                                                                                \
   V(HEAP_NUMBER_TYPE)                                                          \
@@ -669,7 +672,8 @@
   MAP_TYPE,
   CODE_TYPE,
   ODDBALL_TYPE,
-  JS_GLOBAL_PROPERTY_CELL_TYPE,
+  CELL_TYPE,
+  PROPERTY_CELL_TYPE,
   BOX_TYPE,
 
   // "Data", objects that cannot contain non-map-word pointers to heap
@@ -841,6 +845,7 @@
 class FixedArrayBase;
 class ObjectVisitor;
 class StringStream;
+class Type;
 
 struct ValueInfo : public Malloced {
   ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
@@ -1011,6 +1016,7 @@
   V(JSGlobalProxy)                             \
   V(UndetectableObject)                        \
   V(AccessCheckNeeded)                         \
+  V(Cell)                                      \
   V(JSGlobalPropertyCell)                      \
   V(ObjectHashTable)                           \
 
@@ -4378,6 +4384,7 @@
 
 
 // Forward declaration.
+class Cell;
 class JSGlobalPropertyCell;
 
 // TypeFeedbackCells is a fixed array used to hold the association between
@@ -4395,8 +4402,8 @@
   inline void SetAstId(int index, TypeFeedbackId id);
 
   // Accessors for global property cells holding the cache values.
-  inline JSGlobalPropertyCell* Cell(int index);
-  inline void SetCell(int index, JSGlobalPropertyCell* cell);
+  inline Cell* GetCell(int index);
+  inline void SetCell(int index, Cell* cell);
 
   // The object that indicates an uninitialized cache.
   static inline Handle<Object> UninitializedSentinel(Isolate* isolate);
@@ -4662,7 +4669,7 @@
   inline byte to_boolean_state();
 
   // [compare_nil]: For kind COMPARE_NIL_IC tells what state the stub is in.
-  byte compare_nil_types();
+  byte compare_nil_state();
 
   // [has_function_cache]: For kind STUB tells whether there is a function
   // cache is passed to the stub.
@@ -4825,6 +4832,7 @@
   void MakeOlder(MarkingParity);
   static bool IsYoungSequence(byte* sequence);
   bool IsOld();
+  int GetAge();
 
   void PrintDeoptLocation(int bailout_id);
 
@@ -4966,8 +4974,8 @@
 
   // Code aging
   byte* FindCodeAgeSequence();
-  static void  GetCodeAgeAndParity(Code* code, Age* age,
-                                   MarkingParity* parity);
+  static void GetCodeAgeAndParity(Code* code, Age* age,
+                                  MarkingParity* parity);
   static void GetCodeAgeAndParity(byte* sequence, Age* age,
                                   MarkingParity* parity);
   static Code* GetCodeAgeStub(Age age, MarkingParity parity);
@@ -4980,6 +4988,8 @@
 };
 
 
+class CompilationInfo;
+
 // This class describes the layout of dependent codes array of a map. The
 // array is partitioned into several groups of dependent codes. Each group
 // contains codes with the same dependency on the map. The array has the
@@ -5033,8 +5043,14 @@
 
   bool Contains(DependencyGroup group, Code* code);
   static Handle<DependentCode> Insert(Handle<DependentCode> entries,
-                                       DependencyGroup group,
-                                       Handle<Code> value);
+                                      DependencyGroup group,
+                                      Handle<Object> object);
+  void UpdateToFinishedCode(DependencyGroup group,
+                            CompilationInfo* info,
+                            Code* code);
+  void RemoveCompilationInfo(DependentCode::DependencyGroup group,
+                             CompilationInfo* info);
+
   void DeoptimizeDependentCodeGroup(Isolate* isolate,
                                     DependentCode::DependencyGroup group);
 
@@ -5042,10 +5058,14 @@
   // and the mark compact collector.
   inline int number_of_entries(DependencyGroup group);
   inline void set_number_of_entries(DependencyGroup group, int value);
+  inline bool is_code_at(int i);
   inline Code* code_at(int i);
-  inline void set_code_at(int i, Code* value);
-  inline Object** code_slot_at(int i);
-  inline void clear_code_at(int i);
+  inline CompilationInfo* compilation_info_at(int i);
+  inline void set_object_at(int i, Object* object);
+  inline Object** slot_at(int i);
+  inline Object* object_at(int i);
+  inline void clear_at(int i);
+  inline void copy(int from, int to);
   static inline DependentCode* cast(Object* object);
 
  private:
@@ -5388,7 +5408,7 @@
     set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
   }
 
-  inline JSGlobalPropertyCell* RetrieveDescriptorsPointer();
+  inline Cell* RetrieveDescriptorsPointer();
 
   int EnumLength() {
     return EnumLengthBits::decode(bit_field3());
@@ -5554,8 +5574,11 @@
 
   inline bool CanOmitPrototypeChecks();
 
-  inline void AddDependentCode(DependentCode::DependencyGroup group,
-                               Handle<Code> code);
+  void AddDependentCompilationInfo(DependentCode::DependencyGroup group,
+                                        CompilationInfo* info);
+
+  void AddDependentCode(DependentCode::DependencyGroup group,
+                        Handle<Code> code);
 
   bool IsMapInArrayPrototypeChain();
 
@@ -6565,8 +6588,6 @@
   // can be shared by instances.
   DECL_ACCESSORS(shared, SharedFunctionInfo)
 
-  inline SharedFunctionInfo* unchecked_shared();
-
   // [context]: The context for this function.
   inline Context* context();
   inline Object* unchecked_context();
@@ -8539,16 +8560,18 @@
 };
 
 
-class JSGlobalPropertyCell: public HeapObject {
+class Cell: public HeapObject {
  public:
   // [value]: value of the global property.
   DECL_ACCESSORS(value, Object)
 
   // Casting.
-  static inline JSGlobalPropertyCell* cast(Object* obj);
+  static inline Cell* cast(Object* obj);
 
-  static inline JSGlobalPropertyCell* FromValueAddress(Address value) {
-    return cast(FromAddress(value - kValueOffset));
+  static inline Cell* FromValueAddress(Address value) {
+    Object* result = FromAddress(value - kValueOffset);
+    ASSERT(result->IsCell() || result->IsJSGlobalPropertyCell());
+    return static_cast<Cell*>(result);
   }
 
   inline Address ValueAddress() {
@@ -8556,8 +8579,8 @@
   }
 
   // Dispatched behavior.
-  DECLARE_PRINTER(JSGlobalPropertyCell)
-  DECLARE_VERIFIER(JSGlobalPropertyCell)
+  DECLARE_PRINTER(Cell)
+  DECLARE_VERIFIER(Cell)
 
   // Layout description.
   static const int kValueOffset = HeapObject::kHeaderSize;
@@ -8568,6 +8591,37 @@
                               kSize> BodyDescriptor;
 
  private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Cell);
+};
+
+
+class JSGlobalPropertyCell: public Cell {
+ public:
+  Type* type();
+  void set_type(Type* value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
+
+  // Casting.
+  static inline JSGlobalPropertyCell* cast(Object* obj);
+
+  inline Address TypeAddress() {
+    return address() + kTypeOffset;
+  }
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(JSGlobalPropertyCell)
+  DECLARE_VERIFIER(JSGlobalPropertyCell)
+
+  // Layout description.
+  static const int kTypeOffset = kValueOffset + kPointerSize;
+  static const int kSize = kTypeOffset + kPointerSize;
+
+  typedef FixedBodyDescriptor<
+      kValueOffset,
+      kTypeOffset + kPointerSize,
+      JSGlobalPropertyCell::kSize> BodyDescriptor;
+
+ private:
+  DECL_ACCESSORS(type_raw, Object)
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
 };
 
@@ -9587,7 +9641,7 @@
   virtual void VisitCodeEntry(Address entry_address);
 
   // Visits a global property cell reference in the instruction stream.
-  virtual void VisitGlobalPropertyCell(RelocInfo* rinfo);
+  virtual void VisitCell(RelocInfo* rinfo);
 
   // Visits a runtime entry in the instruction stream.
   virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
diff --git a/src/parser.cc b/src/parser.cc
index fa24bf7..996d677 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2624,11 +2624,13 @@
 }
 
 
-bool Parser::CheckInOrOf(ForEachStatement::VisitMode* visit_mode) {
+bool Parser::CheckInOrOf(bool accept_OF,
+                         ForEachStatement::VisitMode* visit_mode) {
   if (Check(Token::IN)) {
     *visit_mode = ForEachStatement::ENUMERATE;
     return true;
-  } else if (allow_for_of() && CheckContextualKeyword(CStrVector("of"))) {
+  } else if (allow_for_of() && accept_OF &&
+             CheckContextualKeyword(CStrVector("of"))) {
     *visit_mode = ForEachStatement::ITERATE;
     return true;
   }
@@ -2726,11 +2728,14 @@
     if (peek() == Token::VAR || peek() == Token::CONST) {
       bool is_const = peek() == Token::CONST;
       Handle<String> name;
+      VariableDeclarationProperties decl_props = kHasNoInitializers;
       Block* variable_statement =
-          ParseVariableDeclarations(kForStatement, NULL, NULL, &name, CHECK_OK);
+          ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
+                                    CHECK_OK);
+      bool accept_OF = decl_props == kHasNoInitializers;
       ForEachStatement::VisitMode mode;
 
-      if (!name.is_null() && CheckInOrOf(&mode)) {
+      if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) {
         Interface* interface =
             is_const ? Interface::NewConst() : Interface::NewValue();
         ForEachStatement* loop = factory()->NewForEachStatement(mode, labels);
@@ -2762,9 +2767,10 @@
          ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
                                    CHECK_OK);
       bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
+      bool accept_OF = decl_props == kHasNoInitializers;
       ForEachStatement::VisitMode mode;
 
-      if (accept_IN && CheckInOrOf(&mode)) {
+      if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
         // Rewrite a for-in statement of the form
         //
         //   for (let x in e) b
@@ -2820,8 +2826,9 @@
     } else {
       Expression* expression = ParseExpression(false, CHECK_OK);
       ForEachStatement::VisitMode mode;
+      bool accept_OF = expression->AsVariableProxy();
 
-      if (CheckInOrOf(&mode)) {
+      if (CheckInOrOf(accept_OF, &mode)) {
         // Signal a reference error if the expression is an invalid
         // left-hand side expression.  We could report this as a syntax
         // error here but for compatibility with JSC we choose to report
diff --git a/src/parser.h b/src/parser.h
index b7e0700..38633b0 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -729,7 +729,7 @@
 
   bool is_generator() const { return current_function_state_->is_generator(); }
 
-  bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode);
+  bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode* visit_mode);
 
   bool peek_any_identifier();
 
diff --git a/src/preparser.cc b/src/preparser.cc
index 828177a..3268e3c 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -659,10 +659,9 @@
 }
 
 
-bool PreParser::CheckInOrOf() {
+bool PreParser::CheckInOrOf(bool accept_OF) {
   if (peek() == i::Token::IN ||
-      (allow_for_of() &&
-       peek() == i::Token::IDENTIFIER &&
+      (allow_for_of() && accept_OF && peek() == i::Token::IDENTIFIER &&
        scanner_->is_next_contextual_keyword(v8::internal::CStrVector("of")))) {
     Next();
     return true;
@@ -685,9 +684,10 @@
       VariableDeclarationProperties decl_props = kHasNoInitializers;
       ParseVariableDeclarations(
           kForStatement, &decl_props, &decl_count, CHECK_OK);
-      bool accept_IN = decl_count == 1 &&
-          !(is_let && decl_props == kHasInitializers);
-      if (accept_IN && CheckInOrOf()) {
+      bool has_initializers = decl_props == kHasInitializers;
+      bool accept_IN = decl_count == 1 && !(is_let && has_initializers);
+      bool accept_OF = !has_initializers;
+      if (accept_IN && CheckInOrOf(accept_OF)) {
         ParseExpression(true, CHECK_OK);
         Expect(i::Token::RPAREN, CHECK_OK);
 
@@ -695,8 +695,8 @@
         return Statement::Default();
       }
     } else {
-      ParseExpression(false, CHECK_OK);
-      if (CheckInOrOf()) {
+      Expression lhs = ParseExpression(false, CHECK_OK);
+      if (CheckInOrOf(lhs.IsIdentifier())) {
         ParseExpression(true, CHECK_OK);
         Expect(i::Token::RPAREN, CHECK_OK);
 
diff --git a/src/preparser.h b/src/preparser.h
index 786316e..41907d1 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -658,7 +658,7 @@
   }
   void ExpectSemicolon(bool* ok);
 
-  bool CheckInOrOf();
+  bool CheckInOrOf(bool accept_OF);
 
   static int Precedence(i::Token::Value tok, bool accept_IN);
 
diff --git a/src/runtime.cc b/src/runtime.cc
index eccf6ea..8711764 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -691,7 +691,7 @@
 
   array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
   isolate->heap()->set_array_buffers_list(*array_buffer);
-  array_buffer->set_weak_first_array(Smi::FromInt(0));
+  array_buffer->set_weak_first_array(isolate->heap()->undefined_value());
 }
 
 
@@ -8097,13 +8097,15 @@
 }
 
 
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WaitUntilOptimized) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_CompleteOptimization) {
   HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
-  if (FLAG_parallel_recompilation) {
-    if (V8::UseCrankshaft() && function->IsOptimizable()) {
-      while (!function->IsOptimized()) OS::Sleep(50);
+  if (FLAG_parallel_recompilation && V8::UseCrankshaft()) {
+    // While function is in optimization pipeline, it is marked with builtins.
+    while (function->code()->kind() == Code::BUILTIN) {
+      isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
+      OS::Sleep(50);
     }
   }
   return isolate->heap()->undefined_value();
@@ -13479,9 +13481,9 @@
   MaybeObject* maybe_array;
   if (!type_info.is_null() &&
       *type_info != isolate->heap()->undefined_value() &&
-      JSGlobalPropertyCell::cast(*type_info)->value()->IsSmi() &&
+      Cell::cast(*type_info)->value()->IsSmi() &&
       can_use_type_feedback) {
-    JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(*type_info);
+    Cell* cell = Cell::cast(*type_info);
     Smi* smi = Smi::cast(cell->value());
     ElementsKind to_kind = static_cast<ElementsKind>(smi->value());
     if (holey && !IsFastHoleyElementsKind(to_kind)) {
diff --git a/src/runtime.h b/src/runtime.h
index ef54016..c52bbe7 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -96,7 +96,7 @@
   F(ClearFunctionTypeFeedback, 1, 1) \
   F(RunningInSimulator, 0, 1) \
   F(OptimizeFunctionOnNextCall, -1, 1) \
-  F(WaitUntilOptimized, 1, 1) \
+  F(CompleteOptimization, 1, 1) \
   F(GetOptimizationStatus, 1, 1) \
   F(GetOptimizationCount, 1, 1) \
   F(CompileForOnStackReplacement, 1, 1) \
diff --git a/src/serialize.cc b/src/serialize.cc
index 6c5ccea..4e51cd3 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -687,6 +687,8 @@
 
   isolate_->heap()->set_native_contexts_list(
       isolate_->heap()->undefined_value());
+  isolate_->heap()->set_array_buffers_list(
+      isolate_->heap()->undefined_value());
 
   // Update data pointers to the external strings containing natives sources.
   for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
@@ -776,6 +778,7 @@
   bool write_barrier_needed = (current_object_address != NULL &&
                                source_space != NEW_SPACE &&
                                source_space != CELL_SPACE &&
+                               source_space != PROPERTY_CELL_SPACE &&
                                source_space != CODE_SPACE &&
                                source_space != OLD_DATA_SPACE);
   while (current < limit) {
@@ -836,8 +839,7 @@
                   new_code_object->instruction_start());                       \
             } else {                                                           \
               ASSERT(space_number == CODE_SPACE);                              \
-              JSGlobalPropertyCell* cell =                                     \
-                  JSGlobalPropertyCell::cast(new_object);                      \
+              Cell* cell = Cell::cast(new_object);                             \
               new_object = reinterpret_cast<Object*>(                          \
                   cell->ValueAddress());                                       \
             }                                                                  \
@@ -877,6 +879,7 @@
   CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE)                        \
   CASE_STATEMENT(where, how, within, CODE_SPACE)                               \
   CASE_STATEMENT(where, how, within, CELL_SPACE)                               \
+  CASE_STATEMENT(where, how, within, PROPERTY_CELL_SPACE)                      \
   CASE_STATEMENT(where, how, within, MAP_SPACE)                                \
   CASE_BODY(where, how, within, kAnyOldSpace)
 
@@ -1564,10 +1567,9 @@
 }
 
 
-void Serializer::ObjectSerializer::VisitGlobalPropertyCell(RelocInfo* rinfo) {
-  ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
-  JSGlobalPropertyCell* cell =
-      JSGlobalPropertyCell::cast(rinfo->target_cell());
+void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) {
+  ASSERT(rinfo->rmode() == RelocInfo::CELL);
+  Cell* cell = Cell::cast(rinfo->target_cell());
   int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping);
   serializer_->SerializeObject(cell, kPlain, kInnerPointer, skip);
 }
diff --git a/src/serialize.h b/src/serialize.h
index 1b56a88..e5664ff 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -519,7 +519,7 @@
     void VisitExternalReference(RelocInfo* rinfo);
     void VisitCodeTarget(RelocInfo* target);
     void VisitCodeEntry(Address entry_address);
-    void VisitGlobalPropertyCell(RelocInfo* rinfo);
+    void VisitCell(RelocInfo* rinfo);
     void VisitRuntimeEntry(RelocInfo* reloc);
     // Used for seralizing the external strings that hold the natives source.
     void VisitExternalAsciiString(
diff --git a/src/snapshot-common.cc b/src/snapshot-common.cc
index a8806f0..576269d 100644
--- a/src/snapshot-common.cc
+++ b/src/snapshot-common.cc
@@ -45,7 +45,8 @@
   OS::SNPrintF(name, "%s.size", file_name);
   FILE* fp = OS::FOpen(name.start(), "r");
   CHECK_NE(NULL, fp);
-  int new_size, pointer_size, data_size, code_size, map_size, cell_size;
+  int new_size, pointer_size, data_size, code_size, map_size, cell_size,
+      property_cell_size;
 #ifdef _MSC_VER
   // Avoid warning about unsafe fscanf from MSVC.
   // Please note that this is only fine if %c and %s are not being used.
@@ -57,6 +58,7 @@
   CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
   CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
   CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
+  CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
 #ifdef _MSC_VER
 #undef fscanf
 #endif
@@ -67,6 +69,8 @@
   deserializer->set_reservation(CODE_SPACE, code_size);
   deserializer->set_reservation(MAP_SPACE, map_size);
   deserializer->set_reservation(CELL_SPACE, cell_size);
+  deserializer->set_reservation(PROPERTY_CELL_SPACE,
+                                property_cell_size);
   name.Dispose();
 }
 
@@ -78,6 +82,8 @@
   deserializer->set_reservation(CODE_SPACE, code_space_used_);
   deserializer->set_reservation(MAP_SPACE, map_space_used_);
   deserializer->set_reservation(CELL_SPACE, cell_space_used_);
+  deserializer->set_reservation(PROPERTY_CELL_SPACE,
+                                property_cell_space_used_);
 }
 
 
@@ -124,6 +130,8 @@
   deserializer.set_reservation(CODE_SPACE, context_code_space_used_);
   deserializer.set_reservation(MAP_SPACE, context_map_space_used_);
   deserializer.set_reservation(CELL_SPACE, context_cell_space_used_);
+  deserializer.set_reservation(PROPERTY_CELL_SPACE,
+                               context_property_cell_space_used_);
   deserializer.DeserializePartial(&root);
   CHECK(root->IsContext());
   return Handle<Context>(Context::cast(root));
diff --git a/src/snapshot-empty.cc b/src/snapshot-empty.cc
index 70e7ab8..54236d8 100644
--- a/src/snapshot-empty.cc
+++ b/src/snapshot-empty.cc
@@ -49,6 +49,7 @@
 const int Snapshot::code_space_used_ = 0;
 const int Snapshot::map_space_used_ = 0;
 const int Snapshot::cell_space_used_ = 0;
+const int Snapshot::property_cell_space_used_ = 0;
 
 const int Snapshot::context_new_space_used_ = 0;
 const int Snapshot::context_pointer_space_used_ = 0;
@@ -56,5 +57,6 @@
 const int Snapshot::context_code_space_used_ = 0;
 const int Snapshot::context_map_space_used_ = 0;
 const int Snapshot::context_cell_space_used_ = 0;
+const int Snapshot::context_property_cell_space_used_ = 0;
 
 } }  // namespace v8::internal
diff --git a/src/snapshot.h b/src/snapshot.h
index c4ae45e..149306e 100644
--- a/src/snapshot.h
+++ b/src/snapshot.h
@@ -77,12 +77,14 @@
   static const int code_space_used_;
   static const int map_space_used_;
   static const int cell_space_used_;
+  static const int property_cell_space_used_;
   static const int context_new_space_used_;
   static const int context_pointer_space_used_;
   static const int context_data_space_used_;
   static const int context_code_space_used_;
   static const int context_map_space_used_;
   static const int context_cell_space_used_;
+  static const int context_property_cell_space_used_;
   static const int size_;
   static const int raw_size_;
   static const int context_size_;
diff --git a/src/spaces.cc b/src/spaces.cc
index 099ad93..8e953e2 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -72,6 +72,7 @@
          owner == page->heap()->old_data_space() ||
          owner == page->heap()->map_space() ||
          owner == page->heap()->cell_space() ||
+         owner == page->heap()->property_cell_space() ||
          owner == page->heap()->code_space());
   Initialize(reinterpret_cast<PagedSpace*>(owner),
              page->area_start(),
@@ -1043,6 +1044,9 @@
     case CELL_SPACE:
       size = 16 * kPointerSize * KB;
       break;
+    case PROPERTY_CELL_SPACE:
+      size = 16 * kPointerSize * KB;
+      break;
     case CODE_SPACE:
       if (heap()->isolate()->code_range()->exists()) {
         // When code range exists, code pages are allocated in a special way
@@ -2834,13 +2838,20 @@
 
 
 // -----------------------------------------------------------------------------
-// GlobalPropertyCellSpace implementation
+// CellSpace and PropertyCellSpace implementation
 // TODO(mvstanton): this is weird...the compiler can't make a vtable unless
 // there is at least one non-inlined virtual function. I would prefer to hide
 // the VerifyObject definition behind VERIFY_HEAP.
 
 void CellSpace::VerifyObject(HeapObject* object) {
   // The object should be a global object property cell or a free-list node.
+  CHECK(object->IsCell() ||
+         object->map() == heap()->two_pointer_filler_map());
+}
+
+
+void PropertyCellSpace::VerifyObject(HeapObject* object) {
+  // The object should be a global object property cell or a free-list node.
   CHECK(object->IsJSGlobalPropertyCell() ||
          object->map() == heap()->two_pointer_filler_map());
 }
diff --git a/src/spaces.h b/src/spaces.h
index e7e4d52..ca61081 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -2626,12 +2626,39 @@
 
 
 // -----------------------------------------------------------------------------
-// Old space for all global object property cell objects
+// Old space for simple property cell objects
 
 class CellSpace : public FixedSpace {
  public:
   // Creates a property cell space object with a maximum capacity.
   CellSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id)
+      : FixedSpace(heap, max_capacity, id, Cell::kSize)
+  {}
+
+  virtual int RoundSizeDownToObjectAlignment(int size) {
+    if (IsPowerOf2(Cell::kSize)) {
+      return RoundDown(size, Cell::kSize);
+    } else {
+      return (size / Cell::kSize) * Cell::kSize;
+    }
+  }
+
+ protected:
+  virtual void VerifyObject(HeapObject* obj);
+
+ public:
+  TRACK_MEMORY("CellSpace")
+};
+
+
+// -----------------------------------------------------------------------------
+// Old space for all global object property cell objects
+
+class PropertyCellSpace : public FixedSpace {
+ public:
+  // Creates a property cell space object with a maximum capacity.
+  PropertyCellSpace(Heap* heap, intptr_t max_capacity,
+                    AllocationSpace id)
       : FixedSpace(heap, max_capacity, id, JSGlobalPropertyCell::kSize)
   {}
 
@@ -2647,7 +2674,7 @@
   virtual void VerifyObject(HeapObject* obj);
 
  public:
-  TRACK_MEMORY("CellSpace")
+  TRACK_MEMORY("PropertyCellSpace")
 };
 
 
diff --git a/src/store-buffer.cc b/src/store-buffer.cc
index c650f57..fd6366a 100644
--- a/src/store-buffer.cc
+++ b/src/store-buffer.cc
@@ -142,6 +142,11 @@
 }
 
 
+bool StoreBuffer::SpaceAvailable(intptr_t space_needed) {
+  return old_limit_ - old_top_ >= space_needed;
+}
+
+
 void StoreBuffer::EnsureSpace(intptr_t space_needed) {
   while (old_limit_ - old_top_ < space_needed &&
          old_limit_ < old_reserved_limit_) {
@@ -152,7 +157,7 @@
     old_limit_ += grow;
   }
 
-  if (old_limit_ - old_top_ >= space_needed) return;
+  if (SpaceAvailable(space_needed)) return;
 
   if (old_buffer_is_filtered_) return;
   ASSERT(may_move_store_buffer_entries_);
@@ -171,9 +176,7 @@
     Filter(MemoryChunk::SCAN_ON_SCAVENGE);
   }
 
-  // If filtering out the entries from scan_on_scavenge pages got us down to
-  // less than half full, then we are satisfied with that.
-  if (old_limit_ - old_top_ > old_top_ - old_start_) return;
+  if (SpaceAvailable(space_needed)) return;
 
   // Sample 1 entry in 97 and filter out the pages where we estimate that more
   // than 1 in 8 pointers are to new space.
@@ -192,7 +195,7 @@
     ExemptPopularPages(samples[i].prime_sample_step, samples[i].threshold);
     // As a last resort we mark all pages as being exempt from the store buffer.
     ASSERT(i != (kSampleFinenesses - 1) || old_top_ == old_start_);
-    if (old_limit_ - old_top_ > old_top_ - old_start_) return;
+    if (SpaceAvailable(space_needed)) return;
   }
   UNREACHABLE();
 }
@@ -294,7 +297,7 @@
 void StoreBuffer::Clean() {
   ClearFilteringHashSets();
   Uniq();  // Also removes things that no longer point to new space.
-  CheckForFullBuffer();
+  EnsureSpace(kStoreBufferSize / 2);
 }
 
 
@@ -687,12 +690,6 @@
     ASSERT(old_top_ <= old_limit_);
   }
   heap_->isolate()->counters()->store_buffer_compactions()->Increment();
-  CheckForFullBuffer();
-}
-
-
-void StoreBuffer::CheckForFullBuffer() {
-  EnsureSpace(kStoreBufferSize * 2);
 }
 
 } }  // namespace v8::internal
diff --git a/src/store-buffer.h b/src/store-buffer.h
index 514534a..520cbc0 100644
--- a/src/store-buffer.h
+++ b/src/store-buffer.h
@@ -160,7 +160,7 @@
 
   void ClearFilteringHashSets();
 
-  void CheckForFullBuffer();
+  bool SpaceAvailable(intptr_t space_needed);
   void Uniq();
   void ExemptPopularPages(int prime_sample_step, int threshold);
 
@@ -223,7 +223,6 @@
   ~StoreBufferRebuildScope() {
     store_buffer_->callback_ = stored_callback_;
     store_buffer_->store_buffer_rebuilding_enabled_ = stored_state_;
-    store_buffer_->CheckForFullBuffer();
   }
 
  private:
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 0f81669..40a7938 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -1977,7 +1977,7 @@
 Handle<Code> CallStubCompiler::CompileCustomCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> fname) {
   ASSERT(HasCustomCallGenerator(function));
diff --git a/src/stub-cache.h b/src/stub-cache.h
index a1b55d8..0c756a1 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -1019,14 +1019,14 @@
   // given function.
   Handle<Code> CompileCustomCall(Handle<Object> object,
                                  Handle<JSObject> holder,
-                                 Handle<JSGlobalPropertyCell> cell,
+                                 Handle<Cell> cell,
                                  Handle<JSFunction> function,
                                  Handle<String> name);
 
 #define DECLARE_CALL_GENERATOR(name)                                    \
   Handle<Code> Compile##name##Call(Handle<Object> object,               \
                                    Handle<JSObject> holder,             \
-                                   Handle<JSGlobalPropertyCell> cell,   \
+                                   Handle<Cell> cell,                   \
                                    Handle<JSFunction> function,         \
                                    Handle<String> fname);
   CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
@@ -1035,7 +1035,7 @@
   Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
                                   Handle<Object> object,
                                   Handle<JSObject> holder,
-                                  Handle<JSGlobalPropertyCell> cell,
+                                  Handle<Cell> cell,
                                   Handle<JSFunction> function,
                                   Handle<String> name);
 
@@ -1053,7 +1053,7 @@
 
   // Generates code to load the function from the cell checking that
   // it still contains the same function.
-  void GenerateLoadFunctionFromCell(Handle<JSGlobalPropertyCell> cell,
+  void GenerateLoadFunctionFromCell(Handle<Cell> cell,
                                     Handle<JSFunction> function,
                                     Label* miss);
 
diff --git a/src/type-info.cc b/src/type-info.cc
index 5113c55..32aef1c 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -42,20 +42,17 @@
 namespace internal {
 
 
-TypeInfo TypeInfo::TypeFromValue(Handle<Object> value) {
-  TypeInfo info;
+TypeInfo TypeInfo::FromValue(Handle<Object> value) {
   if (value->IsSmi()) {
-    info = TypeInfo::Smi();
+    return TypeInfo::Smi();
   } else if (value->IsHeapNumber()) {
-    info = TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value())
+    return TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value())
         ? TypeInfo::Integer32()
         : TypeInfo::Double();
   } else if (value->IsString()) {
-    info = TypeInfo::String();
-  } else {
-    info = TypeInfo::Unknown();
+    return TypeInfo::String();
   }
-  return info;
+  return TypeInfo::Unknown();
 }
 
 
@@ -80,8 +77,8 @@
   int entry = dictionary_->FindEntry(IdToKey(ast_id));
   if (entry != UnseededNumberDictionary::kNotFound) {
     Object* value = dictionary_->ValueAt(entry);
-    if (value->IsJSGlobalPropertyCell()) {
-      JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(value);
+    if (value->IsCell()) {
+      Cell* cell = Cell::cast(value);
       return Handle<Object>(cell->value(), isolate_);
     } else {
       return Handle<Object>(value, isolate_);
@@ -91,15 +88,14 @@
 }
 
 
-Handle<JSGlobalPropertyCell> TypeFeedbackOracle::GetInfoCell(
+Handle<Cell> TypeFeedbackOracle::GetInfoCell(
     TypeFeedbackId ast_id) {
   int entry = dictionary_->FindEntry(IdToKey(ast_id));
   if (entry != UnseededNumberDictionary::kNotFound) {
-    JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
-        dictionary_->ValueAt(entry));
-    return Handle<JSGlobalPropertyCell>(cell, isolate_);
+    Cell* cell = Cell::cast(dictionary_->ValueAt(entry));
+    return Handle<Cell>(cell, isolate_);
   }
-  return Handle<JSGlobalPropertyCell>::null();
+  return Handle<Cell>::null();
 }
 
 
@@ -235,24 +231,6 @@
 }
 
 
-Handle<Map> TypeFeedbackOracle::CompareNilMonomorphicReceiverType(
-    CompareOperation* expr) {
-  Handle<Object> maybe_code = GetInfo(expr->CompareOperationFeedbackId());
-  if (maybe_code->IsCode()) {
-    Map* map = Handle<Code>::cast(maybe_code)->FindFirstMap();
-    if (map == NULL) return Handle<Map>();
-    map = map->CurrentMapForDeprecated();
-    return map == NULL || CanRetainOtherContext(map, *native_context_)
-           ? Handle<Map>()
-           : Handle<Map>(map);
-  } else if (maybe_code->IsMap()) {
-    ASSERT(!Handle<Map>::cast(maybe_code)->is_deprecated());
-    return Handle<Map>::cast(maybe_code);
-  }
-  return Handle<Map>();
-}
-
-
 KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode(
     TypeFeedbackId ast_id) {
   Handle<Object> map_or_code = GetInfo(ast_id);
@@ -335,8 +313,7 @@
 }
 
 
-Handle<JSGlobalPropertyCell> TypeFeedbackOracle::GetCallNewAllocationInfoCell(
-    CallNew* expr) {
+Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell(CallNew* expr) {
   return GetInfoCell(expr->CallNewFeedbackId());
 }
 
@@ -364,69 +341,38 @@
 }
 
 
-static TypeInfo TypeFromCompareType(CompareIC::State state) {
-  switch (state) {
-    case CompareIC::UNINITIALIZED:
-      // Uninitialized means never executed.
-      return TypeInfo::Uninitialized();
-    case CompareIC::SMI:
-      return TypeInfo::Smi();
-    case CompareIC::NUMBER:
-      return TypeInfo::Number();
-    case CompareIC::INTERNALIZED_STRING:
-      return TypeInfo::InternalizedString();
-    case CompareIC::STRING:
-      return TypeInfo::String();
-    case CompareIC::OBJECT:
-    case CompareIC::KNOWN_OBJECT:
-      // TODO(kasperl): We really need a type for JS objects here.
-      return TypeInfo::NonPrimitive();
-    case CompareIC::GENERIC:
-    default:
-      return TypeInfo::Unknown();
-  }
-}
+void TypeFeedbackOracle::CompareTypes(TypeFeedbackId id,
+                                      Handle<Type>* left_type,
+                                      Handle<Type>* right_type,
+                                      Handle<Type>* overall_type,
+                                      Handle<Type>* compare_nil_type) {
+  *left_type = *right_type = *overall_type = *compare_nil_type =
+      handle(Type::Any(), isolate_);
+  Handle<Object> info = GetInfo(id);
+  if (!info->IsCode()) return;
+  Handle<Code> code = Handle<Code>::cast(info);
 
-
-void TypeFeedbackOracle::CompareType(CompareOperation* expr,
-                                     TypeInfo* left_type,
-                                     TypeInfo* right_type,
-                                     TypeInfo* overall_type) {
-  Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
-  TypeInfo unknown = TypeInfo::Unknown();
-  if (!object->IsCode()) {
-    *left_type = *right_type = *overall_type = unknown;
-    return;
-  }
-  Handle<Code> code = Handle<Code>::cast(object);
-  if (!code->is_compare_ic_stub()) {
-    *left_type = *right_type = *overall_type = unknown;
-    return;
+  Handle<Map> map;
+  Map* raw_map = code->FindFirstMap();
+  if (raw_map != NULL) {
+    raw_map = raw_map->CurrentMapForDeprecated();
+    if (!CanRetainOtherContext(raw_map, *native_context_)) {
+      map = handle(raw_map, isolate_);
+    }
   }
 
-  int stub_minor_key = code->stub_info();
-  CompareIC::State left_state, right_state, handler_state;
-  ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
-                                &handler_state, NULL);
-  *left_type = TypeFromCompareType(left_state);
-  *right_type = TypeFromCompareType(right_state);
-  *overall_type = TypeFromCompareType(handler_state);
-}
-
-
-Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) {
-  Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
-  if (!object->IsCode()) return Handle<Map>::null();
-  Handle<Code> code = Handle<Code>::cast(object);
-  if (!code->is_compare_ic_stub()) return Handle<Map>::null();
-  CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
-  if (state != CompareIC::KNOWN_OBJECT) {
-    return Handle<Map>::null();
+  if (code->is_compare_ic_stub()) {
+    int stub_minor_key = code->stub_info();
+    CompareIC::State left_state, right_state, handler_state;
+    ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
+                                  &handler_state, NULL);
+    *left_type = CompareIC::StateToType(isolate_, left_state);
+    *right_type = CompareIC::StateToType(isolate_, right_state);
+    *overall_type = CompareIC::StateToType(isolate_, handler_state, map);
+  } else if (code->is_compare_nil_ic_stub()) {
+    CompareNilICStub::State state(code->compare_nil_state());
+    *compare_nil_type = CompareNilICStub::StateToType(isolate_, state, map);
   }
-  Map* map = code->FindFirstMap()->CurrentMapForDeprecated();
-  return map == NULL || CanRetainOtherContext(map, *native_context_)
-      ? Handle<Map>::null()
-      : Handle<Map>(map);
 }
 
 
@@ -497,15 +443,15 @@
 }
 
 
-TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
-  Handle<Object> object = GetInfo(clause->CompareId());
-  TypeInfo unknown = TypeInfo::Unknown();
-  if (!object->IsCode()) return unknown;
-  Handle<Code> code = Handle<Code>::cast(object);
-  if (!code->is_compare_ic_stub()) return unknown;
-
-  CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
-  return TypeFromCompareType(state);
+Handle<Type> TypeFeedbackOracle::ClauseType(TypeFeedbackId id) {
+  Handle<Object> info = GetInfo(id);
+  Handle<Type> result(Type::None(), isolate_);
+  if (info->IsCode() && Handle<Code>::cast(info)->is_compare_ic_stub()) {
+    Handle<Code> code = Handle<Code>::cast(info);
+    CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
+    result = CompareIC::StateToType(isolate_, state);
+  }
+  return result;
 }
 
 
@@ -636,17 +582,6 @@
 }
 
 
-byte TypeFeedbackOracle::CompareNilTypes(CompareOperation* expr) {
-  Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
-  if (object->IsCode() &&
-      Handle<Code>::cast(object)->is_compare_nil_ic_stub()) {
-    return Handle<Code>::cast(object)->compare_nil_types();
-  } else {
-    return CompareNilICStub::Types::FullCompare().ToIntegral();
-  }
-}
-
-
 // Things are a bit tricky here: The iterator for the RelocInfos and the infos
 // themselves are not GC-safe, so we first get all infos, then we create the
 // dictionary (possibly triggering GC), and finally we relocate the collected
@@ -759,7 +694,7 @@
       TypeFeedbackInfo::cast(raw_info)->type_feedback_cells());
   for (int i = 0; i < cache->CellCount(); i++) {
     TypeFeedbackId ast_id = cache->AstId(i);
-    JSGlobalPropertyCell* cell = cache->Cell(i);
+    Cell* cell = cache->GetCell(i);
     Object* value = cell->value();
     if (value->IsSmi() ||
         (value->IsJSFunction() &&
diff --git a/src/type-info.h b/src/type-info.h
index 53a83be..1262b31 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -30,6 +30,7 @@
 
 #include "allocation.h"
 #include "globals.h"
+#include "types.h"
 #include "zone-inl.h"
 
 namespace v8 {
@@ -113,7 +114,7 @@
     return false;
   }
 
-  static TypeInfo TypeFromValue(Handle<Object> value);
+  static TypeInfo FromValue(Handle<Object> value);
 
   bool Equals(const TypeInfo& other) {
     return type_ == other.type_;
@@ -217,12 +218,12 @@
 
 
 // Forward declarations.
+// TODO(rossberg): these should all go away eventually.
 class Assignment;
 class BinaryOperation;
 class Call;
 class CallNew;
 class CaseClause;
-class CompareOperation;
 class CompilationInfo;
 class CountOperation;
 class Expression;
@@ -257,7 +258,6 @@
 
   Handle<Map> LoadMonomorphicReceiverType(Property* expr);
   Handle<Map> StoreMonomorphicReceiverType(TypeFeedbackId id);
-  Handle<Map> CompareNilMonomorphicReceiverType(CompareOperation* expr);
 
   KeyedAccessStoreMode GetStoreMode(TypeFeedbackId ast_id);
 
@@ -283,7 +283,7 @@
   CheckType GetCallCheckType(Call* expr);
   Handle<JSFunction> GetCallTarget(Call* expr);
   Handle<JSFunction> GetCallNewTarget(CallNew* expr);
-  Handle<JSGlobalPropertyCell> GetCallNewAllocationInfoCell(CallNew* expr);
+  Handle<Cell> GetCallNewAllocationInfoCell(CallNew* expr);
 
   Handle<Map> GetObjectLiteralStoreMap(ObjectLiteralProperty* prop);
 
@@ -293,12 +293,7 @@
   // TODO(1571) We can't use ToBooleanStub::Types as the return value because
   // of various cycles in our headers. Death to tons of implementations in
   // headers!! :-P
-  byte ToBooleanTypes(TypeFeedbackId ast_id);
-
-  // TODO(1571) We can't use CompareNilICStub::Types as the return value because
-  // of various cylces in our headers. Death to tons of implementations in
-  // headers!! :-P
-  byte CompareNilTypes(CompareOperation* expr);
+  byte ToBooleanTypes(TypeFeedbackId id);
 
   // Get type information for arithmetic operations and compares.
   TypeInfo UnaryType(UnaryOperation* expr);
@@ -308,12 +303,15 @@
                   TypeInfo* result,
                   bool* has_fixed_right_arg,
                   int* fixed_right_arg_value);
-  void CompareType(CompareOperation* expr,
-                   TypeInfo* left_type,
-                   TypeInfo* right_type,
-                   TypeInfo* overall_type);
-  Handle<Map> GetCompareMap(CompareOperation* expr);
-  TypeInfo SwitchType(CaseClause* clause);
+
+  void CompareTypes(TypeFeedbackId id,
+                    Handle<Type>* left_type,
+                    Handle<Type>* right_type,
+                    Handle<Type>* overall_type,
+                    Handle<Type>* compare_nil_type);
+
+  Handle<Type> ClauseType(TypeFeedbackId id);
+
   TypeInfo IncrementType(CountOperation* expr);
 
   Zone* zone() const { return zone_; }
@@ -341,7 +339,7 @@
   Handle<Object> GetInfo(TypeFeedbackId ast_id);
 
   // Return the cell that contains type feedback.
-  Handle<JSGlobalPropertyCell> GetInfoCell(TypeFeedbackId ast_id);
+  Handle<Cell> GetInfoCell(TypeFeedbackId ast_id);
 
  private:
   Handle<Context> native_context_;
diff --git a/src/types.cc b/src/types.cc
index f7fbd2d..20e8a4c 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -30,6 +30,84 @@
 namespace v8 {
 namespace internal {
 
+int Type::NumClasses() {
+  if (is_class()) {
+    return 1;
+  } else if (is_union()) {
+    Handle<Unioned> unioned = as_union();
+    int result = 0;
+    for (int i = 0; i < unioned->length(); ++i) {
+      if (union_get(unioned, i)->is_class()) ++result;
+    }
+    return result;
+  } else {
+    return 0;
+  }
+}
+
+
+int Type::NumConstants() {
+  if (is_constant()) {
+    return 1;
+  } else if (is_union()) {
+    Handle<Unioned> unioned = as_union();
+    int result = 0;
+    for (int i = 0; i < unioned->length(); ++i) {
+      if (union_get(unioned, i)->is_constant()) ++result;
+    }
+    return result;
+  } else {
+    return 0;
+  }
+}
+
+
+template<class T>
+Handle<Type> Type::Iterator<T>::get_type() {
+  ASSERT(!Done());
+  return type_->is_union() ? union_get(type_->as_union(), index_) : type_;
+}
+
+template<>
+Handle<Map> Type::Iterator<Map>::Current() {
+  return get_type()->as_class();
+}
+
+template<>
+Handle<v8::internal::Object> Type::Iterator<v8::internal::Object>::Current() {
+  return get_type()->as_constant();
+}
+
+
+template<>
+bool Type::Iterator<Map>::matches(Handle<Type> type) {
+  return type->is_class();
+}
+
+template<>
+bool Type::Iterator<v8::internal::Object>::matches(Handle<Type> type) {
+  return type->is_constant();
+}
+
+
+template<class T>
+void Type::Iterator<T>::Advance() {
+  ++index_;
+  if (type_->is_union()) {
+    Handle<Unioned> unioned = type_->as_union();
+    for (; index_ < unioned->length(); ++index_) {
+      if (matches(union_get(unioned, index_))) return;
+    }
+  } else if (index_ == 0 && matches(type_)) {
+    return;
+  }
+  index_ = -1;
+}
+
+template class Type::Iterator<Map>;
+template class Type::Iterator<v8::internal::Object>;
+
+
 // Get the smallest bitset subsuming this type.
 int Type::LubBitset() {
   if (this->is_bitset()) {
@@ -46,9 +124,14 @@
     if (this->is_class()) {
       map = *this->as_class();
     } else {
-      v8::internal::Object* value = this->as_constant()->value();
-      if (value->IsSmi()) return kSmi;
-      map = HeapObject::cast(value)->map();
+      Handle<v8::internal::Object> value = this->as_constant();
+      if (value->IsSmi()) return kInteger31;
+      map = HeapObject::cast(*value)->map();
+      if (map->instance_type() == ODDBALL_TYPE) {
+        if (value->IsUndefined()) return kUndefined;
+        if (value->IsNull()) return kNull;
+        if (value->IsTrue() || value->IsFalse()) return kBoolean;
+      }
     }
     switch (map->instance_type()) {
       case STRING_TYPE:
@@ -56,6 +139,7 @@
       case CONS_STRING_TYPE:
       case CONS_ASCII_STRING_TYPE:
       case SLICED_STRING_TYPE:
+      case SLICED_ASCII_STRING_TYPE:
       case EXTERNAL_STRING_TYPE:
       case EXTERNAL_ASCII_STRING_TYPE:
       case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
@@ -92,6 +176,7 @@
       case JS_TYPED_ARRAY_TYPE:
       case JS_WEAK_MAP_TYPE:
       case JS_REGEXP_TYPE:
+        if (map->is_undetectable()) return kUndetectable;
         return kOtherObject;
       case JS_ARRAY_TYPE:
         return kArray;
@@ -100,6 +185,17 @@
       case JS_PROXY_TYPE:
       case JS_FUNCTION_PROXY_TYPE:
         return kProxy;
+      case MAP_TYPE:
+        // When compiling stub templates, the meta map is used as a place holder
+        // for the actual map with which the template is later instantiated.
+        // We treat it as a kind of type variable whose upper bound is Any.
+        // TODO(rossberg): for caching of CompareNilIC stubs to work correctly,
+        // we must exclude Undetectable here. This makes no sense, really,
+        // because it means that the template isn't actually parametric.
+        // Also, it doesn't apply elsewhere. 8-(
+        // We ought to find a cleaner solution for compiling stubs parameterised
+        // over type or class variables, esp ones with bounds...
+        return kDetectable;
       default:
         UNREACHABLE();
         return kNone;
@@ -122,7 +218,7 @@
 
 
 // Check this <= that.
-bool Type::Is(Handle<Type> that) {
+bool Type::Is(Type* that) {
   // Fast path for bitsets.
   if (that->is_bitset()) {
     return (this->LubBitset() | that->as_bitset()) == that->as_bitset();
@@ -132,8 +228,7 @@
     return this->is_class() && *this->as_class() == *that->as_class();
   }
   if (that->is_constant()) {
-    return this->is_constant() &&
-        this->as_constant()->value() == that->as_constant()->value();
+    return this->is_constant() && *this->as_constant() == *that->as_constant();
   }
 
   // (T1 \/ ... \/ Tn) <= T  <=>  (T1 <= T) /\ ... /\ (Tn <= T)
@@ -163,7 +258,7 @@
 
 
 // Check this overlaps that.
-bool Type::Maybe(Handle<Type> that) {
+bool Type::Maybe(Type* that) {
   // Fast path for bitsets.
   if (this->is_bitset()) {
     return (this->as_bitset() & that->LubBitset()) != 0;
@@ -176,8 +271,7 @@
     return that->is_class() && *this->as_class() == *that->as_class();
   }
   if (this->is_constant()) {
-    return that->is_constant() &&
-        this->as_constant()->value() == that->as_constant()->value();
+    return that->is_constant() && *this->as_constant() == *that->as_constant();
   }
 
   // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
diff --git a/src/types.h b/src/types.h
index 6db9bfb..883d884 100644
--- a/src/types.h
+++ b/src/types.h
@@ -48,11 +48,15 @@
 //   T <= Any
 //
 //   Oddball = Boolean \/ Null \/ Undefined
-//   Number = Smi \/ Double
+//   Number = Integer32 \/ Double
+//   Integer31 < Integer32
 //   Name = String \/ Symbol
 //   UniqueName = InternalizedString \/ Symbol
 //   InternalizedString < String
 //
+//   Allocated = Receiver \/ Number \/ Name
+//   Detectable = Allocated - Undetectable
+//   Undetectable < Object
 //   Receiver = Object \/ Proxy
 //   Array < Object
 //   Function < Object
@@ -70,8 +74,9 @@
 //   T1->Is(T2)     -- tests whether T1 is included in T2 (i.e., T1 <= T2)
 //   T1->Maybe(T2)  -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0)
 //
-// Typically, the latter should be used to check whether a specific case needs
-// handling (e.g., via T->Maybe(Number)).
+// Typically, the former is to be used to select representations (e.g., via
+// T->Is(Integer31())), and the to check whether a specific case needs handling
+// (e.g., via T->Maybe(Number())).
 //
 // There is no functionality to discover whether a type is a leaf in the
 // lattice. That is intentional. It should always be possible to refine the
@@ -89,6 +94,8 @@
  public:
   static Type* None() { return from_bitset(kNone); }
   static Type* Any() { return from_bitset(kAny); }
+  static Type* Allocated() { return from_bitset(kAllocated); }
+  static Type* Detectable() { return from_bitset(kDetectable); }
 
   static Type* Oddball() { return from_bitset(kOddball); }
   static Type* Boolean() { return from_bitset(kBoolean); }
@@ -96,7 +103,8 @@
   static Type* Undefined() { return from_bitset(kUndefined); }
 
   static Type* Number() { return from_bitset(kNumber); }
-  static Type* Smi() { return from_bitset(kSmi); }
+  static Type* Integer31() { return from_bitset(kInteger31); }
+  static Type* Integer32() { return from_bitset(kInteger32); }
   static Type* Double() { return from_bitset(kDouble); }
 
   static Type* Name() { return from_bitset(kName); }
@@ -107,6 +115,7 @@
 
   static Type* Receiver() { return from_bitset(kReceiver); }
   static Type* Object() { return from_bitset(kObject); }
+  static Type* Undetectable() { return from_bitset(kUndetectable); }
   static Type* Array() { return from_bitset(kArray); }
   static Type* Function() { return from_bitset(kFunction); }
   static Type* Proxy() { return from_bitset(kProxy); }
@@ -122,10 +131,49 @@
   static Type* Union(Handle<Type> type1, Handle<Type> type2);
   static Type* Optional(Handle<Type> type);  // type \/ Undefined
 
-  bool Is(Handle<Type> that);
-  bool Maybe(Handle<Type> that);
+  bool Is(Type* that);
+  bool Is(Handle<Type> that) { return this->Is(*that); }
+  bool Maybe(Type* that);
+  bool Maybe(Handle<Type> that) { return this->Maybe(*that); }
 
-  // TODO(rossberg): method to iterate unions?
+  bool IsClass() { return is_class(); }
+  bool IsConstant() { return is_constant(); }
+  Handle<Map> AsClass() { return as_class(); }
+  Handle<v8::internal::Object> AsConstant() { return as_constant(); }
+
+  int NumClasses();
+  int NumConstants();
+
+  template<class T>
+  class Iterator {
+   public:
+    bool Done() const { return index_ < 0; }
+    Handle<T> Current();
+    void Advance();
+
+   private:
+    friend class Type;
+
+    Iterator() : index_(-1) {}
+    explicit Iterator(Handle<Type> type) : type_(type), index_(-1) {
+      Advance();
+    }
+
+    inline bool matches(Handle<Type> type);
+    inline Handle<Type> get_type();
+
+    Handle<Type> type_;
+    int index_;
+  };
+
+  Iterator<Map> Classes() {
+    if (this->is_bitset()) return Iterator<Map>();
+    return Iterator<Map>(this->handle());
+  }
+  Iterator<v8::internal::Object> Constants() {
+    if (this->is_bitset()) return Iterator<v8::internal::Object>();
+    return Iterator<v8::internal::Object>(this->handle());
+  }
 
  private:
   // A union is a fixed array containing types. Invariants:
@@ -138,24 +186,29 @@
     kNull = 1 << 0,
     kUndefined = 1 << 1,
     kBoolean = 1 << 2,
-    kSmi = 1 << 3,
-    kDouble = 1 << 4,
-    kSymbol = 1 << 5,
-    kInternalizedString = 1 << 6,
-    kOtherString = 1 << 7,
-    kArray = 1 << 8,
-    kFunction = 1 << 9,
-    kOtherObject = 1 << 10,
-    kProxy = 1 << 11,
+    kInteger31 = 1 << 3,
+    kOtherInteger = 1 << 4,
+    kDouble = 1 << 5,
+    kSymbol = 1 << 6,
+    kInternalizedString = 1 << 7,
+    kOtherString = 1 << 8,
+    kUndetectable = 1 << 9,
+    kArray = 1 << 10,
+    kFunction = 1 << 11,
+    kOtherObject = 1 << 12,
+    kProxy = 1 << 13,
 
     kOddball = kBoolean | kNull | kUndefined,
-    kNumber = kSmi | kDouble,
+    kInteger32 = kInteger31 | kOtherInteger,
+    kNumber = kInteger32 | kDouble,
     kString = kInternalizedString | kOtherString,
     kUniqueName = kSymbol | kInternalizedString,
     kName = kSymbol | kString,
-    kObject = kArray | kFunction | kOtherObject,
+    kObject = kUndetectable | kArray | kFunction | kOtherObject,
     kReceiver = kObject | kProxy,
-    kAny = kOddball | kNumber | kName | kReceiver,
+    kAllocated = kDouble | kName | kReceiver,
+    kAny = kOddball | kNumber | kAllocated,
+    kDetectable = kAllocated - kUndetectable,
     kNone = 0
   };
 
@@ -166,7 +219,10 @@
 
   int as_bitset() { return Smi::cast(this)->value(); }
   Handle<Map> as_class() { return Handle<Map>::cast(handle()); }
-  Handle<Box> as_constant() { return Handle<Box>::cast(handle()); }
+  Handle<v8::internal::Object> as_constant() {
+    Handle<Box> box = Handle<Box>::cast(handle());
+    return v8::internal::handle(box->value(), box->GetIsolate());
+  }
   Handle<Unioned> as_union() { return Handle<Unioned>::cast(handle()); }
 
   Handle<Type> handle() { return handle_via_isolate_of(this); }
diff --git a/src/typing.cc b/src/typing.cc
index 4ba6721..e1fd8aa 100644
--- a/src/typing.cc
+++ b/src/typing.cc
@@ -52,7 +52,7 @@
   } while (false)
 
 
-void AstTyper::Type(CompilationInfo* info) {
+void AstTyper::Run(CompilationInfo* info) {
   AstTyper* visitor = new(info->zone()) AstTyper(info);
   Scope* scope = info->scope();
 
diff --git a/src/typing.h b/src/typing.h
index d8708c2..1f172ea 100644
--- a/src/typing.h
+++ b/src/typing.h
@@ -43,7 +43,7 @@
 
 class AstTyper: public AstVisitor {
  public:
-  static void Type(CompilationInfo* info);
+  static void Run(CompilationInfo* info);
 
   void* operator new(size_t size, Zone* zone) {
     return zone->New(static_cast<int>(size));
diff --git a/src/v8-counters.h b/src/v8-counters.h
index c810cba..373618e 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -63,12 +63,16 @@
      V8.MemoryExternalFragmentationMapSpace)                          \
   HP(external_fragmentation_cell_space,                               \
      V8.MemoryExternalFragmentationCellSpace)                         \
+  HP(external_fragmentation_property_cell_space,                      \
+     V8.MemoryExternalFragmentationPropertyCellSpace)                 \
   HP(external_fragmentation_lo_space,                                 \
      V8.MemoryExternalFragmentationLoSpace)                           \
   HP(heap_fraction_map_space,                                         \
      V8.MemoryHeapFractionMapSpace)                                   \
   HP(heap_fraction_cell_space,                                        \
      V8.MemoryHeapFractionCellSpace)                                  \
+  HP(heap_fraction_property_cell_space,                               \
+     V8.MemoryHeapFractionPropertyCellSpace)                          \
 
 
 #define HISTOGRAM_MEMORY_LIST(HM)                                     \
@@ -77,7 +81,9 @@
   HM(heap_sample_map_space_committed,                                 \
      V8.MemoryHeapSampleMapSpaceCommitted)                            \
   HM(heap_sample_cell_space_committed,                                \
-     V8.MemoryHeapSampleCellSpaceCommitted)
+     V8.MemoryHeapSampleCellSpaceCommitted)                           \
+  HM(heap_sample_property_cell_space_committed,                       \
+     V8.MemoryHeapSamplePropertyCellSpaceCommitted)                   \
 
 
 // WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
@@ -297,6 +303,12 @@
   SC(cell_space_bytes_available, V8.MemoryCellSpaceBytesAvailable)    \
   SC(cell_space_bytes_committed, V8.MemoryCellSpaceBytesCommitted)    \
   SC(cell_space_bytes_used, V8.MemoryCellSpaceBytesUsed)              \
+  SC(property_cell_space_bytes_available,                             \
+     V8.MemoryPropertyCellSpaceBytesAvailable)                        \
+  SC(property_cell_space_bytes_committed,                             \
+     V8.MemoryPropertyCellSpaceBytesCommitted)                        \
+  SC(property_cell_space_bytes_used,                                  \
+     V8.MemoryPropertyCellSpaceBytesUsed)                             \
   SC(lo_space_bytes_available, V8.MemoryLoSpaceBytesAvailable)        \
   SC(lo_space_bytes_committed, V8.MemoryLoSpaceBytesCommitted)        \
   SC(lo_space_bytes_used, V8.MemoryLoSpaceBytesUsed)
diff --git a/src/v8globals.h b/src/v8globals.h
index 98940c5..4932da9 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -180,12 +180,13 @@
   CODE_SPACE,           // No pointers to new space, marked executable.
   MAP_SPACE,            // Only and all map objects.
   CELL_SPACE,           // Only and all cell objects.
+  PROPERTY_CELL_SPACE,  // Only and all global property cell objects.
   LO_SPACE,             // Promoted large objects.
 
   FIRST_SPACE = NEW_SPACE,
   LAST_SPACE = LO_SPACE,
   FIRST_PAGED_SPACE = OLD_POINTER_SPACE,
-  LAST_PAGED_SPACE = CELL_SPACE
+  LAST_PAGED_SPACE = PROPERTY_CELL_SPACE
 };
 const int kSpaceTagSize = 3;
 const int kSpaceTagMask = (1 << kSpaceTagSize) - 1;
diff --git a/src/v8natives.js b/src/v8natives.js
index e168b71..76eeac6 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -1786,30 +1786,36 @@
 }
 
 
-function NewFunction(arg1) {  // length == 1
-  var n = %_ArgumentsLength();
+function NewFunctionString(arguments, function_token) {
+  var n = arguments.length;
   var p = '';
   if (n > 1) {
-    p = new InternalArray(n - 1);
-    for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i);
-    p = Join(p, n - 1, ',', NonStringToString);
+    p = ToString(arguments[0]);
+    for (var i = 1; i < n - 1; i++) {
+      p += ',' + ToString(arguments[i]);
+    }
     // If the formal parameters string include ) - an illegal
     // character - it may make the combined function expression
     // compile. We avoid this problem by checking for this early on.
     if (%_CallFunction(p, ')', StringIndexOf) != -1) {
-      throw MakeSyntaxError('paren_in_arg_string',[]);
+      throw MakeSyntaxError('paren_in_arg_string', []);
     }
     // If the formal parameters include an unbalanced block comment, the
     // function must be rejected. Since JavaScript does not allow nested
     // comments we can include a trailing block comment to catch this.
     p += '\n/' + '**/';
   }
-  var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
-  var source = '(function(' + p + ') {\n' + body + '\n})';
+  var body = (n > 0) ? ToString(arguments[n - 1]) : '';
+  return '(' + function_token + '(' + p + ') {\n' + body + '\n})';
+}
 
+
+function FunctionConstructor(arg1) {  // length == 1
+  var source = NewFunctionString(arguments, 'function');
   var global_receiver = %GlobalReceiver(global);
+  // Compile the string in the constructor and not a helper so that errors
+  // appear to come from here.
   var f = %_CallFunction(global_receiver, %CompileString(source, true));
-
   %FunctionMarkNameShouldPrintAsAnonymous(f);
   return f;
 }
@@ -1820,7 +1826,7 @@
 function SetUpFunction() {
   %CheckIsBootstrapping();
 
-  %SetCode($Function, NewFunction);
+  %SetCode($Function, FunctionConstructor);
   %SetProperty($Function.prototype, "constructor", $Function, DONT_ENUM);
 
   InstallFunctions($Function.prototype, DONT_ENUM, $Array(
diff --git a/src/version.cc b/src/version.cc
index c07f9be..f6e8e2f 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     19
-#define BUILD_NUMBER      13
-#define PATCH_LEVEL       1
+#define BUILD_NUMBER      14
+#define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h
index 91bc528..d1d6278 100644
--- a/src/x64/assembler-x64-inl.h
+++ b/src/x64/assembler-x64-inl.h
@@ -332,24 +332,22 @@
 }
 
 
-Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
-  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+Handle<Cell> RelocInfo::target_cell_handle() {
+  ASSERT(rmode_ == RelocInfo::CELL);
   Address address = Memory::Address_at(pc_);
-  return Handle<JSGlobalPropertyCell>(
-      reinterpret_cast<JSGlobalPropertyCell**>(address));
+  return Handle<Cell>(reinterpret_cast<Cell**>(address));
 }
 
 
-JSGlobalPropertyCell* RelocInfo::target_cell() {
-  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
-  return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
+Cell* RelocInfo::target_cell() {
+  ASSERT(rmode_ == RelocInfo::CELL);
+  return Cell::FromValueAddress(Memory::Address_at(pc_));
 }
 
 
-void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
-                                WriteBarrierMode mode) {
-  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
-  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
+void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
+  ASSERT(rmode_ == RelocInfo::CELL);
+  Address address = cell->address() + Cell::kValueOffset;
   Memory::Address_at(pc_) = address;
   CPU::FlushICache(pc_, sizeof(Address));
   if (mode == UPDATE_WRITE_BARRIER &&
@@ -445,8 +443,8 @@
     CPU::FlushICache(pc_, sizeof(Address));
   } else if (RelocInfo::IsCodeTarget(mode)) {
     visitor->VisitCodeTarget(this);
-  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
-    visitor->VisitGlobalPropertyCell(this);
+  } else if (mode == RelocInfo::CELL) {
+    visitor->VisitCell(this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     visitor->VisitExternalReference(this);
     CPU::FlushICache(pc_, sizeof(Address));
@@ -475,8 +473,8 @@
     CPU::FlushICache(pc_, sizeof(Address));
   } else if (RelocInfo::IsCodeTarget(mode)) {
     StaticVisitor::VisitCodeTarget(heap, this);
-  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
-    StaticVisitor::VisitGlobalPropertyCell(heap, this);
+  } else if (mode == RelocInfo::CELL) {
+    StaticVisitor::VisitCell(heap, this);
   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     StaticVisitor::VisitExternalReference(this);
     CPU::FlushICache(pc_, sizeof(Address));
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index bc2e59a..40025d3 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -3727,7 +3727,7 @@
   Label initialize, done;
 
   // Load the cache state into rcx.
-  __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
+  __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset));
 
   // A monomorphic cache hit or an already megamorphic state: invoke the
   // function without changing the state.
@@ -3742,13 +3742,13 @@
   __ j(equal, &initialize, Label::kNear);
   // MegamorphicSentinel is an immortal immovable object (undefined) so no
   // write-barrier is needed.
-  __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+  __ Move(FieldOperand(rbx, Cell::kValueOffset),
           TypeFeedbackCells::MegamorphicSentinel(isolate));
   __ jmp(&done, Label::kNear);
 
   // An uninitialized cache is patched with the function.
   __ bind(&initialize);
-  __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi);
+  __ movq(FieldOperand(rbx, Cell::kValueOffset), rdi);
   // No need for a write barrier here - cells are rescanned.
 
   __ bind(&done);
@@ -3766,7 +3766,7 @@
   Label initialize, done, miss, megamorphic, not_array_function;
 
   // Load the cache state into rcx.
-  __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
+  __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset));
 
   // A monomorphic cache hit or an already megamorphic state: invoke the
   // function without changing the state.
@@ -3799,7 +3799,7 @@
   // MegamorphicSentinel is an immortal immovable object (undefined) so no
   // write-barrier is needed.
   __ bind(&megamorphic);
-  __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+  __ Move(FieldOperand(rbx, Cell::kValueOffset),
           TypeFeedbackCells::MegamorphicSentinel(isolate));
   __ jmp(&done, Label::kNear);
 
@@ -3817,12 +3817,12 @@
   Handle<Object> initial_kind_sentinel =
       TypeFeedbackCells::MonomorphicArraySentinel(isolate,
           GetInitialFastElementsKind());
-  __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+  __ Move(FieldOperand(rbx, Cell::kValueOffset),
           initial_kind_sentinel);
   __ jmp(&done);
 
   __ bind(&not_array_function);
-  __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi);
+  __ movq(FieldOperand(rbx, Cell::kValueOffset), rdi);
   // No need for a write barrier here - cells are rescanned.
 
   __ bind(&done);
@@ -3893,7 +3893,7 @@
     // If there is a call target cache, mark it megamorphic in the
     // non-function case.  MegamorphicSentinel is an immortal immovable
     // object (undefined) so no write barrier is needed.
-    __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+    __ Move(FieldOperand(rbx, Cell::kValueOffset),
             TypeFeedbackCells::MegamorphicSentinel(isolate));
   }
   // Check for function proxy.
@@ -6934,13 +6934,12 @@
     __ CmpObjectType(rcx, MAP_TYPE, rcx);
     __ Check(equal, "Unexpected initial map for Array function");
 
-    // We should either have undefined in ebx or a valid jsglobalpropertycell
+    // We should either have undefined in ebx or a valid cell
     Label okay_here;
-    Handle<Map> global_property_cell_map(
-        masm->isolate()->heap()->global_property_cell_map());
+    Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
     __ Cmp(rbx, undefined_sentinel);
     __ j(equal, &okay_here);
-    __ Cmp(FieldOperand(rbx, 0), global_property_cell_map);
+    __ Cmp(FieldOperand(rbx, 0), cell_map);
     __ Assert(equal, "Expected property cell in register rbx");
     __ bind(&okay_here);
   }
@@ -6950,7 +6949,7 @@
     // Get the elements kind and case on that.
     __ Cmp(rbx, undefined_sentinel);
     __ j(equal, &no_info);
-    __ movq(rdx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
+    __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset));
     __ JumpIfNotSmi(rdx, &no_info);
     __ SmiToInteger32(rdx, rdx);
     __ jmp(&switch_ready);
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index e9fe2a8..74ccef9 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -118,7 +118,7 @@
   CompilationInfo* info = info_;
   handler_table_ =
       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
-  profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
+  profiling_counter_ = isolate()->factory()->NewCell(
       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
   SetFunctionPosition(function());
   Comment cmnt(masm_, "[ function compiled by full code generator");
@@ -308,7 +308,7 @@
 
 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
   __ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
-  __ SmiAddConstant(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+  __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
                     Smi::FromInt(-delta));
 }
 
@@ -323,8 +323,7 @@
   __ movq(kScratchRegister,
           reinterpret_cast<uint64_t>(Smi::FromInt(reset_value)),
           RelocInfo::NONE64);
-  __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
-          kScratchRegister);
+  __ movq(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
 }
 
 
@@ -1128,14 +1127,12 @@
   Label non_proxy;
   __ bind(&fixed_array);
 
-  Handle<JSGlobalPropertyCell> cell =
-      isolate()->factory()->NewJSGlobalPropertyCell(
-          Handle<Object>(
-              Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
-              isolate()));
+  Handle<Cell> cell = isolate()->factory()->NewCell(
+      Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
+                     isolate()));
   RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
   __ LoadHeapObject(rbx, cell);
-  __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+  __ Move(FieldOperand(rbx, Cell::kValueOffset),
           Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker));
 
   __ Move(rbx, Smi::FromInt(1));  // Smi indicates slow check
@@ -1974,8 +1971,12 @@
   VisitForStackValue(expr->expression());
 
   switch (expr->yield_kind()) {
-    case Yield::INITIAL:
-    case Yield::SUSPEND: {
+    case Yield::SUSPEND:
+      // Pop value from top-of-stack slot; box result into result register.
+      EmitCreateIteratorResult(false);
+      __ push(result_register());
+      // Fall through.
+    case Yield::INITIAL: {
       VisitForStackValue(expr->generator_object());
       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
       __ movq(context_register(),
@@ -1984,12 +1985,8 @@
       Label resume;
       __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
       __ j(not_equal, &resume);
-      if (expr->yield_kind() == Yield::SUSPEND) {
-        EmitReturnIteratorResult(false);
-      } else {
-        __ pop(result_register());
-        EmitReturnSequence();
-      }
+      __ pop(result_register());
+      EmitReturnSequence();
 
       __ bind(&resume);
       context()->Plug(result_register());
@@ -2001,7 +1998,10 @@
       __ Move(FieldOperand(result_register(),
                            JSGeneratorObject::kContinuationOffset),
               Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
-      EmitReturnIteratorResult(true);
+      // Pop value from top-of-stack slot, box result into result register.
+      EmitCreateIteratorResult(true);
+      EmitUnwindBeforeReturn();
+      EmitReturnSequence();
       break;
     }
 
@@ -2031,17 +2031,18 @@
 
       // try { received = yield result.value }
       __ bind(&l_try);
-      __ pop(rax);                                       // result.value
+      EmitCreateIteratorResult(false);                    // pop and box to rax
       __ PushTryHandler(StackHandler::CATCH, expr->index());
       const int handler_size = StackHandlerConstants::kSize;
-      __ push(rax);                                      // result.value
+      __ push(rax);                                      // result
       __ push(Operand(rsp, (0 + 1) * kPointerSize + handler_size));  // g
       __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
       __ movq(context_register(),
               Operand(rbp, StandardFrameConstants::kContextOffset));
       __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
       __ j(not_equal, &l_resume);
-      EmitReturnIteratorResult(false);
+      __ pop(rax);                                       // result
+      EmitReturnSequence();
       __ bind(&l_resume);                                // received in rax
       __ PopTryHandler();
 
@@ -2195,13 +2196,20 @@
 }
 
 
-void FullCodeGenerator::EmitReturnIteratorResult(bool done) {
+void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
   Label gc_required;
   Label allocated;
 
   Handle<Map> map(isolate()->native_context()->generator_result_map());
 
   __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT);
+  __ jmp(&allocated);
+
+  __ bind(&gc_required);
+  __ Push(Smi::FromInt(map->instance_size()));
+  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+  __ movq(context_register(),
+          Operand(rbp, StandardFrameConstants::kContextOffset));
 
   __ bind(&allocated);
   __ Move(rbx, map);
@@ -2222,26 +2230,6 @@
   // root set.
   __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
                       rcx, rdx, kDontSaveFPRegs);
-
-  if (done) {
-    // Exit all nested statements.
-    NestedStatement* current = nesting_stack_;
-    int stack_depth = 0;
-    int context_length = 0;
-    while (current != NULL) {
-      current = current->Exit(&stack_depth, &context_length);
-    }
-    __ Drop(stack_depth);
-  }
-
-  EmitReturnSequence();
-
-  __ bind(&gc_required);
-  __ Push(Smi::FromInt(map->instance_size()));
-  __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
-  __ movq(context_register(),
-          Operand(rbp, StandardFrameConstants::kContextOffset));
-  __ jmp(&allocated);
 }
 
 
@@ -2620,8 +2608,7 @@
   flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
   Handle<Object> uninitialized =
       TypeFeedbackCells::UninitializedSentinel(isolate());
-  Handle<JSGlobalPropertyCell> cell =
-      isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+  Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
   RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
   __ Move(rbx, cell);
 
@@ -2804,8 +2791,7 @@
   // Record call targets in unoptimized code, but not in the snapshot.
   Handle<Object> uninitialized =
       TypeFeedbackCells::UninitializedSentinel(isolate());
-  Handle<JSGlobalPropertyCell> cell =
-      isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+  Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
   RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
   __ Move(rbx, cell);
 
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index f423133..1dd27ac 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -92,20 +92,7 @@
     RegisterDependentCodeForEmbeddedMaps(code);
   }
   PopulateDeoptimizationData(code);
-  for (int i = 0 ; i < prototype_maps_.length(); i++) {
-    prototype_maps_.at(i)->AddDependentCode(
-        DependentCode::kPrototypeCheckGroup, code);
-  }
-  for (int i = 0 ; i < transition_maps_.length(); i++) {
-    transition_maps_.at(i)->AddDependentCode(
-        DependentCode::kTransitionGroup, code);
-  }
-  if (graph()->depends_on_empty_array_proto_elements()) {
-    isolate()->initial_object_prototype()->map()->AddDependentCode(
-        DependentCode::kElementsCantBeAddedGroup, code);
-    isolate()->initial_array_prototype()->map()->AddDependentCode(
-        DependentCode::kElementsCantBeAddedGroup, code);
-  }
+  info()->CommitDependentMaps(code);
 }
 
 
@@ -482,27 +469,15 @@
 
 
 void LCodeGen::WriteTranslation(LEnvironment* environment,
-                                Translation* translation,
-                                int* pushed_arguments_index,
-                                int* pushed_arguments_count) {
+                                Translation* translation) {
   if (environment == NULL) return;
 
   // The translation includes one command per value in the environment.
-  int translation_size = environment->values()->length();
+  int translation_size = environment->translation_size();
   // The output frame height does not include the parameters.
   int height = translation_size - environment->parameter_count();
 
-  // Function parameters are arguments to the outermost environment. The
-  // arguments index points to the first element of a sequence of tagged
-  // values on the stack that represent the arguments. This needs to be
-  // kept in sync with the LArgumentsElements implementation.
-  *pushed_arguments_index = -environment->parameter_count();
-  *pushed_arguments_count = environment->parameter_count();
-
-  WriteTranslation(environment->outer(),
-                   translation,
-                   pushed_arguments_index,
-                   pushed_arguments_count);
+  WriteTranslation(environment->outer(), translation);
   bool has_closure_id = !info()->closure().is_null() &&
       !info()->closure().is_identical_to(environment->closure());
   int closure_id = has_closure_id
@@ -534,23 +509,6 @@
       break;
   }
 
-  // Inlined frames which push their arguments cause the index to be
-  // bumped and another stack area to be used for materialization,
-  // otherwise actual argument values are unknown for inlined frames.
-  bool arguments_known = true;
-  int arguments_index = *pushed_arguments_index;
-  int arguments_count = *pushed_arguments_count;
-  if (environment->entry() != NULL) {
-    arguments_known = environment->entry()->arguments_pushed();
-    arguments_index = arguments_index < 0
-        ? GetStackSlotCount() : arguments_index + arguments_count;
-    arguments_count = environment->entry()->arguments_count() + 1;
-    if (environment->entry()->arguments_pushed()) {
-      *pushed_arguments_index = arguments_index;
-      *pushed_arguments_count = arguments_count;
-    }
-  }
-
   for (int i = 0; i < translation_size; ++i) {
     LOperand* value = environment->values()->at(i);
     // spilled_registers_ and spilled_double_registers_ are either
@@ -562,10 +520,7 @@
         AddToTranslation(translation,
                          environment->spilled_registers()[value->index()],
                          environment->HasTaggedValueAt(i),
-                         environment->HasUint32ValueAt(i),
-                         arguments_known,
-                         arguments_index,
-                         arguments_count);
+                         environment->HasUint32ValueAt(i));
       } else if (
           value->IsDoubleRegister() &&
           environment->spilled_double_registers()[value->index()] != NULL) {
@@ -574,20 +529,36 @@
             translation,
             environment->spilled_double_registers()[value->index()],
             false,
-            false,
-            arguments_known,
-            arguments_index,
-            arguments_count);
+            false);
       }
     }
 
+    // TODO(mstarzinger): Introduce marker operands to indicate that this value
+    // is not present and must be reconstructed from the deoptimizer. Currently
+    // this is only used for the arguments object.
+    if (value == NULL) {
+      int arguments_count = environment->values()->length() - translation_size;
+      translation->BeginArgumentsObject(arguments_count);
+      for (int i = 0; i < arguments_count; ++i) {
+        LOperand* value = environment->values()->at(translation_size + i);
+        ASSERT(environment->spilled_registers() == NULL ||
+               !value->IsRegister() ||
+               environment->spilled_registers()[value->index()] == NULL);
+        ASSERT(environment->spilled_registers() == NULL ||
+               !value->IsDoubleRegister() ||
+               environment->spilled_double_registers()[value->index()] == NULL);
+        AddToTranslation(translation,
+                         value,
+                         environment->HasTaggedValueAt(translation_size + i),
+                         environment->HasUint32ValueAt(translation_size + i));
+      }
+      continue;
+    }
+
     AddToTranslation(translation,
                      value,
                      environment->HasTaggedValueAt(i),
-                     environment->HasUint32ValueAt(i),
-                     arguments_known,
-                     arguments_index,
-                     arguments_count);
+                     environment->HasUint32ValueAt(i));
   }
 }
 
@@ -595,17 +566,8 @@
 void LCodeGen::AddToTranslation(Translation* translation,
                                 LOperand* op,
                                 bool is_tagged,
-                                bool is_uint32,
-                                bool arguments_known,
-                                int arguments_index,
-                                int arguments_count) {
-  if (op == NULL) {
-    // TODO(twuerthinger): Introduce marker operands to indicate that this value
-    // is not present and must be reconstructed from the deoptimizer. Currently
-    // this is only used for the arguments object.
-    translation->StoreArgumentsObject(
-        arguments_known, arguments_index, arguments_count);
-  } else if (op->IsStackSlot()) {
+                                bool is_uint32) {
+  if (op->IsStackSlot()) {
     if (is_tagged) {
       translation->StoreStackSlot(op->index());
     } else if (is_uint32) {
@@ -710,8 +672,6 @@
 
     int frame_count = 0;
     int jsframe_count = 0;
-    int args_index = 0;
-    int args_count = 0;
     for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
       ++frame_count;
       if (e->frame_type() == JS_FUNCTION) {
@@ -719,7 +679,7 @@
       }
     }
     Translation translation(&translations_, frame_count, jsframe_count, zone());
-    WriteTranslation(environment, &translation, &args_index, &args_count);
+    WriteTranslation(environment, &translation);
     int deoptimization_index = deoptimizations_.length();
     int pc_offset = masm()->pc_offset();
     environment->Register(deoptimization_index,
@@ -2490,9 +2450,8 @@
   Register map = ToRegister(instr->temp());
   __ movq(map, FieldOperand(object, HeapObject::kMapOffset));
   __ bind(deferred->map_check());  // Label for calculating code patching.
-  Handle<JSGlobalPropertyCell> cache_cell =
-      factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
-  __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+  Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
+  __ movq(kScratchRegister, cache_cell, RelocInfo::CELL);
   __ cmpq(map, Operand(kScratchRegister, 0));
   __ j(not_equal, &cache_miss, Label::kNear);
   // Patched to load either true or false.
@@ -2661,7 +2620,7 @@
 
 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
   Register value = ToRegister(instr->value());
-  Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell();
+  Handle<Cell> cell_handle = instr->hydrogen()->cell();
 
   // If the cell we are storing to contains the hole it could have
   // been deleted from the property dictionary. In that case, we need
@@ -2671,14 +2630,14 @@
     // We have a temp because CompareRoot might clobber kScratchRegister.
     Register cell = ToRegister(instr->temp());
     ASSERT(!value.is(cell));
-    __ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL);
+    __ movq(cell, cell_handle, RelocInfo::CELL);
     __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex);
     DeoptimizeIf(equal, instr->environment());
     // Store the value.
     __ movq(Operand(cell, 0), value);
   } else {
     // Store the value.
-    __ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL);
+    __ movq(kScratchRegister, cell_handle, RelocInfo::CELL);
     __ movq(Operand(kScratchRegister, 0), value);
   }
   // Cells are always rescanned, so no write barrier here.
@@ -3964,8 +3923,26 @@
     ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
     CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
   } else if (instr->arity() == 1) {
+    Label done;
+    if (IsFastPackedElementsKind(kind)) {
+      Label packed_case;
+      // We might need a change here
+      // look at the first argument
+      __ movq(rcx, Operand(rsp, 0));
+      __ testq(rcx, rcx);
+      __ j(zero, &packed_case);
+
+      ElementsKind holey_kind = GetHoleyElementsKind(kind);
+      ArraySingleArgumentConstructorStub stub(holey_kind,
+                                              disable_allocation_sites);
+      CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+      __ jmp(&done);
+      __ bind(&packed_case);
+    }
+
     ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites);
     CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+    __ bind(&done);
   } else {
     ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites);
     CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
@@ -4025,9 +4002,6 @@
   }
 
   if (!transition.is_null()) {
-    if (transition->CanBeDeprecated()) {
-      transition_maps_.Add(transition, info()->zone());
-    }
     if (!instr->hydrogen()->NeedsWriteBarrierForMap()) {
       __ Move(FieldOperand(object, HeapObject::kMapOffset), transition);
     } else {
@@ -5100,11 +5074,7 @@
 
   ASSERT(prototypes->length() == maps->length());
 
-  if (instr->hydrogen()->CanOmitPrototypeChecks()) {
-    for (int i = 0; i < maps->length(); i++) {
-      prototype_maps_.Add(maps->at(i), info()->zone());
-    }
-  } else {
+  if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
     for (int i = 0; i < prototypes->length(); i++) {
       __ LoadHeapObject(reg, prototypes->at(i));
       DoCheckMapCommon(reg, maps->at(i), instr);
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 07a948c..31dd9c4 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -57,8 +57,6 @@
         deoptimizations_(4, info->zone()),
         jump_table_(4, info->zone()),
         deoptimization_literals_(8, info->zone()),
-        prototype_maps_(0, info->zone()),
-        transition_maps_(0, info->zone()),
         inlined_function_count_(0),
         scope_(info->scope()),
         status_(UNUSED),
@@ -141,10 +139,7 @@
   void DoGap(LGap* instr);
 
   // Emit frame translation commands for an environment.
-  void WriteTranslation(LEnvironment* environment,
-                        Translation* translation,
-                        int* arguments_index,
-                        int* arguments_count);
+  void WriteTranslation(LEnvironment* environment, Translation* translation);
 
   // Declare methods that deal with the individual node types.
 #define DECLARE_DO(type) void Do##type(L##type* node);
@@ -255,10 +250,7 @@
   void AddToTranslation(Translation* translation,
                         LOperand* op,
                         bool is_tagged,
-                        bool is_uint32,
-                        bool arguments_known,
-                        int arguments_index,
-                        int arguments_count);
+                        bool is_uint32);
   void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -362,8 +354,6 @@
   ZoneList<LEnvironment*> deoptimizations_;
   ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
   ZoneList<Handle<Object> > deoptimization_literals_;
-  ZoneList<Handle<Map> > prototype_maps_;
-  ZoneList<Handle<Map> > transition_maps_;
   int inlined_function_count_;
   Scope* const scope_;
   Status status_;
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index cb0659d..57a8b2e 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -937,7 +937,7 @@
   BailoutId ast_id = hydrogen_env->ast_id();
   ASSERT(!ast_id.IsNone() ||
          hydrogen_env->frame_type() != JS_FUNCTION);
-  int value_count = hydrogen_env->length();
+  int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
   LEnvironment* result = new(zone()) LEnvironment(
       hydrogen_env->closure(),
       hydrogen_env->frame_type(),
@@ -948,13 +948,15 @@
       outer,
       hydrogen_env->entry(),
       zone());
+  bool needs_arguments_object_materialization = false;
   int argument_index = *argument_index_accumulator;
-  for (int i = 0; i < value_count; ++i) {
+  for (int i = 0; i < hydrogen_env->length(); ++i) {
     if (hydrogen_env->is_special_index(i)) continue;
 
     HValue* value = hydrogen_env->values()->at(i);
     LOperand* op = NULL;
     if (value->IsArgumentsObject()) {
+      needs_arguments_object_materialization = true;
       op = NULL;
     } else if (value->IsPushArgument()) {
       op = new(zone()) LArgument(argument_index++);
@@ -966,6 +968,22 @@
                      value->CheckFlag(HInstruction::kUint32));
   }
 
+  if (needs_arguments_object_materialization) {
+    HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+        ? graph()->GetArgumentsObject()
+        : hydrogen_env->entry()->arguments_object();
+    ASSERT(arguments->IsLinked());
+    for (int i = 1; i < arguments->arguments_count(); ++i) {
+      HValue* value = arguments->arguments_values()->at(i);
+      ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+      ASSERT(HInstruction::cast(value)->IsLinked());
+      LOperand* op = UseAny(value);
+      result->AddValue(op,
+                       value->representation(),
+                       value->CheckFlag(HInstruction::kUint32));
+    }
+  }
+
   if (hydrogen_env->frame_type() == JS_FUNCTION) {
     *argument_index_accumulator = argument_index;
   }
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 46e2c69..a2568a4 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -2357,9 +2357,8 @@
                                     Handle<HeapObject> object) {
   AllowDeferredHandleDereference using_raw_address;
   if (isolate()->heap()->InNewSpace(*object)) {
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(object);
-    movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+    Handle<Cell> cell = isolate()->factory()->NewCell(object);
+    movq(result, cell, RelocInfo::CELL);
     movq(result, Operand(result, 0));
   } else {
     Move(result, object);
@@ -2370,9 +2369,8 @@
 void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
   AllowDeferredHandleDereference using_raw_address;
   if (isolate()->heap()->InNewSpace(*object)) {
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(object);
-    movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+    Handle<Cell> cell = isolate()->factory()->NewCell(object);
+    movq(kScratchRegister, cell, RelocInfo::CELL);
     cmpq(reg, Operand(kScratchRegister, 0));
   } else {
     Cmp(reg, object);
@@ -2383,9 +2381,8 @@
 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
   AllowDeferredHandleDereference using_raw_address;
   if (isolate()->heap()->InNewSpace(*object)) {
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(object);
-    movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+    Handle<Cell> cell = isolate()->factory()->NewCell(object);
+    movq(kScratchRegister, cell, RelocInfo::CELL);
     movq(kScratchRegister, Operand(kScratchRegister, 0));
     push(kScratchRegister);
   } else {
@@ -2394,13 +2391,12 @@
 }
 
 
-void MacroAssembler::LoadGlobalCell(Register dst,
-                                    Handle<JSGlobalPropertyCell> cell) {
+void MacroAssembler::LoadGlobalCell(Register dst, Handle<Cell> cell) {
   if (dst.is(rax)) {
     AllowDeferredHandleDereference embedding_raw_address;
-    load_rax(cell.location(), RelocInfo::GLOBAL_PROPERTY_CELL);
+    load_rax(cell.location(), RelocInfo::CELL);
   } else {
-    movq(dst, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+    movq(dst, cell, RelocInfo::CELL);
     movq(dst, Operand(dst, 0));
   }
 }
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index c10cbc6..7b8747c 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -810,7 +810,7 @@
   }
 
   // Load a global cell into a register.
-  void LoadGlobalCell(Register dst, Handle<JSGlobalPropertyCell> cell);
+  void LoadGlobalCell(Register dst, Handle<Cell> cell);
 
   // Emit code to discard a non-negative number of pointer-sized elements
   // from the stack, clobbering only the rsp register.
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 06d8f71..c105905 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -741,7 +741,7 @@
       GlobalObject::EnsurePropertyCell(global, name);
   ASSERT(cell->value()->IsTheHole());
   __ Move(scratch, cell);
-  __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
+  __ Cmp(FieldOperand(scratch, Cell::kValueOffset),
          masm->isolate()->factory()->the_hole_value());
   __ j(not_equal, miss);
 }
@@ -1485,12 +1485,12 @@
 
 
 void CallStubCompiler::GenerateLoadFunctionFromCell(
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Label* miss) {
   // Get the value from the cell.
   __ Move(rdi, cell);
-  __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset));
+  __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset));
 
   // Check that the cell contains the same function.
   if (heap()->InNewSpace(*function)) {
@@ -1584,7 +1584,7 @@
 Handle<Code> CallStubCompiler::CompileArrayPushCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -1834,7 +1834,7 @@
 Handle<Code> CallStubCompiler::CompileArrayPopCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -1915,7 +1915,7 @@
 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -1995,7 +1995,7 @@
 Handle<Code> CallStubCompiler::CompileStringCharAtCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2075,7 +2075,7 @@
 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2146,7 +2146,7 @@
 Handle<Code> CallStubCompiler::CompileMathFloorCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // TODO(872): implement this.
@@ -2157,7 +2157,7 @@
 Handle<Code> CallStubCompiler::CompileMathAbsCall(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   // ----------- S t a t e -------------
@@ -2263,7 +2263,7 @@
     const CallOptimization& optimization,
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<JSGlobalPropertyCell> cell,
+    Handle<Cell> cell,
     Handle<JSFunction> function,
     Handle<String> name) {
   ASSERT(optimization.is_simple_api_call());
diff --git a/test/cctest/test-compare-nil-ic-stub.cc b/test/cctest/test-compare-nil-ic-stub.cc
index affb8bd..258ab01 100644
--- a/test/cctest/test-compare-nil-ic-stub.cc
+++ b/test/cctest/test-compare-nil-ic-stub.cc
@@ -34,26 +34,26 @@
 
 using namespace v8::internal;
 
-#define Types CompareNilICStub::Types
+typedef CompareNilICStub::State State;
 
-TEST(TypeConstructors) {
-  Types types;
-  types.Add(CompareNilICStub::MONOMORPHIC_MAP);
-  Types types2(types);
-  CHECK_EQ(types.ToIntegral(), types2.ToIntegral());
+TEST(StateConstructors) {
+  State state;
+  state.Add(CompareNilICStub::MONOMORPHIC_MAP);
+  State state2(state);
+  CHECK_EQ(state.ToIntegral(), state2.ToIntegral());
 }
 
 TEST(ExternalICStateParsing) {
-  Types types;
-  types.Add(CompareNilICStub::UNDEFINED);
-  CompareNilICStub stub(kUndefinedValue, types);
+  State state;
+  state.Add(CompareNilICStub::UNDEFINED);
+  CompareNilICStub stub(kUndefinedValue, state);
   CompareNilICStub stub2(stub.GetExtraICState());
   CHECK_EQ(stub.GetNilValue(), stub2.GetNilValue());
-  CHECK_EQ(stub.GetTypes().ToIntegral(), stub2.GetTypes().ToIntegral());
+  CHECK_EQ(stub.GetState().ToIntegral(), stub2.GetState().ToIntegral());
 }
 
-TEST(SettingTypes) {
-  Types state;
+TEST(SettingState) {
+  State state;
   CHECK(state.IsEmpty());
   state.Add(CompareNilICStub::NULL_TYPE);
   CHECK(!state.IsEmpty());
@@ -66,20 +66,22 @@
   CHECK(!state.Contains(CompareNilICStub::UNDETECTABLE));
 }
 
-TEST(ClearTypes) {
-  Types state;
+TEST(ClearState) {
+  State state;
   state.Add(CompareNilICStub::NULL_TYPE);
   state.RemoveAll();
   CHECK(state.IsEmpty());
 }
 
-TEST(FullCompare) {
-  Types state;
-  CHECK(Types::FullCompare() != state);
+TEST(Generic) {
+  State state;
+  CHECK(State::Generic() != state);
   state.Add(CompareNilICStub::UNDEFINED);
-  CHECK(state != Types::FullCompare());
+  CHECK(state != State::Generic());
   state.Add(CompareNilICStub::NULL_TYPE);
-  CHECK(state != Types::FullCompare());
+  CHECK(state != State::Generic());
   state.Add(CompareNilICStub::UNDETECTABLE);
-  CHECK(state == Types::FullCompare());
+  CHECK(state != State::Generic());
+  state.Add(CompareNilICStub::GENERIC);
+  CHECK(state == State::Generic());
 }
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index a615fe9..95930b4 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -917,3 +917,89 @@
 
   cpu_profiler->DeleteAllCpuProfiles();
 }
+
+
+static const char* cpu_profiler_sourceURL_source =
+"function start(timeout) {\n"
+"  var start = Date.now();\n"
+"  var duration = 0;\n"
+"  do {\n"
+"    try {\n"
+"      duration = Date.now() - start;\n"
+"    } catch(e) { }\n"
+"  } while (duration < timeout);\n"
+"  return duration;\n"
+"}\n"
+"//# sourceURL=cpu_profiler_sourceURL_source.js";
+
+
+TEST(SourceURLSupportForNewFunctions) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+
+  v8::Script::Compile(v8::String::New(cpu_profiler_sourceURL_source))->Run();
+  v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::New("start")));
+  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+  int32_t profiling_interval_ms = 200;
+#if defined(_WIN32) || defined(_WIN64)
+  // 200ms is not enough on Windows. See
+  // https://code.google.com/p/v8/issues/detail?id=2628
+  profiling_interval_ms = 500;
+#endif
+
+  // Cold run.
+  v8::Local<v8::String> profile_name = v8::String::New("my_profile");
+  cpu_profiler->StartCpuProfiling(profile_name);
+  v8::Handle<v8::Value> args[] = { v8::Integer::New(profiling_interval_ms) };
+  function->Call(env->Global(), ARRAY_SIZE(args), args);
+  const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name);
+  CHECK_NE(NULL, profile);
+
+  // Dump collected profile to have a better diagnostic in case of failure.
+  reinterpret_cast<i::CpuProfile*>(
+      const_cast<v8::CpuProfile*>(profile))->Print();
+  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+  const v8::CpuProfileNode* startNode = GetChild(root, "start");
+
+  CHECK_EQ(v8::String::New("cpu_profiler_sourceURL_source.js"),
+           startNode->GetScriptResourceName());
+
+  cpu_profiler->DeleteAllCpuProfiles();
+}
+
+TEST(LogExistingFunctionSourceURLCheck) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+
+  v8::Script::Compile(v8::String::New(cpu_profiler_sourceURL_source))->Run();
+  v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::New("start")));
+  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+  int32_t profiling_interval_ms = 200;
+
+  // Warm up.
+  v8::Handle<v8::Value> args[] = { v8::Integer::New(profiling_interval_ms) };
+  function->Call(env->Global(), ARRAY_SIZE(args), args);
+
+#if defined(_WIN32) || defined(_WIN64)
+  // 200ms is not enough on Windows. See
+  // https://code.google.com/p/v8/issues/detail?id=2628
+  profiling_interval_ms = 500;
+#endif
+  v8::Local<v8::String> profile_name = v8::String::New("my_profile");
+  cpu_profiler->StartCpuProfiling(profile_name);
+  function->Call(env->Global(), ARRAY_SIZE(args), args);
+  const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name);
+  CHECK_NE(NULL, profile);
+
+  // Dump collected profile to have a better diagnostic in case of failure.
+  reinterpret_cast<i::CpuProfile*>(
+      const_cast<v8::CpuProfile*>(profile))->Print();
+  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+  const v8::CpuProfileNode* startNode = GetChild(root, "start");
+  CHECK_EQ(v8::String::New("cpu_profiler_sourceURL_source.js"),
+           startNode->GetScriptResourceName());
+
+  cpu_profiler->DeleteAllCpuProfiles();
+}
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 68ed83d..72d124f 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -2498,15 +2498,15 @@
       f->shared()->code()->type_feedback_info())->type_feedback_cells());
 
   CHECK_EQ(2, cells->CellCount());
-  CHECK(cells->Cell(0)->value()->IsJSFunction());
-  CHECK(cells->Cell(1)->value()->IsJSFunction());
+  CHECK(cells->GetCell(0)->value()->IsJSFunction());
+  CHECK(cells->GetCell(1)->value()->IsJSFunction());
 
   SimulateIncrementalMarking();
   HEAP->CollectAllGarbage(Heap::kNoGCFlags);
 
   CHECK_EQ(2, cells->CellCount());
-  CHECK(cells->Cell(0)->value()->IsTheHole());
-  CHECK(cells->Cell(1)->value()->IsTheHole());
+  CHECK(cells->GetCell(0)->value()->IsTheHole());
+  CHECK(cells->GetCell(1)->value()->IsTheHole());
 }
 
 
diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index 45cb39c..f6f2172 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -557,7 +557,7 @@
       }
     } else {                            // 32-bit.
       if (v8::internal::Snapshot::IsEnabled()) {
-        CHECK_LE(delta, 2900 * 1024);
+        CHECK_LE(delta, 2910 * 1024);
       } else {
         CHECK_LE(delta, 3400 * 1024);
       }
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 8973d54..20c00c1 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -195,7 +195,8 @@
       int data_space_used,
       int code_space_used,
       int map_space_used,
-      int cell_space_used);
+      int cell_space_used,
+      int property_cell_space_used);
 
  private:
   FILE* fp_;
@@ -209,7 +210,8 @@
       int data_space_used,
       int code_space_used,
       int map_space_used,
-      int cell_space_used) {
+      int cell_space_used,
+      int property_cell_space_used) {
   int file_name_length = StrLength(file_name_) + 10;
   Vector<char> name = Vector<char>::New(file_name_length + 1);
   OS::SNPrintF(name, "%s.size", file_name_);
@@ -221,6 +223,7 @@
   fprintf(fp, "code %d\n", code_space_used);
   fprintf(fp, "map %d\n", map_space_used);
   fprintf(fp, "cell %d\n", cell_space_used);
+  fprintf(fp, "property cell %d\n", property_cell_space_used);
   fclose(fp);
 }
 
@@ -236,7 +239,8 @@
       ser.CurrentAllocationAddress(OLD_DATA_SPACE),
       ser.CurrentAllocationAddress(CODE_SPACE),
       ser.CurrentAllocationAddress(MAP_SPACE),
-      ser.CurrentAllocationAddress(CELL_SPACE));
+      ser.CurrentAllocationAddress(CELL_SPACE),
+      ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
 
   return true;
 }
@@ -425,7 +429,8 @@
         p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
         p_ser.CurrentAllocationAddress(CODE_SPACE),
         p_ser.CurrentAllocationAddress(MAP_SPACE),
-        p_ser.CurrentAllocationAddress(CELL_SPACE));
+        p_ser.CurrentAllocationAddress(CELL_SPACE),
+        p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
 
     startup_sink.WriteSpaceUsed(
         startup_serializer.CurrentAllocationAddress(NEW_SPACE),
@@ -433,7 +438,8 @@
         startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
         startup_serializer.CurrentAllocationAddress(CODE_SPACE),
         startup_serializer.CurrentAllocationAddress(MAP_SPACE),
-        startup_serializer.CurrentAllocationAddress(CELL_SPACE));
+        startup_serializer.CurrentAllocationAddress(CELL_SPACE),
+        startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
     startup_name.Dispose();
   }
 }
@@ -446,7 +452,8 @@
   OS::SNPrintF(name, "%s.size", file_name);
   FILE* fp = OS::FOpen(name.start(), "r");
   name.Dispose();
-  int new_size, pointer_size, data_size, code_size, map_size, cell_size;
+  int new_size, pointer_size, data_size, code_size, map_size, cell_size,
+      property_cell_size;
 #ifdef _MSC_VER
   // Avoid warning about unsafe fscanf from MSVC.
   // Please note that this is only fine if %c and %s are not being used.
@@ -458,6 +465,7 @@
   CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
   CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
   CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
+  CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
 #ifdef _MSC_VER
 #undef fscanf
 #endif
@@ -468,6 +476,7 @@
   deserializer->set_reservation(CODE_SPACE, code_size);
   deserializer->set_reservation(MAP_SPACE, map_size);
   deserializer->set_reservation(CELL_SPACE, cell_size);
+  deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_size);
 }
 
 
@@ -566,7 +575,8 @@
         p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
         p_ser.CurrentAllocationAddress(CODE_SPACE),
         p_ser.CurrentAllocationAddress(MAP_SPACE),
-        p_ser.CurrentAllocationAddress(CELL_SPACE));
+        p_ser.CurrentAllocationAddress(CELL_SPACE),
+        p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
 
     startup_sink.WriteSpaceUsed(
         startup_serializer.CurrentAllocationAddress(NEW_SPACE),
@@ -574,7 +584,8 @@
         startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
         startup_serializer.CurrentAllocationAddress(CODE_SPACE),
         startup_serializer.CurrentAllocationAddress(MAP_SPACE),
-        startup_serializer.CurrentAllocationAddress(CELL_SPACE));
+        startup_serializer.CurrentAllocationAddress(CELL_SPACE),
+        startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
     startup_name.Dispose();
   }
 }
diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc
index 3cdfdad..9729488 100644
--- a/test/cctest/test-types.cc
+++ b/test/cctest/test-types.cc
@@ -51,7 +51,8 @@
       Null(Type::Null(), isolate),
       Undefined(Type::Undefined(), isolate),
       Number(Type::Number(), isolate),
-      Smi(Type::Smi(), isolate),
+      Integer31(Type::Integer31(), isolate),
+      Integer32(Type::Integer32(), isolate),
       Double(Type::Double(), isolate),
       Name(Type::Name(), isolate),
       UniqueName(Type::UniqueName(), isolate),
@@ -72,7 +73,7 @@
     array = isolate->factory()->NewJSArray(20);
     ObjectClass = handle(Type::Class(object_map), isolate);
     ArrayClass = handle(Type::Class(array_map), isolate);
-    SmiConstant = handle(Type::Constant(smi, isolate), isolate);
+    Integer31Constant = handle(Type::Constant(smi, isolate), isolate);
     ObjectConstant1 = handle(Type::Constant(object1), isolate);
     ObjectConstant2 = handle(Type::Constant(object2), isolate);
     ArrayConstant = handle(Type::Constant(array), isolate);
@@ -85,7 +86,8 @@
   Handle<Type> Null;
   Handle<Type> Undefined;
   Handle<Type> Number;
-  Handle<Type> Smi;
+  Handle<Type> Integer31;
+  Handle<Type> Integer32;
   Handle<Type> Double;
   Handle<Type> Name;
   Handle<Type> UniqueName;
@@ -101,7 +103,7 @@
   Handle<Type> ObjectClass;
   Handle<Type> ArrayClass;
 
-  Handle<Type> SmiConstant;
+  Handle<Type> Integer31Constant;
   Handle<Type> ObjectConstant1;
   Handle<Type> ObjectConstant2;
   Handle<Type> ArrayConstant;
@@ -168,12 +170,12 @@
   HandleScope scope(isolate);
   HandlifiedTypes T(isolate);
 
-  CHECK(IsConstant(*T.SmiConstant));
+  CHECK(IsConstant(*T.Integer31Constant));
   CHECK(IsConstant(*T.ObjectConstant1));
   CHECK(IsConstant(*T.ObjectConstant2));
   CHECK(IsConstant(*T.ArrayConstant));
 
-  CHECK(*T.smi == AsConstant(*T.SmiConstant));
+  CHECK(*T.smi == AsConstant(*T.Integer31Constant));
   CHECK(*T.object1 == AsConstant(*T.ObjectConstant1));
   CHECK(*T.object2 == AsConstant(*T.ObjectConstant2));
   CHECK(*T.object1 != AsConstant(*T.ObjectConstant2));
@@ -224,9 +226,12 @@
   CheckUnordered(T.Boolean, T.Undefined);
 
   CheckSub(T.Number, T.Any);
-  CheckSub(T.Smi, T.Number);
+  CheckSub(T.Integer31, T.Number);
+  CheckSub(T.Integer32, T.Number);
   CheckSub(T.Double, T.Number);
-  CheckUnordered(T.Smi, T.Double);
+  CheckSub(T.Integer31, T.Integer32);
+  CheckUnordered(T.Integer31, T.Double);
+  CheckUnordered(T.Integer32, T.Double);
 
   CheckSub(T.Name, T.Any);
   CheckSub(T.UniqueName, T.Any);
@@ -255,8 +260,9 @@
   CheckSub(T.ArrayClass, T.Object);
   CheckUnordered(T.ObjectClass, T.ArrayClass);
 
-  CheckSub(T.SmiConstant, T.Smi);
-  CheckSub(T.SmiConstant, T.Number);
+  CheckSub(T.Integer31Constant, T.Integer31);
+  CheckSub(T.Integer31Constant, T.Integer32);
+  CheckSub(T.Integer31Constant, T.Number);
   CheckSub(T.ObjectConstant1, T.Object);
   CheckSub(T.ObjectConstant2, T.Object);
   CheckSub(T.ArrayConstant, T.Object);
@@ -308,9 +314,9 @@
   CheckDisjoint(T.Boolean, T.Undefined);
 
   CheckOverlap(T.Number, T.Any);
-  CheckOverlap(T.Smi, T.Number);
+  CheckOverlap(T.Integer31, T.Number);
   CheckOverlap(T.Double, T.Number);
-  CheckDisjoint(T.Smi, T.Double);
+  CheckDisjoint(T.Integer32, T.Double);
 
   CheckOverlap(T.Name, T.Any);
   CheckOverlap(T.UniqueName, T.Any);
@@ -340,9 +346,10 @@
   CheckOverlap(T.ArrayClass, T.ArrayClass);
   CheckDisjoint(T.ObjectClass, T.ArrayClass);
 
-  CheckOverlap(T.SmiConstant, T.Smi);
-  CheckOverlap(T.SmiConstant, T.Number);
-  CheckDisjoint(T.SmiConstant, T.Double);
+  CheckOverlap(T.Integer31Constant, T.Integer31);
+  CheckOverlap(T.Integer31Constant, T.Integer32);
+  CheckOverlap(T.Integer31Constant, T.Number);
+  CheckDisjoint(T.Integer31Constant, T.Double);
   CheckOverlap(T.ObjectConstant1, T.Object);
   CheckOverlap(T.ObjectConstant2, T.Object);
   CheckOverlap(T.ArrayConstant, T.Object);
@@ -425,21 +432,22 @@
 
   CheckEqual(T.Union(T.ObjectClass, T.Object), T.Object);
   CheckSub(T.Union(T.ObjectClass, T.Number), T.Any);
-  CheckSub(T.Union(T.ObjectClass, T.Smi), T.Union(T.Object, T.Number));
+  CheckSub(T.Union(T.ObjectClass, T.Integer31), T.Union(T.Object, T.Number));
   CheckSub(T.Union(T.ObjectClass, T.Array), T.Object);
   CheckUnordered(T.Union(T.ObjectClass, T.String), T.Array);
   CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object);
   CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number);
 
   // Bitset-constant
-  CHECK(IsBitset(Type::Union(T.SmiConstant, T.Number)));
+  CHECK(IsBitset(Type::Union(T.Integer31Constant, T.Number)));
   CHECK(IsBitset(Type::Union(T.ObjectConstant1, T.Object)));
   CHECK(IsUnion(Type::Union(T.ObjectConstant2, T.Number)));
 
-  CheckEqual(T.Union(T.SmiConstant, T.Number), T.Number);
+  CheckEqual(T.Union(T.Integer31Constant, T.Number), T.Number);
   CheckEqual(T.Union(T.ObjectConstant1, T.Object), T.Object);
   CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any);
-  CheckSub(T.Union(T.ObjectConstant1, T.Smi), T.Union(T.Object, T.Number));
+  CheckSub(
+      T.Union(T.ObjectConstant1, T.Integer32), T.Union(T.Object, T.Number));
   CheckSub(T.Union(T.ObjectConstant1, T.Array), T.Object);
   CheckUnordered(T.Union(T.ObjectConstant1, T.String), T.Array);
   CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object);
@@ -516,8 +524,8 @@
       T.Union(T.ObjectConstant2, T.Union(T.ArrayConstant, T.ObjectConstant1)));
 
   // Union-union
-  CHECK(IsBitset(
-      Type::Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array))));
+  CHECK(IsBitset(Type::Union(
+      T.Union(T.Number, T.ArrayClass), T.Union(T.Integer32, T.Array))));
 
   CheckEqual(
       T.Union(T.Union(T.ObjectConstant2, T.ObjectConstant1),
@@ -528,6 +536,6 @@
               T.Union(T.ObjectConstant1, T.ArrayConstant)),
       T.Union(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ArrayConstant));
   CheckEqual(
-      T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array)),
+      T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Integer31, T.Array)),
       T.Union(T.Number, T.Array));
 }
diff --git a/test/cctest/test-weaktypedarrays.cc b/test/cctest/test-weaktypedarrays.cc
index aef610d..ead5734 100644
--- a/test/cctest/test-weaktypedarrays.cc
+++ b/test/cctest/test-weaktypedarrays.cc
@@ -44,7 +44,7 @@
 static int CountArrayBuffersInWeakList(Heap* heap) {
   int count = 0;
   for (Object* o = heap->array_buffers_list();
-       o != Smi::FromInt(0);
+       !o->IsUndefined();
        o = JSArrayBuffer::cast(o)->weak_next()) {
     count++;
   }
@@ -54,7 +54,7 @@
 
 static bool HasArrayBufferInWeakList(Heap* heap, JSArrayBuffer* ab) {
   for (Object* o = heap->array_buffers_list();
-       o != Smi::FromInt(0);
+       !o->IsUndefined();
        o = JSArrayBuffer::cast(o)->weak_next()) {
     if (ab == o) return true;
   }
@@ -65,7 +65,7 @@
 static int CountTypedArrays(JSArrayBuffer* array_buffer) {
   int count = 0;
   for (Object* o = array_buffer->weak_first_array();
-       o != Smi::FromInt(0);
+       !o->IsUndefined();
        o = JSTypedArray::cast(o)->weak_next()) {
     count++;
   }
@@ -76,7 +76,7 @@
 static bool HasTypedArrayInWeakList(JSArrayBuffer* array_buffer,
                                     JSTypedArray* ta) {
   for (Object* o = array_buffer->weak_first_array();
-       o != Smi::FromInt(0);
+       !o->IsUndefined();
        o = JSTypedArray::cast(o)->weak_next()) {
     if (ta == o) return true;
   }
diff --git a/test/mjsunit/compiler/inline-arguments.js b/test/mjsunit/compiler/inline-arguments.js
index df1bd22..75d01b5 100644
--- a/test/mjsunit/compiler/inline-arguments.js
+++ b/test/mjsunit/compiler/inline-arguments.js
@@ -266,3 +266,46 @@
     }
   }
 })();
+
+
+// Test materialization of arguments object with values in registers.
+(function () {
+  "use strict";
+  var forceDeopt = { deopt:false };
+  function inner(a,b,c,d,e,f,g,h,i,j) {
+    var args = arguments;
+    forceDeopt.deopt;
+    assertSame(10, args.length);
+    assertSame(a, args[0]);
+    assertSame(b, args[1]);
+    assertSame(c, args[2]);
+    assertSame(d, args[3]);
+    assertSame(e, args[4]);
+    assertSame(f, args[5]);
+    assertSame(g, args[6]);
+    assertSame(h, args[7]);
+    assertSame(i, args[8]);
+    assertSame(j, args[9]);
+  }
+
+  var a = 0.5;
+  var b = 1.7;
+  var c = 123;
+  function outer() {
+    inner(
+      a - 0.3,  // double in double register
+      b + 2.3,  // integer in double register
+      c + 321,  // integer in general register
+      c - 456,  // integer in stack slot
+      a + 0.1, a + 0.2, a + 0.3, a + 0.4, a + 0.5,
+      a + 0.6   // double in stack slot
+    );
+  }
+
+  outer();
+  outer();
+  %OptimizeFunctionOnNextCall(outer);
+  outer();
+  delete forceDeopt.deopt;
+  outer();
+})();
diff --git a/test/mjsunit/compiler/parallel-proto-change.js b/test/mjsunit/compiler/parallel-proto-change.js
index 74e6d86..aa1ac6d 100644
--- a/test/mjsunit/compiler/parallel-proto-change.js
+++ b/test/mjsunit/compiler/parallel-proto-change.js
@@ -25,7 +25,12 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --allow-natives-syntax --parallel-recompilation
+// Flags: --allow-natives-syntax
+// Flags: --parallel-recompilation --parallel-recompilation-delay=50
+
+function assertUnoptimized(fun) {
+  assertTrue(%GetOptimizationStatus(fun) != 1);
+}
 
 function f(foo) { return foo.bar(); }
 
@@ -36,10 +41,10 @@
 assertEquals(1, f(o));
 
 %OptimizeFunctionOnNextCall(f, "parallel");
-assertEquals(1, f(o));
-// Change the prototype chain during optimization.
+assertEquals(1, f(o));     // Trigger optimization.
+assertUnoptimized(f);      // Optimization not yet done.
+// Change the prototype chain during optimization to trigger map invalidation.
 o.__proto__.__proto__ = { bar: function() { return 2; } };
-
-%WaitUntilOptimized(f);
-
+%CompleteOptimization(f);  // Conclude optimization with...
+assertUnoptimized(f);      // ... bailing out due to map dependency.
 assertEquals(2, f(o));
diff --git a/test/mjsunit/harmony/generators-iteration.js b/test/mjsunit/harmony/generators-iteration.js
index 01facd0..2ca35f2 100644
--- a/test/mjsunit/harmony/generators-iteration.js
+++ b/test/mjsunit/harmony/generators-iteration.js
@@ -324,6 +324,28 @@
     "foo",
     [2, "1foo3", 5, "4foo6", "foofoo"]);
 
+// Generator function instances.
+TestGenerator(GeneratorFunction(),
+              [undefined],
+              "foo",
+              [undefined]);
+
+TestGenerator(new GeneratorFunction(),
+              [undefined],
+              "foo",
+              [undefined]);
+
+TestGenerator(GeneratorFunction('yield 1;'),
+              [1, undefined],
+              "foo",
+              [1, undefined]);
+
+TestGenerator(
+    function() { return GeneratorFunction('x', 'y', 'yield x + y;')(1, 2) },
+    [3, undefined],
+    "foo",
+    [3, undefined]);
+
 function TestTryCatch(instantiate) {
   function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; }
   function Sentinel() {}
diff --git a/test/mjsunit/harmony/generators-runtime.js b/test/mjsunit/harmony/generators-runtime.js
index 7667deb..aef063b 100644
--- a/test/mjsunit/harmony/generators-runtime.js
+++ b/test/mjsunit/harmony/generators-runtime.js
@@ -110,6 +110,9 @@
   // Not all functions are generators.
   assertTrue(f instanceof Function);  // Sanity check.
   assertTrue(!(f instanceof GeneratorFunction));
+
+  assertTrue((new GeneratorFunction()) instanceof GeneratorFunction);
+  assertTrue(GeneratorFunction() instanceof GeneratorFunction);
 }
 TestGeneratorFunction();
 
diff --git a/test/mjsunit/harmony/iteration-syntax.js b/test/mjsunit/harmony/iteration-syntax.js
index 21149c0..3bda78e 100644
--- a/test/mjsunit/harmony/iteration-syntax.js
+++ b/test/mjsunit/harmony/iteration-syntax.js
@@ -54,6 +54,11 @@
 assertThrows("function f() { for (let of y) { } }", SyntaxError);
 assertThrows("function f() { for (let of of) { } }", SyntaxError);
 
+assertThrows("function f() { for (x = 3 of y) { } }", SyntaxError);
+assertThrows("function f() { for (var x = 3 of y) { } }", SyntaxError);
+assertThrows("function f() { for (let x = 3 of y) { } }", SyntaxError);
+
+
 // Alack, this appears to be valid.
 function f() { for (of of y) { } }
 function f() { for (let of of y) { } }
diff --git a/test/mjsunit/manual-parallel-recompile.js b/test/mjsunit/manual-parallel-recompile.js
index 8d660e0..f090ff4 100644
--- a/test/mjsunit/manual-parallel-recompile.js
+++ b/test/mjsunit/manual-parallel-recompile.js
@@ -25,12 +25,17 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --allow-natives-syntax --expose-gc --parallel-recompilation
+// Flags: --allow-natives-syntax --expose-gc
+// Flags: --parallel-recompilation --parallel-recompilation-delay=50
 
 function assertUnoptimized(fun) {
   assertTrue(%GetOptimizationStatus(fun) != 1);
 }
 
+function assertOptimized(fun) {
+  assertTrue(%GetOptimizationStatus(fun) != 2);
+}
+
 function f(x) {
   var xx = x * x;
   var xxstr = xx.toString();
@@ -53,10 +58,13 @@
 
 %OptimizeFunctionOnNextCall(f, "parallel");
 %OptimizeFunctionOnNextCall(g, "parallel");
-f(g(2));
+f(g(2));  // Trigger optimization.
 
-assertUnoptimized(f);
+assertUnoptimized(f);  // Not yet optimized.
 assertUnoptimized(g);
 
-%WaitUntilOptimized(f);
-%WaitUntilOptimized(g);
+%CompleteOptimization(f);  // Wait till optimized code is installed.
+%CompleteOptimization(g);
+
+assertOptimized(f);  // Optimized now.
+assertOptimized(g);
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 8d6274b..585d503 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -47,10 +47,6 @@
 stack-traces-gc: PASS || FAIL
 
 ##############################################################################
-# TODO(wingo): Re-enable when GC bug from r15060 is solved.
-harmony/generators-iteration: SKIP
-
-##############################################################################
 # Too slow in debug mode with --stress-opt mode.
 compiler/regress-stacktrace-methods: PASS, SKIP if $mode == debug
 compiler/regress-funcaller: PASS, SKIP if $mode == debug
diff --git a/test/mjsunit/parallel-initial-prototype-change.js b/test/mjsunit/parallel-initial-prototype-change.js
new file mode 100644
index 0000000..5544beb
--- /dev/null
+++ b/test/mjsunit/parallel-initial-prototype-change.js
@@ -0,0 +1,50 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+// Flags: --parallel-recompilation --parallel-recompilation-delay=50
+
+function assertUnoptimized(fun) {
+  assertTrue(%GetOptimizationStatus(fun) != 1);
+}
+
+function f1(a, i) {
+  return a[i] + 0.5;
+}
+
+var arr = [0.0,,2.5];
+assertEquals(0.5, f1(arr, 0));
+assertEquals(0.5, f1(arr, 0));
+
+// Optimized code of f1 depends on initial object and array maps.
+%OptimizeFunctionOnNextCall(f1, "parallel");
+assertEquals(0.5, f1(arr, 0));
+assertUnoptimized(f1);      // Not yet optimized.
+Object.prototype[1] = 1.5;  // Invalidate current initial object map.
+assertEquals(2, f1(arr, 1));
+%CompleteOptimization(f1);  // Conclude optimization with...
+assertUnoptimized(f1);      // ... bailing out due to map dependency.
diff --git a/test/mjsunit/parallel-invalidate-transition-map.js b/test/mjsunit/parallel-invalidate-transition-map.js
new file mode 100644
index 0000000..42a266f
--- /dev/null
+++ b/test/mjsunit/parallel-invalidate-transition-map.js
@@ -0,0 +1,56 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --track-fields --track-double-fields --allow-natives-syntax
+// Flags: --parallel-recompilation --parallel-recompilation-delay=50
+
+function assertUnoptimized(fun) {
+  assertTrue(%GetOptimizationStatus(fun) != 1);
+}
+
+function new_object() {
+  var o = {};
+  o.a = 1;
+  o.b = 2;
+  return o;
+}
+
+function add_field(obj) {
+  obj.c = 3;
+}
+
+add_field(new_object());
+add_field(new_object());
+%OptimizeFunctionOnNextCall(add_field, "parallel");
+
+var o = new_object();
+add_field(o);                      // Trigger optimization.
+assertUnoptimized(add_field);      // Not yet optimized.
+o.c = 2.2;                         // Invalidate transition map.
+%CompleteOptimization(add_field);  // Conclude optimization with...
+assertUnoptimized(add_field);      // ... bailing out due to map dependency.
+
diff --git a/test/mjsunit/parallel-optimize-disabled.js b/test/mjsunit/parallel-optimize-disabled.js
index 86b375c..479684d 100644
--- a/test/mjsunit/parallel-optimize-disabled.js
+++ b/test/mjsunit/parallel-optimize-disabled.js
@@ -43,4 +43,4 @@
 %OptimizeFunctionOnNextCall(g, "parallel");
 f(0);  // g() is disabled for optimization on inlining attempt.
 // Attempt to optimize g() should not run into any assertion.
-%WaitUntilOptimized(g);
+%CompleteOptimization(g);
diff --git a/test/mjsunit/regress/regress-crbug-245480.js b/test/mjsunit/regress/regress-crbug-245480.js
new file mode 100644
index 0000000..4769486
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-245480.js
@@ -0,0 +1,90 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --smi-only-arrays --expose-gc
+// Flags: --track-allocation-sites --noalways-opt
+
+// Test element kind of objects.
+// Since --smi-only-arrays affects builtins, its default setting at compile
+// time sticks if built with snapshot.  If --smi-only-arrays is deactivated
+// by default, only a no-snapshot build actually has smi-only arrays enabled
+// in this test case.  Depending on whether smi-only arrays are actually
+// enabled, this test takes the appropriate code path to check smi-only arrays.
+
+// support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
+support_smi_only_arrays = true;
+
+if (support_smi_only_arrays) {
+  print("Tests include smi-only arrays.");
+} else {
+  print("Tests do NOT include smi-only arrays.");
+}
+
+function isHoley(obj) {
+  if (%HasFastHoleyElements(obj)) return true;
+  return false;
+}
+
+function assertHoley(obj, name_opt) {
+  assertEquals(true, isHoley(obj), name_opt);
+}
+
+function assertNotHoley(obj, name_opt) {
+  assertEquals(false, isHoley(obj), name_opt);
+}
+
+if (support_smi_only_arrays) {
+  function create_array(arg) {
+    return new Array(arg);
+  }
+
+  obj = create_array(0);
+  assertNotHoley(obj);
+  create_array(0);
+  %OptimizeFunctionOnNextCall(create_array);
+  obj = create_array(10);
+  assertHoley(obj);
+}
+
+// The code below would assert in debug or crash in release
+function f(length) {
+  return new Array(length)
+}
+
+f(0);
+f(0);
+%OptimizeFunctionOnNextCall(f);
+var a = f(10);
+
+function g(a) {
+  return a[0];
+}
+
+var b = [0];
+g(b);
+g(b);
+assertEquals(undefined, g(a));
\ No newline at end of file
diff --git a/tools/v8-info.sh b/tools/v8-info.sh
new file mode 100755
index 0000000..1f25d14
--- /dev/null
+++ b/tools/v8-info.sh
@@ -0,0 +1,161 @@
+#!/bin/bash
+# Copyright 2013 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#     * Neither the name of Google Inc. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+########## Global variable definitions
+
+BASE_URL="https://code.google.com/p/v8/source/list"
+VERSION="src/version.cc"
+MAJOR="MAJOR_VERSION"
+MINOR="MINOR_VERSION"
+BUILD="BUILD_NUMBER"
+PATCH="PATCH_LEVEL"
+
+V8="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+
+########## Function definitions
+
+cd $V8
+
+usage() {
+cat << EOF
+usage: $0 OPTIONS
+
+Fetches V8 revision information from a git-svn checkout.
+
+OPTIONS:
+  -h    Show this message.
+
+  -i    Print revision info for all branches matching the V8 version.
+          Example usage: $0 -i 3.19.10$
+          Output format: [Git hash] [SVN revision] [V8 version]
+
+  -v    Print the V8 version tag for a trunk SVN revision.
+          Example usage: $0 -v 14981
+          Output format: [V8 version]
+
+  -m    Print all patches that were merged to the specified V8 branch.
+          Example usage: $0 -m 3.18
+          Output format: [V8 version] [SVN revision] [SVN patch merged]*.
+
+  -p    Print all patches merged to a specific V8 point-release.
+          Example usage: $0 -p 3.19.12.1
+          Output format: [SVN patch merged]*
+
+  -u    Print a link to all SVN revisions between two V8 revision tags.
+          Example usage: $0 -u 3.19.10:3.19.11
+EOF
+}
+
+tags() {
+  git for-each-ref --format="%(objectname) %(refname:short)" refs/remotes/svn
+}
+
+tag_revision() {
+  cut -d" " -f1
+}
+
+tag_log() {
+  git log --format="%h %ci %ce %s" -1 $1
+}
+
+v8_hash() {
+  tags | grep "svn/tags/$1$" | tag_revision
+}
+
+point_merges() {
+  echo $1 | grep -o "r[0-9]\+"
+}
+
+hash_to_svn() {
+  git svn log -1 --oneline $1 | cut -d" " -f1
+}
+
+tag_version() {
+  tags | grep svn/tags/$1 | while read tag; do
+    id=$(echo $tag | grep -o "[^/]*$")
+    rev=$(echo $tag | tag_revision)
+    svn=$(hash_to_svn $rev)
+    echo $rev $svn $id
+  done
+}
+
+svn_rev() {
+  git svn find-rev $2 svn/$1
+}
+
+v8_rev() {
+  cd $(git rev-parse --show-toplevel)
+  rev=$(git show $1:$VERSION \
+      | grep "#define" \
+      | grep "$MAJOR\|$MINOR\|$BUILD\|$PATCH" \
+      | grep -o "[0-9]\+$" \
+      | tr "\\n" ".")
+  echo ${rev%?}
+}
+
+merges_to_branch() {
+  git cherry -v svn/trunk svn/$1 | while read merge; do
+    h=$(echo $merge | cut -d" " -f2)
+    svn=$(svn_rev $1 $h)
+    merges=$(echo $merge | grep -o "r[0-9]\+")
+    rev=$(v8_rev $h)
+    echo $rev r$svn $merges
+  done
+}
+
+url_for() {
+  first=$(svn_rev trunk $(v8_hash $(echo $1 | cut -d":" -f1)))
+  last=$(svn_rev trunk $(v8_hash $(echo $1 | cut -d":" -f2)))
+  num=$[ $last - $first]
+  echo "$BASE_URL?num=$num&start=$last"
+}
+
+########## Option parsing
+
+while getopts ":hi:v:m:p:u:" OPTION ; do
+  case $OPTION in
+    h)  usage
+        exit 0
+        ;;
+    i)  tag_version $OPTARG
+        ;;
+    v)  v8_rev $(svn_rev trunk r$OPTARG)
+        ;;
+    m)  merges_to_branch $OPTARG
+        ;;
+    p)  echo $(point_merges "$(tag_log $(v8_hash $OPTARG)^1)")
+        ;;
+    u)  url_for $OPTARG
+        ;;
+    ?)  echo "Illegal option: -$OPTARG"
+        usage
+        exit 1
+        ;;
+  esac
+done
diff --git a/tools/v8-rolls.sh b/tools/v8-rolls.sh
new file mode 100755
index 0000000..590e05c
--- /dev/null
+++ b/tools/v8-rolls.sh
@@ -0,0 +1,120 @@
+#!/bin/bash
+# Copyright 2013 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#     * Neither the name of Google Inc. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+########## Global variable definitions
+
+DEPS_STRING='"v8_revision":'
+INFO=tools/v8-info.sh
+
+V8="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+
+########## Function definitions
+
+usage() {
+cat << EOF
+usage: $0 OPTIONS
+
+Run in chromium/src to get information about V8 rolls.
+
+OPTIONS:
+  -h    Show this message.
+  -n    Number of rolls to print information about.
+  -s    Chromium git hash to start printing V8 information about.
+EOF
+}
+
+v8_line() {
+  git show $1:DEPS | grep -n $DEPS_STRING | cut -d":" -f1
+}
+
+v8_info() {
+  git blame -L$(v8_line $1),+1 $1 DEPS | grep $DEPS_STRING
+}
+
+v8_svn() {
+  sed -e 's/^.*"\([0-9]\+\)",$/\1/'
+}
+
+v8_roll() {
+  cut -d" " -f1
+}
+
+find_rev() {
+  git svn find-rev $1
+}
+
+msg() {
+  msg=$(git log --format="%h %ci %ce" -1 $1)
+  h=$(echo $msg | cut -d" " -f1)
+  d=$(echo $msg | cut -d" " -f2)
+  t=$(echo $msg | cut -d" " -f3)
+  a=$(echo $msg | cut -d" " -f5)
+  a1=$(echo $a | cut -d"@" -f1)
+  a2=$(echo $a | cut -d"@" -f2)
+  echo $h $d $t $a1@$a2
+}
+
+v8_revision() {
+  cd $V8
+  $INFO -v $1
+}
+
+rolls() {
+  roll=$2
+  for i in $(seq 1 $1); do
+    info=$(v8_info $roll)
+    roll=$(echo $info | v8_roll $roll)
+    trunk=$(echo $info | v8_svn $roll)
+    echo "$(v8_revision $trunk) $trunk $(find_rev $roll) $(msg $roll)"
+    roll=$roll^1
+  done
+}
+
+########## Option parsing
+
+REVISIONS=1
+START=HEAD
+
+while getopts ":hn:s:" OPTION ; do
+  case $OPTION in
+    h)  usage
+        exit 0
+        ;;
+    n) REVISIONS=$OPTARG
+        ;;
+    s) START=$OPTARG
+        ;;
+    ?)  echo "Illegal option: -$OPTARG"
+        usage
+        exit 1
+        ;;
+  esac
+done
+
+rolls $REVISIONS $START