Version 3.19.7

Added support for //# sourceURL similar to deprecated //@ sourceURL one. (issue 2702)

Made sure IfBuilder::Return clears the current block. (Chromium issue 243868)

Fixed two CPU profiler tests on ARM and MIPS simulators (issue 2628)

Fixed idle incremental GC for large objects. (Chromium issue 241815)

Disabled --optimize-constructed-arrays due to crashes (Chromium issue 244461)

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@14900 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index a5ef054..c2c7930 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -625,23 +625,19 @@
 }
 
 
-void V8::MakeWeak(i::Isolate* isolate,
-                  i::Object** object,
+void V8::MakeWeak(i::Object** object,
                   void* parameters,
                   RevivableCallback weak_reference_callback,
                   NearDeathCallback near_death_callback) {
-  ASSERT(isolate == i::Isolate::Current());
-  LOG_API(isolate, "MakeWeak");
-  isolate->global_handles()->MakeWeak(object,
-                                      parameters,
-                                      weak_reference_callback,
-                                      near_death_callback);
+  i::GlobalHandles::MakeWeak(object,
+                             parameters,
+                             weak_reference_callback,
+                             near_death_callback);
 }
 
 
-void V8::ClearWeak(i::Isolate* isolate, i::Object** obj) {
-  LOG_API(isolate, "ClearWeak");
-  isolate->global_handles()->ClearWeakness(obj);
+void V8::ClearWeak(i::Object** obj) {
+  i::GlobalHandles::ClearWeakness(obj);
 }
 
 
@@ -683,19 +679,7 @@
 
 
 void HandleScope::Leave() {
-  v8::ImplementationUtilities::HandleScopeData* current =
-      isolate_->handle_scope_data();
-  current->level--;
-  ASSERT(current->level >= 0);
-  current->next = prev_next_;
-  if (current->limit != prev_limit_) {
-    current->limit = prev_limit_;
-    i::HandleScope::DeleteExtensions(isolate_);
-  }
-
-#ifdef ENABLE_EXTRA_CHECKS
-  i::HandleScope::ZapRange(prev_next_, prev_limit_);
-#endif
+  return i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
 }
 
 
@@ -5104,8 +5088,14 @@
     UNREACHABLE();
   }
   virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
+#ifdef V8_USE_OLD_STYLE_PERSISTENT_HANDLE_VISITORS
     visitor_->VisitPersistentHandle(ToApi<Value>(i::Handle<i::Object>(p)),
                                     class_id);
+#else
+    Value* value = ToApi<Value>(i::Handle<i::Object>(p));
+    visitor_->VisitPersistentHandle(
+        reinterpret_cast<Persistent<Value>*>(&value), class_id);
+#endif
   }
  private:
   PersistentHandleVisitor* visitor_;
@@ -6374,42 +6364,6 @@
 }
 
 
-void V8::AddObjectGroup(Persistent<Value>* objects,
-                        size_t length,
-                        RetainedObjectInfo* info) {
-  i::Isolate* isolate = i::Isolate::Current();
-  if (IsDeadCheck(isolate, "v8::V8::AddObjectGroup()")) return;
-  STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
-  isolate->global_handles()->AddObjectGroup(
-      reinterpret_cast<i::Object***>(objects), length, info);
-}
-
-
-void V8::AddObjectGroup(Isolate* exported_isolate,
-                        Persistent<Value>* objects,
-                        size_t length,
-                        RetainedObjectInfo* info) {
-  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
-  ASSERT(isolate == i::Isolate::Current());
-  if (IsDeadCheck(isolate, "v8::V8::AddObjectGroup()")) return;
-  STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
-  isolate->global_handles()->AddObjectGroup(
-      reinterpret_cast<i::Object***>(objects), length, info);
-}
-
-
-void V8::AddImplicitReferences(Persistent<Object> parent,
-                               Persistent<Value>* children,
-                               size_t length) {
-  i::Isolate* isolate = i::Isolate::Current();
-  if (IsDeadCheck(isolate, "v8::V8::AddImplicitReferences()")) return;
-  STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
-  isolate->global_handles()->AddImplicitReferences(
-      i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*parent)).location(),
-      reinterpret_cast<i::Object***>(children), length);
-}
-
-
 intptr_t Isolate::AdjustAmountOfExternalAllocatedMemory(
     intptr_t change_in_bytes) {
   i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
diff --git a/src/api.h b/src/api.h
index 12d6e3d..62380ce 100644
--- a/src/api.h
+++ b/src/api.h
@@ -637,7 +637,12 @@
     internal::Object** block_limit = block_start + kHandleBlockSize;
 #ifdef DEBUG
     // NoHandleAllocation may make the prev_limit to point inside the block.
-    if (block_start <= prev_limit && prev_limit <= block_limit) break;
+    if (block_start <= prev_limit && prev_limit <= block_limit) {
+#ifdef ENABLE_EXTRA_CHECKS
+      internal::HandleScope::ZapRange(prev_limit, block_limit);
+#endif
+      break;
+    }
 #else
     if (prev_limit == block_limit) break;
 #endif
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 201ecb2..20d4da5 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -45,7 +45,6 @@
   static Register registers[] = { r3, r2, r1 };
   descriptor->register_param_count_ = 3;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry;
 }
@@ -57,7 +56,6 @@
   static Register registers[] = { r3, r2, r1, r0 };
   descriptor->register_param_count_ = 4;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry;
 }
@@ -80,7 +78,6 @@
   static Register registers[] = { r0 };
   descriptor->register_param_count_ = 1;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ = NULL;
 }
 
@@ -91,7 +88,6 @@
   static Register registers[] = { r1 };
   descriptor->register_param_count_ = 1;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ = NULL;
 }
 
@@ -175,6 +171,19 @@
 }
 
 
+void ToBooleanStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { r0 };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(ToBooleanIC_Miss);
+  descriptor->SetMissHandler(
+      ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
+}
+
+
 #define __ ACCESS_MASM(masm)
 
 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
@@ -1207,116 +1216,6 @@
 }
 
 
-// The stub expects its argument in the tos_ register and returns its result in
-// it, too: zero for false, and a non-zero value for true.
-void ToBooleanStub::Generate(MacroAssembler* masm) {
-  // This stub overrides SometimesSetsUpAFrame() to return false.  That means
-  // we cannot call anything that could cause a GC from this stub.
-  Label patch;
-  const Register map = r9.is(tos_) ? r7 : r9;
-
-  // undefined -> false.
-  CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
-
-  // Boolean -> its value.
-  CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
-  CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
-
-  // 'null' -> false.
-  CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
-
-  if (types_.Contains(SMI)) {
-    // Smis: 0 -> false, all other -> true
-    __ SmiTst(tos_);
-    // tos_ contains the correct return value already
-    __ Ret(eq);
-  } else if (types_.NeedsMap()) {
-    // If we need a map later and have a Smi -> patch.
-    __ JumpIfSmi(tos_, &patch);
-  }
-
-  if (types_.NeedsMap()) {
-    __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
-
-    if (types_.CanBeUndetectable()) {
-      __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
-      __ tst(ip, Operand(1 << Map::kIsUndetectable));
-      // Undetectable -> false.
-      __ mov(tos_, Operand::Zero(), LeaveCC, ne);
-      __ Ret(ne);
-    }
-  }
-
-  if (types_.Contains(SPEC_OBJECT)) {
-    // Spec object -> true.
-    __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
-    // tos_ contains the correct non-zero return value already.
-    __ Ret(ge);
-  }
-
-  if (types_.Contains(STRING)) {
-    // String value -> false iff empty.
-    __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
-    __ ldr(tos_, FieldMemOperand(tos_, String::kLengthOffset), lt);
-    __ Ret(lt);  // the string length is OK as the return value
-  }
-
-  if (types_.Contains(HEAP_NUMBER)) {
-    // Heap number -> false iff +0, -0, or NaN.
-    Label not_heap_number;
-    __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
-    __ b(ne, &not_heap_number);
-
-    __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset));
-    __ VFPCompareAndSetFlags(d1, 0.0);
-    // "tos_" is a register, and contains a non zero value by default.
-    // Hence we only need to overwrite "tos_" with zero to return false for
-    // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
-    __ mov(tos_, Operand::Zero(), LeaveCC, eq);  // for FP_ZERO
-    __ mov(tos_, Operand::Zero(), LeaveCC, vs);  // for FP_NAN
-    __ Ret();
-    __ bind(&not_heap_number);
-  }
-
-  __ bind(&patch);
-  GenerateTypeTransition(masm);
-}
-
-
-void ToBooleanStub::CheckOddball(MacroAssembler* masm,
-                                 Type type,
-                                 Heap::RootListIndex value,
-                                 bool result) {
-  if (types_.Contains(type)) {
-    // If we see an expected oddball, return its ToBoolean value tos_.
-    __ LoadRoot(ip, value);
-    __ cmp(tos_, ip);
-    // The value of a root is never NULL, so we can avoid loading a non-null
-    // value into tos_ when we want to return 'true'.
-    if (!result) {
-      __ mov(tos_, Operand::Zero(), LeaveCC, eq);
-    }
-    __ Ret(eq);
-  }
-}
-
-
-void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
-  if (!tos_.is(r3)) {
-    __ mov(r3, Operand(tos_));
-  }
-  __ mov(r2, Operand(Smi::FromInt(tos_.code())));
-  __ mov(r1, Operand(Smi::FromInt(types_.ToByte())));
-  __ Push(r3, r2, r1);
-  // Patch the caller to an appropriate specialized stub and return the
-  // operation result to the caller of the stub.
-  __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
-      3,
-      1);
-}
-
-
 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
   // We don't allow a GC during a store buffer overflow so there is no need to
   // store the registers in any particular way, but we do have to store and
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 967a4d4..2b04914 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -678,8 +678,8 @@
                                Label* if_true,
                                Label* if_false,
                                Label* fall_through) {
-  ToBooleanStub stub(result_register());
-  __ CallStub(&stub, condition->test_id());
+  Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
+  CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
   __ tst(result_register(), result_register());
   Split(ne, if_true, if_false, fall_through);
 }
@@ -2050,8 +2050,8 @@
       Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
       CallIC(done_ic);                                   // result.done in r0
       __ add(sp, sp, Operand(kPointerSize));             // drop LoadIC state
-      ToBooleanStub stub(r0);
-      __ CallStub(&stub);
+      Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
+      CallIC(bool_ic);
       __ cmp(r0, Operand(0));
       __ b(eq, &l_try);
 
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 2ad6eb4..c1f24c9 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -2035,7 +2035,7 @@
   } else if (input_rep.IsInteger32()) {
     return DefineAsRegister(new(zone()) LClampIToUint8(reg));
   } else {
-    ASSERT(input_rep.IsTagged());
+    ASSERT(input_rep.IsSmiOrTagged());
     // Register allocator doesn't (yet) support allocation of double
     // temps. Reserve d1 explicitly.
     LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(d11));
@@ -2053,11 +2053,13 @@
 
 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
   Representation r = instr->representation();
-  if (r.IsInteger32()) {
+  if (r.IsSmi()) {
+    return DefineAsRegister(new(zone()) LConstantS);
+  } else if (r.IsInteger32()) {
     return DefineAsRegister(new(zone()) LConstantI);
   } else if (r.IsDouble()) {
     return DefineAsRegister(new(zone()) LConstantD);
-  } else if (r.IsSmiOrTagged()) {
+  } else if (r.IsTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
     UNREACHABLE();
@@ -2483,7 +2485,7 @@
     index = UseOrConstant(instr->index());
   } else {
     length = UseTempRegister(instr->length());
-    index = Use(instr->index());
+    index = UseRegisterAtStart(instr->index());
   }
   return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
 }
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index e4016c4..6ae65e8 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -87,6 +87,7 @@
   V(CmpT)                                       \
   V(ConstantD)                                  \
   V(ConstantI)                                  \
+  V(ConstantS)                                  \
   V(ConstantT)                                  \
   V(Context)                                    \
   V(DebugBreak)                                 \
@@ -1206,6 +1207,15 @@
 };
 
 
+class LConstantS: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
+};
+
+
 class LConstantD: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index c1f6695..06a6506 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -181,6 +181,7 @@
       __ add(fp, sp, Operand(2 * kPointerSize));
     }
     frame_is_built_ = true;
+    info_->AddNoFrameRange(0, masm_->pc_offset());
   }
 
   // Reserve space for the stack slots needed by the code.
@@ -1900,7 +1901,11 @@
 
 
 void LCodeGen::DoConstantI(LConstantI* instr) {
-  ASSERT(instr->result()->IsRegister());
+  __ mov(ToRegister(instr->result()), Operand(instr->value()));
+}
+
+
+void LCodeGen::DoConstantS(LConstantS* instr) {
   __ mov(ToRegister(instr->result()), Operand(instr->value()));
 }
 
@@ -2242,10 +2247,12 @@
 
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsInteger32() || r.IsSmi()) {
+    ASSERT(!info()->IsStub());
     Register reg = ToRegister(instr->value());
     __ cmp(reg, Operand::Zero());
     EmitBranch(true_block, false_block, ne);
   } else if (r.IsDouble()) {
+    ASSERT(!info()->IsStub());
     DwVfpRegister reg = ToDoubleRegister(instr->value());
     // Test the double value. Zero and NaN are false.
     __ VFPCompareAndSetFlags(reg, 0.0);
@@ -2256,9 +2263,11 @@
     Register reg = ToRegister(instr->value());
     HType type = instr->hydrogen()->value()->type();
     if (type.IsBoolean()) {
+      ASSERT(!info()->IsStub());
       __ CompareRoot(reg, Heap::kTrueValueRootIndex);
       EmitBranch(true_block, false_block, eq);
     } else if (type.IsSmi()) {
+      ASSERT(!info()->IsStub());
       __ cmp(reg, Operand::Zero());
       EmitBranch(true_block, false_block, ne);
     } else {
@@ -2947,8 +2956,8 @@
   int no_frame_start = -1;
   if (NeedsEagerFrame()) {
     __ mov(sp, fp);
-    __ ldm(ia_w, sp, fp.bit() | lr.bit());
     no_frame_start = masm_->pc_offset();
+    __ ldm(ia_w, sp, fp.bit() | lr.bit());
   }
   if (instr->has_constant_parameter_count()) {
     int parameter_count = ToInteger32(instr->constant_parameter_count());
@@ -4967,7 +4976,7 @@
 
 void LCodeGen::EmitNumberUntagD(Register input_reg,
                                 DwVfpRegister result_reg,
-                                bool deoptimize_on_undefined,
+                                bool allow_undefined_as_nan,
                                 bool deoptimize_on_minus_zero,
                                 LEnvironment* env,
                                 NumberUntagDMode mode) {
@@ -4987,7 +4996,7 @@
     __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
     __ cmp(scratch, Operand(ip));
-    if (deoptimize_on_undefined) {
+    if (!allow_undefined_as_nan) {
       DeoptimizeIf(ne, env);
     } else {
       Label heap_number, convert;
@@ -5157,7 +5166,7 @@
   }
 
   EmitNumberUntagD(input_reg, result_reg,
-                   instr->hydrogen()->deoptimize_on_undefined(),
+                   instr->hydrogen()->allow_undefined_as_nan(),
                    instr->hydrogen()->deoptimize_on_minus_zero(),
                    instr->environment(),
                    mode);
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 58aa93d..f282847 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -335,7 +335,7 @@
   void EmitBranch(int left_block, int right_block, Condition cc);
   void EmitNumberUntagD(Register input,
                         DwVfpRegister result,
-                        bool deoptimize_on_undefined,
+                        bool allow_undefined_as_nan,
                         bool deoptimize_on_minus_zero,
                         LEnvironment* env,
                         NumberUntagDMode mode);
diff --git a/src/array.js b/src/array.js
index a3674e8..dcfcde5 100644
--- a/src/array.js
+++ b/src/array.js
@@ -395,6 +395,23 @@
 }
 
 
+function ObservedArrayPop(n) {
+  n--;
+  var value = this[n];
+
+  EnqueueSpliceRecord(this, n, [value], 1, 0);
+
+  try {
+    BeginPerformSplice(this);
+    delete this[n];
+    this.length = n;
+  } finally {
+    EndPerformSplice(this);
+  }
+
+  return value;
+}
+
 // Removes the last element from the array and returns it. See
 // ECMA-262, section 15.4.4.6.
 function ArrayPop() {
@@ -408,6 +425,10 @@
     this.length = n;
     return;
   }
+
+  if (%IsObserved(this))
+    return ObservedArrayPop.call(this, n);
+
   n--;
   var value = this[n];
   delete this[n];
@@ -424,7 +445,6 @@
 
   try {
     BeginPerformSplice(this);
-
     for (var i = 0; i < m; i++) {
       this[i+n] = %_Arguments(i);
     }
@@ -558,6 +578,22 @@
 }
 
 
+function ObservedArrayShift(len) {
+  var first = this[0];
+
+  EnqueueSpliceRecord(this, 0, [first], 1, 0);
+
+  try {
+    BeginPerformSplice(this);
+    SimpleMove(this, 0, 1, len, 0);
+    this.length = len - 1;
+  } finally {
+    EndPerformSplice(this);
+  }
+
+  return first;
+}
+
 function ArrayShift() {
   if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
     throw MakeTypeError("called_on_null_or_undefined",
@@ -571,9 +607,12 @@
     return;
   }
 
+  if (%IsObserved(this))
+    return ObservedArrayShift.call(this, len);
+
   var first = this[0];
 
-  if (IS_ARRAY(this) && !%IsObserved(this)) {
+  if (IS_ARRAY(this)) {
     SmartMove(this, 0, 1, len, 0);
   } else {
     SimpleMove(this, 0, 1, len, 0);
@@ -584,6 +623,25 @@
   return first;
 }
 
+function ObservedArrayUnshift() {
+  var len = TO_UINT32(this.length);
+  var num_arguments = %_ArgumentsLength();
+
+  EnqueueSpliceRecord(this, 0, [], 0, num_arguments);
+
+  try {
+    BeginPerformSplice(this);
+    SimpleMove(this, 0, 0, len, num_arguments);
+    for (var i = 0; i < num_arguments; i++) {
+      this[i] = %_Arguments(i);
+    }
+    this.length = len + num_arguments;
+  } finally {
+    EndPerformSplice(this);
+  }
+
+  return len + num_arguments;
+}
 
 function ArrayUnshift(arg1) {  // length == 1
   if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
@@ -591,10 +649,13 @@
                         ["Array.prototype.unshift"]);
   }
 
+  if (%IsObserved(this))
+    return ObservedArrayUnshift.apply(this, arguments);
+
   var len = TO_UINT32(this.length);
   var num_arguments = %_ArgumentsLength();
 
-  if (IS_ARRAY(this) && !%IsObserved(this)) {
+  if (IS_ARRAY(this)) {
     SmartMove(this, 0, 0, len, num_arguments);
   } else {
     SimpleMove(this, 0, 0, len, num_arguments);
@@ -655,52 +716,100 @@
 }
 
 
-function ArraySplice(start, delete_count) {
-  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
-    throw MakeTypeError("called_on_null_or_undefined",
-                        ["Array.prototype.splice"]);
-  }
-
-  var num_arguments = %_ArgumentsLength();
-
-  var len = TO_UINT32(this.length);
-  var start_i = TO_INTEGER(start);
-
+function ComputeSpliceStartIndex(start_i, len) {
   if (start_i < 0) {
     start_i += len;
-    if (start_i < 0) start_i = 0;
-  } else {
-    if (start_i > len) start_i = len;
+    return start_i < 0 ? 0 : start_i;
   }
 
+  return start_i > len ? len : start_i;
+}
+
+
+function ComputeSpliceDeleteCount(delete_count, num_arguments, len, start_i) {
   // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
   // given as a request to delete all the elements from the start.
   // And it differs from the case of undefined delete count.
   // This does not follow ECMA-262, but we do the same for
   // compatibility.
   var del_count = 0;
-  if (num_arguments == 1) {
-    del_count = len - start_i;
-  } else {
-    del_count = TO_INTEGER(delete_count);
-    if (del_count < 0) del_count = 0;
-    if (del_count > len - start_i) del_count = len - start_i;
-  }
+  if (num_arguments == 1)
+    return len - start_i;
 
+  del_count = TO_INTEGER(delete_count);
+  if (del_count < 0)
+    return 0;
+
+  if (del_count > len - start_i)
+    return len - start_i;
+
+  return del_count;
+}
+
+
+function ObservedArraySplice(start, delete_count) {
+  var num_arguments = %_ArgumentsLength();
+  var len = TO_UINT32(this.length);
+  var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
+  var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
+                                           start_i);
   var deleted_elements = [];
   deleted_elements.length = del_count;
+  var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
 
-  // Number of elements to add.
-  var num_additional_args = 0;
-  if (num_arguments > 2) {
-    num_additional_args = num_arguments - 2;
+  try {
+    BeginPerformSplice(this);
+
+    SimpleSlice(this, start_i, del_count, len, deleted_elements);
+    SimpleMove(this, start_i, del_count, len, num_elements_to_add);
+
+    // Insert the arguments into the resulting array in
+    // place of the deleted elements.
+    var i = start_i;
+    var arguments_index = 2;
+    var arguments_length = %_ArgumentsLength();
+    while (arguments_index < arguments_length) {
+      this[i++] = %_Arguments(arguments_index++);
+    }
+    this.length = len - del_count + num_elements_to_add;
+
+  } finally {
+    EndPerformSplice(this);
+    if (deleted_elements.length || num_elements_to_add) {
+       EnqueueSpliceRecord(this,
+                           start_i,
+                           deleted_elements.slice(),
+                           deleted_elements.length,
+                           num_elements_to_add);
+    }
   }
 
-  var use_simple_splice = true;
+  // Return the deleted elements.
+  return deleted_elements;
+}
 
+
+function ArraySplice(start, delete_count) {
+  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
+    throw MakeTypeError("called_on_null_or_undefined",
+                        ["Array.prototype.splice"]);
+  }
+
+  if (%IsObserved(this))
+    return ObservedArraySplice.apply(this, arguments);
+
+  var num_arguments = %_ArgumentsLength();
+  var len = TO_UINT32(this.length);
+  var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
+  var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
+                                           start_i);
+  var deleted_elements = [];
+  deleted_elements.length = del_count;
+  var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
+
+  var use_simple_splice = true;
   if (IS_ARRAY(this) &&
-      !%IsObserved(this) &&
-      num_additional_args !== del_count) {
+      num_elements_to_add !== del_count) {
     // If we are only deleting/moving a few things near the end of the
     // array then the simple version is going to be faster, because it
     // doesn't touch most of the array.
@@ -712,10 +821,10 @@
 
   if (use_simple_splice) {
     SimpleSlice(this, start_i, del_count, len, deleted_elements);
-    SimpleMove(this, start_i, del_count, len, num_additional_args);
+    SimpleMove(this, start_i, del_count, len, num_elements_to_add);
   } else {
     SmartSlice(this, start_i, del_count, len, deleted_elements);
-    SmartMove(this, start_i, del_count, len, num_additional_args);
+    SmartMove(this, start_i, del_count, len, num_elements_to_add);
   }
 
   // Insert the arguments into the resulting array in
@@ -726,7 +835,7 @@
   while (arguments_index < arguments_length) {
     this[i++] = %_Arguments(arguments_index++);
   }
-  this.length = len - del_count + num_additional_args;
+  this.length = len - del_count + num_elements_to_add;
 
   // Return the deleted elements.
   return deleted_elements;
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index d7b74f8..9277719 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1611,14 +1611,12 @@
 
   array_function->shared()->DontAdaptArguments();
 
-  MaybeObject* maybe_map = array_function->initial_map()->Copy();
-  Map* new_map;
-  if (!maybe_map->To(&new_map)) return Handle<JSFunction>::null();
-  new_map->set_elements_kind(elements_kind);
-  array_function->set_initial_map(new_map);
+  Handle<Map> original_map(array_function->initial_map());
+  Handle<Map> initial_map = factory()->CopyMap(original_map);
+  initial_map->set_elements_kind(elements_kind);
+  array_function->set_initial_map(*initial_map);
 
   // Make "length" magic on instances.
-  Handle<Map> initial_map(array_function->initial_map());
   Handle<DescriptorArray> array_descriptors(
       factory()->NewDescriptorArray(0, 1));
   DescriptorArray::WhitenessWitness witness(*array_descriptors);
@@ -1872,14 +1870,11 @@
   {
     Handle<JSFunction> array_function =
         InstallInternalArray(builtins, "InternalArray", FAST_HOLEY_ELEMENTS);
-    if (array_function.is_null()) return false;
     native_context()->set_internal_array_function(*array_function);
   }
 
   {
-    Handle<JSFunction> array_function =
-        InstallInternalArray(builtins, "InternalPackedArray", FAST_ELEMENTS);
-    if (array_function.is_null()) return false;
+    InstallInternalArray(builtins, "InternalPackedArray", FAST_ELEMENTS);
   }
 
   if (FLAG_disable_native_files) {
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 86bf075..9a9f0d5 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -186,11 +186,12 @@
     }
   }
 
-  if (!current_block()->IsFinished()) {
+  if (current_block() != NULL) {
     HReturn* hreturn_instruction = new(zone) HReturn(return_value,
                                                      context_,
                                                      stack_pop_count);
     current_block()->Finish(hreturn_instruction);
+    set_current_block(NULL);
   }
   return true;
 }
@@ -564,16 +565,13 @@
       new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero));
 
   HConstant* max_alloc_length =
-      new(zone()) HConstant(JSObject::kInitialMaxFastElementArray,
-                            Representation::Tagged());
+      new(zone()) HConstant(JSObject::kInitialMaxFastElementArray);
   AddInstruction(max_alloc_length);
   const int initial_capacity = JSArray::kPreallocatedArrayElements;
-  HConstant* initial_capacity_node =
-      new(zone()) HConstant(initial_capacity, Representation::Tagged());
+  HConstant* initial_capacity_node = new(zone()) HConstant(initial_capacity);
   AddInstruction(initial_capacity_node);
 
-  HBoundsCheck* checked_arg = AddBoundsCheck(
-      argument, max_alloc_length, ALLOW_SMI_KEY);
+  HBoundsCheck* checked_arg = AddBoundsCheck(argument, max_alloc_length);
   IfBuilder if_builder(this);
   if_builder.IfCompare(checked_arg, constant_zero, Token::EQ);
   if_builder.Then();
@@ -676,4 +674,24 @@
   return DoGenerateCode(this);
 }
 
+
+template <>
+HValue* CodeStubGraphBuilder<ToBooleanStub>::BuildCodeInitializedStub() {
+  ToBooleanStub* stub = casted_stub();
+
+  IfBuilder if_true(this);
+  if_true.If<HBranch>(GetParameter(0), stub->GetTypes());
+  if_true.Then();
+    if_true.Return(graph()->GetConstant1());
+  if_true.Else();
+  if_true.End();
+  return graph()->GetConstant0();
+}
+
+
+Handle<Code> ToBooleanStub::GenerateCode() {
+  return DoGenerateCode(this);
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 2b96dbf..882d743 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -572,6 +572,14 @@
 }
 
 
+bool ToBooleanStub::Record(Handle<Object> object) {
+  Types old_types(types_);
+  bool to_boolean_value = types_.Record(object);
+  old_types.TraceTransition(types_);
+  return to_boolean_value;
+}
+
+
 void ToBooleanStub::PrintName(StringStream* stream) {
   stream->Add("ToBooleanStub_");
   types_.Print(stream);
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 901751f..513ad9a 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -1816,7 +1816,7 @@
 };
 
 
-class ToBooleanStub: public PlatformCodeStub {
+class ToBooleanStub: public HydrogenCodeStub {
  public:
   enum Type {
     UNDEFINED,
@@ -1850,31 +1850,47 @@
   static Types no_types() { return Types(); }
   static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); }
 
-  explicit ToBooleanStub(Register tos, Types types = Types())
-      : tos_(tos), types_(types) { }
+  explicit ToBooleanStub(Types types = Types())
+      : types_(types) { }
+  explicit ToBooleanStub(Code::ExtraICState state)
+      : types_(static_cast<byte>(state)) { }
 
-  void Generate(MacroAssembler* masm);
+  bool Record(Handle<Object> object);
+  Types GetTypes() { return types_; }
+
+  virtual Handle<Code> GenerateCode();
+  virtual void InitializeInterfaceDescriptor(
+      Isolate* isolate,
+      CodeStubInterfaceDescriptor* descriptor);
+
   virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
   virtual void PrintName(StringStream* stream);
 
   virtual bool SometimesSetsUpAFrame() { return false; }
 
- private:
-  Major MajorKey() { return ToBoolean; }
-  int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) |
-                          types_.ToByte(); }
-
-  virtual void FinishCode(Handle<Code> code) {
-    code->set_to_boolean_state(types_.ToByte());
+  static void InitializeForIsolate(Isolate* isolate) {
+    ToBooleanStub stub;
+    stub.InitializeInterfaceDescriptor(
+        isolate,
+        isolate->code_stub_interface_descriptor(CodeStub::ToBoolean));
   }
 
-  void CheckOddball(MacroAssembler* masm,
-                    Type type,
-                    Heap::RootListIndex value,
-                    bool result);
-  void GenerateTypeTransition(MacroAssembler* masm);
+  static Handle<Code> GetUninitialized(Isolate* isolate) {
+    return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
+  }
 
-  Register tos_;
+  virtual Code::ExtraICState GetExtraICState() {
+    return types_.ToIntegral();
+  }
+
+
+ private:
+  Major MajorKey() { return ToBoolean; }
+  int NotMissMinorKey() { return GetExtraICState(); }
+
+  explicit ToBooleanStub(InitializationState init_state) :
+    HydrogenCodeStub(init_state) {}
+
   Types types_;
 };
 
diff --git a/src/d8.cc b/src/d8.cc
index 149a65f..79244d7 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -40,11 +40,6 @@
 #include <string.h>
 #include <sys/stat.h>
 
-// TODO(dcarney): remove
-#define V8_ALLOW_ACCESS_TO_PERSISTENT_ARROW
-#define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR
-#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT
-
 #ifdef V8_SHARED
 #include <assert.h>
 #endif  // V8_SHARED
@@ -246,7 +241,7 @@
           v8::Local<v8::Context> context =
               v8::Local<v8::Context>::New(isolate, utility_context_);
           v8::Context::Scope context_scope(context);
-          Handle<Object> global = utility_context_->Global();
+          Handle<Object> global = context->Global();
           Handle<Value> fun = global->Get(String::New("Stringify"));
           Handle<Value> argv[1] = { result };
           Handle<Value> s = Handle<Function>::Cast(fun)->Call(global, 1, argv);
@@ -268,8 +263,7 @@
   data_->realm_current_ = 0;
   data_->realm_switch_ = 0;
   data_->realms_ = new Persistent<Context>[1];
-  data_->realms_[0] =
-      Persistent<Context>::New(data_->isolate_, Context::GetEntered());
+  data_->realms_[0].Reset(data_->isolate_, Context::GetEntered());
   data_->realm_shared_.Clear();
 }
 
@@ -326,7 +320,8 @@
   if (index >= data->realm_count_ || data->realms_[index].IsEmpty()) {
     return Throw("Invalid realm index");
   }
-  return data->realms_[index]->Global();
+  return
+      Local<Context>::New(args.GetIsolate(), data->realms_[index])->Global();
 }
 
 
@@ -337,10 +332,12 @@
   Persistent<Context>* old_realms = data->realms_;
   int index = data->realm_count_;
   data->realms_ = new Persistent<Context>[++data->realm_count_];
-  for (int i = 0; i < index; ++i) data->realms_[i] = old_realms[i];
+  for (int i = 0; i < index; ++i) {
+    data->realms_[i].Reset(isolate, old_realms[i]);
+  }
   delete[] old_realms;
   Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
-  data->realms_[index] = Persistent<Context>::New(
+  data->realms_[index].Reset(
       isolate, Context::New(isolate, NULL, global_template));
   return Number::New(index);
 }
@@ -417,7 +414,7 @@
   Isolate* isolate = info.GetIsolate();
   PerIsolateData* data = PerIsolateData::Get(isolate);
   if (!data->realm_shared_.IsEmpty()) data->realm_shared_.Dispose(isolate);
-  data->realm_shared_ = Persistent<Value>::New(isolate, value);
+  data->realm_shared_.Reset(isolate, value);
 }
 
 
@@ -546,8 +543,12 @@
 void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
   HandleScope handle_scope(isolate);
 #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
+  Handle<Context> utility_context;
   bool enter_context = !Context::InContext();
-  if (enter_context) utility_context_->Enter();
+  if (enter_context) {
+    utility_context = Local<Context>::New(isolate, utility_context_);
+    utility_context->Enter();
+  }
 #endif  // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
   v8::String::Utf8Value exception(try_catch->Exception());
   const char* exception_string = ToCString(exception);
@@ -584,7 +585,7 @@
   }
   printf("\n");
 #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
-  if (enter_context) utility_context_->Exit();
+  if (enter_context) utility_context->Exit();
 #endif  // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
 }
 
@@ -594,13 +595,15 @@
                                     Handle<String> text,
                                     Handle<String> full) {
   HandleScope handle_scope(isolate);
-  v8::Local<v8::Context> context =
+  v8::Local<v8::Context> utility_context =
       v8::Local<v8::Context>::New(isolate, utility_context_);
-  v8::Context::Scope context_scope(context);
-  Handle<Object> global = utility_context_->Global();
+  v8::Context::Scope context_scope(utility_context);
+  Handle<Object> global = utility_context->Global();
   Handle<Value> fun = global->Get(String::New("GetCompletions"));
   static const int kArgc = 3;
-  Handle<Value> argv[kArgc] = { evaluation_context_->Global(), text, full };
+  v8::Local<v8::Context> evaluation_context =
+      v8::Local<v8::Context>::New(isolate, evaluation_context_);
+  Handle<Value> argv[kArgc] = { evaluation_context->Global(), text, full };
   Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
   return handle_scope.Close(Handle<Array>::Cast(val));
 }
@@ -613,7 +616,7 @@
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate, utility_context_);
   v8::Context::Scope context_scope(context);
-  Handle<Object> global = utility_context_->Global();
+  Handle<Object> global = context->Global();
   Handle<Value> fun = global->Get(String::New("DebugMessageDetails"));
   static const int kArgc = 1;
   Handle<Value> argv[kArgc] = { message };
@@ -628,7 +631,7 @@
   v8::Local<v8::Context> context =
       v8::Local<v8::Context>::New(isolate, utility_context_);
   v8::Context::Scope context_scope(context);
-  Handle<Object> global = utility_context_->Global();
+  Handle<Object> global = context->Global();
   Handle<Value> fun = global->Get(String::New("DebugCommandToJSONRequest"));
   static const int kArgc = 1;
   Handle<Value> argv[kArgc] = { command };
@@ -753,11 +756,13 @@
   HandleScope scope(isolate);
   // If we use the utility context, we have to set the security tokens so that
   // utility, evaluation and debug context can all access each other.
-  utility_context_->SetSecurityToken(Undefined(isolate));
-  evaluation_context_->SetSecurityToken(Undefined(isolate));
-  v8::Local<v8::Context> context =
+  v8::Local<v8::Context> utility_context =
       v8::Local<v8::Context>::New(isolate, utility_context_);
-  v8::Context::Scope context_scope(context);
+  v8::Local<v8::Context> evaluation_context =
+      v8::Local<v8::Context>::New(isolate, evaluation_context_);
+  utility_context->SetSecurityToken(Undefined(isolate));
+  evaluation_context->SetSecurityToken(Undefined(isolate));
+  v8::Context::Scope context_scope(utility_context);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   if (i::FLAG_debugger) printf("JavaScript debugger enabled\n");
@@ -766,7 +771,7 @@
   debug->Load();
   i::Handle<i::JSObject> js_debug
       = i::Handle<i::JSObject>(debug->debug_context()->global_object());
-  utility_context_->Global()->Set(String::New("$debug"),
+  utility_context->Global()->Set(String::New("$debug"),
                                   Utils::ToLocal(js_debug));
   debug->debug_context()->set_security_token(HEAP->undefined_value());
 #endif  // ENABLE_DEBUGGER_SUPPORT
@@ -1086,8 +1091,7 @@
     return Throw("Error reading file");
   }
   Handle<v8::ArrayBuffer> buffer = ArrayBuffer::New(data, length);
-  v8::Persistent<v8::Value> weak_handle =
-      v8::Persistent<v8::Value>::New(isolate, buffer);
+  v8::Persistent<v8::Value> weak_handle(isolate, buffer);
   weak_handle.MakeWeak(isolate, data, ReadBufferWeakCallback);
   weak_handle.MarkIndependent();
   isolate->AdjustAmountOfExternalAllocatedMemory(length);
diff --git a/src/global-handles.cc b/src/global-handles.cc
index bfd8357..8ed6fc9 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -199,9 +199,9 @@
     set_independent(true);
   }
 
-  void MarkPartiallyDependent(GlobalHandles* global_handles) {
+  void MarkPartiallyDependent() {
     ASSERT(state() != FREE);
-    if (global_handles->isolate()->heap()->InNewSpace(object_)) {
+    if (GetGlobalHandles()->isolate()->heap()->InNewSpace(object_)) {
       set_partially_dependent(true);
     }
   }
@@ -231,8 +231,7 @@
     parameter_or_next_free_.next_free = value;
   }
 
-  void MakeWeak(GlobalHandles* global_handles,
-                void* parameter,
+  void MakeWeak(void* parameter,
                 RevivableCallback weak_reference_callback,
                 NearDeathCallback near_death_callback) {
     ASSERT(state() != FREE);
@@ -248,7 +247,7 @@
     }
   }
 
-  void ClearWeakness(GlobalHandles* global_handles) {
+  void ClearWeakness() {
     ASSERT(state() != FREE);
     set_state(NORMAL);
     set_parameter(NULL);
@@ -296,6 +295,7 @@
 
  private:
   inline NodeBlock* FindBlock();
+  inline GlobalHandles* GetGlobalHandles();
   inline void IncreaseBlockUses();
   inline void DecreaseBlockUses();
 
@@ -400,6 +400,11 @@
 };
 
 
+GlobalHandles* GlobalHandles::Node::GetGlobalHandles() {
+  return FindBlock()->global_handles();
+}
+
+
 GlobalHandles::NodeBlock* GlobalHandles::Node::FindBlock() {
   intptr_t ptr = reinterpret_cast<intptr_t>(this);
   ptr = ptr - index_ * sizeof(Node);
@@ -507,15 +512,14 @@
                              RevivableCallback weak_reference_callback,
                              NearDeathCallback near_death_callback) {
   ASSERT((weak_reference_callback == NULL) != (near_death_callback == NULL));
-  Node::FromLocation(location)->MakeWeak(this,
-                                         parameter,
+  Node::FromLocation(location)->MakeWeak(parameter,
                                          weak_reference_callback,
                                          near_death_callback);
 }
 
 
 void GlobalHandles::ClearWeakness(Object** location) {
-  Node::FromLocation(location)->ClearWeakness(this);
+  Node::FromLocation(location)->ClearWeakness();
 }
 
 
@@ -525,7 +529,7 @@
 
 
 void GlobalHandles::MarkPartiallyDependent(Object** location) {
-  Node::FromLocation(location)->MarkPartiallyDependent(this);
+  Node::FromLocation(location)->MarkPartiallyDependent();
 }
 
 
diff --git a/src/global-handles.h b/src/global-handles.h
index 3cca384..cce4328 100644
--- a/src/global-handles.h
+++ b/src/global-handles.h
@@ -138,10 +138,10 @@
   // function is invoked (for each handle) with the handle and corresponding
   // parameter as arguments.  Note: cleared means set to Smi::FromInt(0). The
   // reason is that Smi::FromInt(0) does not change during garage collection.
-  void MakeWeak(Object** location,
-                void* parameter,
-                RevivableCallback weak_reference_callback,
-                NearDeathCallback near_death_callback);
+  static void MakeWeak(Object** location,
+                       void* parameter,
+                       RevivableCallback weak_reference_callback,
+                       NearDeathCallback near_death_callback);
 
   void RecordStats(HeapStats* stats);
 
@@ -158,13 +158,13 @@
   }
 
   // Clear the weakness of a global handle.
-  void ClearWeakness(Object** location);
+  static void ClearWeakness(Object** location);
 
   // Clear the weakness of a global handle.
-  void MarkIndependent(Object** location);
+  static void MarkIndependent(Object** location);
 
   // Mark the reference to this object externaly unreachable.
-  void MarkPartiallyDependent(Object** location);
+  static void MarkPartiallyDependent(Object** location);
 
   static bool IsIndependent(Object** location);
 
diff --git a/src/handles-inl.h b/src/handles-inl.h
index 4f5e9fe..14687e3 100644
--- a/src/handles-inl.h
+++ b/src/handles-inl.h
@@ -122,31 +122,37 @@
 
 
 HandleScope::~HandleScope() {
-  CloseScope();
+  CloseScope(isolate_, prev_next_, prev_limit_);
 }
 
-void HandleScope::CloseScope() {
+
+void HandleScope::CloseScope(Isolate* isolate,
+                             Object** prev_next,
+                             Object** prev_limit) {
   v8::ImplementationUtilities::HandleScopeData* current =
-      isolate_->handle_scope_data();
-  current->next = prev_next_;
+      isolate->handle_scope_data();
+
+  current->next = prev_next;
   current->level--;
-  if (current->limit != prev_limit_) {
-    current->limit = prev_limit_;
-    DeleteExtensions(isolate_);
+  if (current->limit != prev_limit) {
+    current->limit = prev_limit;
+    DeleteExtensions(isolate);
   }
+
 #ifdef ENABLE_EXTRA_CHECKS
-  ZapRange(prev_next_, prev_limit_);
+  ZapRange(prev_next, prev_limit);
 #endif
 }
 
 
 template <typename T>
 Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
-  T* value = *handle_value;
-  // Throw away all handles in the current scope.
-  CloseScope();
   v8::ImplementationUtilities::HandleScopeData* current =
       isolate_->handle_scope_data();
+
+  T* value = *handle_value;
+  // Throw away all handles in the current scope.
+  CloseScope(isolate_, prev_next_, prev_limit_);
   // Allocate one handle in the parent scope.
   ASSERT(current->level > 0);
   Handle<T> result(CreateHandle<T>(isolate_, value));
@@ -180,15 +186,14 @@
 #ifdef DEBUG
 inline NoHandleAllocation::NoHandleAllocation(Isolate* isolate)
     : isolate_(isolate) {
-  v8::ImplementationUtilities::HandleScopeData* current =
-      isolate_->handle_scope_data();
-
   active_ = !isolate->optimizing_compiler_thread()->IsOptimizerThread();
   if (active_) {
     // Shrink the current handle scope to make it impossible to do
     // handle allocations without an explicit handle scope.
+    v8::ImplementationUtilities::HandleScopeData* current =
+        isolate_->handle_scope_data();
+    limit_ = current->limit;
     current->limit = current->next;
-
     level_ = current->level;
     current->level = 0;
   }
@@ -199,10 +204,12 @@
   if (active_) {
     // Restore state in current handle scope to re-enable handle
     // allocations.
-    v8::ImplementationUtilities::HandleScopeData* data =
+    v8::ImplementationUtilities::HandleScopeData* current =
         isolate_->handle_scope_data();
-    ASSERT_EQ(0, data->level);
-    data->level = level_;
+    ASSERT_EQ(0, current->level);
+    current->level = level_;
+    ASSERT_EQ(current->next, current->limit);
+    current->limit = limit_;
   }
 }
 
diff --git a/src/handles.h b/src/handles.h
index 938d43b..29ece28 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -155,18 +155,21 @@
   void* operator new(size_t size);
   void operator delete(void* size_t);
 
-  inline void CloseScope();
-
   Isolate* isolate_;
   Object** prev_next_;
   Object** prev_limit_;
 
+  // Close the handle scope resetting limits to a previous state.
+  static inline void CloseScope(Isolate* isolate,
+                                Object** prev_next,
+                                Object** prev_limit);
+
   // Extend the handle scope making room for more handles.
   static internal::Object** Extend(Isolate* isolate);
 
 #ifdef ENABLE_EXTRA_CHECKS
   // Zaps the handles in the half-open interval [start, end).
-  static void ZapRange(internal::Object** start, internal::Object** end);
+  static void ZapRange(Object** start, Object** end);
 #endif
 
   friend class v8::HandleScope;
@@ -337,6 +340,7 @@
   inline ~NoHandleAllocation();
  private:
   Isolate* isolate_;
+  Object** limit_;
   int level_;
   bool active_;
 #endif
diff --git a/src/heap.cc b/src/heap.cc
index 587e2f1..50b5a34 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -152,7 +152,6 @@
       last_idle_notification_gc_count_(0),
       last_idle_notification_gc_count_init_(false),
       mark_sweeps_since_idle_round_started_(0),
-      ms_count_at_last_idle_notification_(0),
       gc_count_at_last_idle_gc_(0),
       scavenges_since_last_idle_round_(kIdleScavengeThreshold),
       gcs_since_last_deopt_(0),
@@ -5770,6 +5769,7 @@
       uncommit = true;
     }
     CollectAllGarbage(kNoGCFlags, "idle notification: finalize incremental");
+    mark_sweeps_since_idle_round_started_++;
     gc_count_at_last_idle_gc_ = gc_count_;
     if (uncommit) {
       new_space_.Shrink();
@@ -5845,18 +5845,9 @@
     }
   }
 
-  int new_mark_sweeps = ms_count_ - ms_count_at_last_idle_notification_;
-  mark_sweeps_since_idle_round_started_ += new_mark_sweeps;
-  ms_count_at_last_idle_notification_ = ms_count_;
-
   int remaining_mark_sweeps = kMaxMarkSweepsInIdleRound -
                               mark_sweeps_since_idle_round_started_;
 
-  if (remaining_mark_sweeps <= 0) {
-    FinishIdleRound();
-    return true;
-  }
-
   if (incremental_marking()->IsStopped()) {
     // If there are no more than two GCs left in this idle round and we are
     // allowed to do a full GC, then make those GCs full in order to compact
@@ -5866,6 +5857,7 @@
     if (remaining_mark_sweeps <= 2 && hint >= kMinHintForFullGC) {
       CollectAllGarbage(kReduceMemoryFootprintMask,
                         "idle notification: finalize idle round");
+      mark_sweeps_since_idle_round_started_++;
     } else {
       incremental_marking()->Start();
     }
@@ -5873,6 +5865,12 @@
   if (!incremental_marking()->IsStopped()) {
     AdvanceIdleIncrementalMarking(step_size);
   }
+
+  if (mark_sweeps_since_idle_round_started_ >= kMaxMarkSweepsInIdleRound) {
+    FinishIdleRound();
+    return true;
+  }
+
   return false;
 }
 
diff --git a/src/heap.h b/src/heap.h
index 3387d94..556e1db 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -2266,7 +2266,6 @@
 
   void StartIdleRound() {
     mark_sweeps_since_idle_round_started_ = 0;
-    ms_count_at_last_idle_notification_ = ms_count_;
   }
 
   void FinishIdleRound() {
@@ -2343,7 +2342,6 @@
   bool last_idle_notification_gc_count_init_;
 
   int mark_sweeps_since_idle_round_started_;
-  int ms_count_at_last_idle_notification_;
   unsigned int gc_count_at_last_idle_gc_;
   int scavenges_since_last_idle_round_;
 
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 069b3f2..d4938e5 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1142,17 +1142,16 @@
 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) {
   ASSERT(CheckFlag(kFlexibleRepresentation));
   Representation r;
-  HValue* actual_length = length()->ActualValue();
   HValue* actual_index = index()->ActualValue();
-  if (key_mode_ == DONT_ALLOW_SMI_KEY ||
-      !actual_length->representation().IsSmiOrTagged()) {
+  HValue* actual_length = length()->ActualValue();
+  Representation index_rep = actual_index->representation();
+  if (!actual_length->representation().IsSmiOrTagged()) {
     r = Representation::Integer32();
-  } else if (actual_index->representation().IsSmiOrTagged() ||
-             (actual_index->IsConstant() &&
-              HConstant::cast(actual_index)->HasSmiValue())) {
-    // If the index is smi, or a constant that holds a Smi, allow the length to
-    // be smi, since it is usually already smi from loading it out of the length
-    // field of a JSArray. This allows for direct comparison without untagging.
+  } else if ((index_rep.IsTagged() && actual_index->type().IsSmi()) ||
+      index_rep.IsSmi()) {
+    // If the index is smi, allow the length to be smi, since it is usually
+    // already smi from loading it out of the length field of a JSArray.  This
+    // allows for direct comparison without untagging.
     r = Representation::Smi();
   } else {
     r = Representation::Integer32();
@@ -1486,7 +1485,7 @@
 
   if (CanTruncateToInt32()) stream->Add(" truncating-int32");
   if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
-  if (CheckFlag(kDeoptimizeOnUndefined)) stream->Add(" deopt-on-undefined");
+  if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan");
 }
 
 
@@ -1812,8 +1811,18 @@
   if (representation().IsInteger32()) {
     Range* a = left()->range();
     Range* b = right()->range();
-    Range* result = new(zone) Range();
-    if (a->CanBeMinusZero() || a->CanBeNegative()) {
+
+    // The magnitude of the modulus is bounded by the right operand. Note that
+    // apart for the cases involving kMinInt, the calculation below is the same
+    // as Max(Abs(b->lower()), Abs(b->upper())) - 1.
+    int32_t positive_bound = -(Min(NegAbs(b->lower()), NegAbs(b->upper())) + 1);
+
+    // The result of the modulo operation has the sign of its left operand.
+    bool left_can_be_negative = a->CanBeMinusZero() || a->CanBeNegative();
+    Range* result = new(zone) Range(left_can_be_negative ? -positive_bound : 0,
+                                    a->CanBePositive() ? positive_bound : 0);
+
+    if (left_can_be_negative) {
       result->set_can_be_minus_zero(true);
     }
 
@@ -2481,8 +2490,8 @@
     // (false). Therefore, any comparisons other than ordered relational
     // comparisons must cause a deopt when one of their arguments is undefined.
     // See also v8:1434
-    if (!Token::IsOrderedRelationalCompareOp(token_)) {
-      SetFlag(kDeoptimizeOnUndefined);
+    if (Token::IsOrderedRelationalCompareOp(token_)) {
+      SetFlag(kAllowUndefinedAsNaN);
     }
   }
   ChangeRepresentation(rep);
@@ -2745,7 +2754,7 @@
 
   for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
     HValue* use = it.value();
-    if (use->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
+    if (!use->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
       return false;
     }
   }
@@ -3250,7 +3259,7 @@
   if (FLAG_fold_constants && string->IsConstant()) {
     HConstant* c_string = HConstant::cast(string);
     if (c_string->HasStringValue()) {
-      return H_CONSTANT_INT32(c_string->StringValue()->length());
+      return new(zone) HConstant(c_string->StringValue()->length());
     }
   }
   return new(zone) HStringLength(string);
@@ -3740,7 +3749,6 @@
     // track dominating allocations in order to eliminate write barriers
     instr->SetGVNFlag(kDependsOnNewSpacePromotion);
     instr->SetFlag(HValue::kTrackSideEffectDominators);
-    instr->SetFlag(HValue::kDeoptimizeOnUndefined);
   } else {
     // try to GVN loads, but don't hoist above map changes
     instr->SetFlag(HValue::kUseGVN);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 6fbfd15..9f52569 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -263,6 +263,7 @@
   bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
   bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
   bool CanBeNegative() const { return lower_ < 0; }
+  bool CanBePositive() const { return upper_ > 0; }
   bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
   bool IsMostGeneric() const {
     return lower_ == kMinInt && upper_ == kMaxInt && CanBeMinusZero();
@@ -789,7 +790,7 @@
     kCanOverflow,
     kBailoutOnMinusZero,
     kCanBeDivByZero,
-    kDeoptimizeOnUndefined,
+    kAllowUndefinedAsNaN,
     kIsArguments,
     kTruncatingToInt32,
     // Set after an instruction is killed.
@@ -1561,6 +1562,9 @@
   }
   explicit HBranch(HValue* value)
       : HUnaryControlInstruction(value, NULL, NULL) { }
+  HBranch(HValue* value, ToBooleanStub::Types expected_input_types)
+      : HUnaryControlInstruction(value, NULL, NULL),
+        expected_input_types_(expected_input_types) { }
 
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -1711,14 +1715,14 @@
   HChange(HValue* value,
           Representation to,
           bool is_truncating,
-          bool deoptimize_on_undefined)
+          bool allow_undefined_as_nan)
       : HUnaryOperation(value) {
     ASSERT(!value->representation().IsNone());
     ASSERT(!to.IsNone());
     ASSERT(!value->representation().Equals(to));
     set_representation(to);
     SetFlag(kUseGVN);
-    if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
+    if (allow_undefined_as_nan) SetFlag(kAllowUndefinedAsNaN);
     if (is_truncating) SetFlag(kTruncatingToInt32);
     if (value->representation().IsSmi() || value->type().IsSmi()) {
       set_type(HType::Smi());
@@ -1734,8 +1738,8 @@
 
   Representation from() const { return value()->representation(); }
   Representation to() const { return representation(); }
-  bool deoptimize_on_undefined() const {
-    return CheckFlag(kDeoptimizeOnUndefined);
+  bool allow_undefined_as_nan() const {
+    return CheckFlag(kAllowUndefinedAsNaN);
   }
   bool deoptimize_on_minus_zero() const {
     return CheckFlag(kBailoutOnMinusZero);
@@ -1765,6 +1769,7 @@
   explicit HClampToUint8(HValue* value)
       : HUnaryOperation(value) {
     set_representation(Representation::Integer32());
+    SetFlag(kAllowUndefinedAsNaN);
     SetFlag(kUseGVN);
   }
 
@@ -2491,6 +2496,7 @@
     set_representation(Representation::Integer32());
     SetFlag(kUseGVN);
     SetFlag(kTruncatingToInt32);
+    SetFlag(kAllowUndefinedAsNaN);
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -2600,6 +2606,7 @@
         UNREACHABLE();
     }
     SetFlag(kUseGVN);
+    SetFlag(kAllowUndefinedAsNaN);
   }
 
   virtual bool IsDeletable() const { return true; }
@@ -2941,6 +2948,7 @@
     }
     ASSERT(merged_index >= 0);
     SetFlag(kFlexibleRepresentation);
+    SetFlag(kAllowUndefinedAsNaN);
   }
 
   virtual Representation RepresentationFromInputs();
@@ -3124,11 +3132,11 @@
  public:
   HConstant(Handle<Object> handle, Representation r);
   HConstant(int32_t value,
-            Representation r,
+            Representation r = Representation::None(),
             bool is_not_in_new_space = true,
             Handle<Object> optional_handle = Handle<Object>::null());
   HConstant(double value,
-            Representation r,
+            Representation r = Representation::None(),
             bool is_not_in_new_space = true,
             Handle<Object> optional_handle = Handle<Object>::null());
   HConstant(Handle<Object> handle,
@@ -3527,12 +3535,6 @@
 };
 
 
-enum BoundsCheckKeyMode {
-  DONT_ALLOW_SMI_KEY,
-  ALLOW_SMI_KEY
-};
-
-
 class HBoundsCheckBaseIndexInformation;
 
 
@@ -3542,10 +3544,8 @@
   // HGraphBuilder::AddBoundsCheck() helper.
   // However when building stubs, where we know that the arguments are Int32,
   // it makes sense to invoke this constructor directly.
-  HBoundsCheck(HValue* index,
-               HValue* length,
-               BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY)
-    : key_mode_(key_mode), skip_check_(false),
+  HBoundsCheck(HValue* index, HValue* length)
+    : skip_check_(false),
       base_(NULL), offset_(0), scale_(0),
       responsibility_direction_(DIRECTION_NONE) {
     SetOperandAt(0, index);
@@ -3618,7 +3618,6 @@
 
   virtual bool DataEquals(HValue* other) { return true; }
   virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context);
-  BoundsCheckKeyMode key_mode_;
   bool skip_check_;
   HValue* base_;
   int offset_;
@@ -3673,6 +3672,7 @@
       : HBinaryOperation(context, left, right) {
     SetFlag(kFlexibleRepresentation);
     SetFlag(kTruncatingToInt32);
+    SetFlag(kAllowUndefinedAsNaN);
     SetAllSideEffects();
   }
 
@@ -3727,6 +3727,7 @@
     if (!right->IsConstant()) {
       SetFlag(kCanBeDivByZero);
     }
+    SetFlag(kAllowUndefinedAsNaN);
   }
 
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
@@ -3751,6 +3752,7 @@
       : HBinaryOperation(context, left, right) {
     SetAllSideEffects();
     SetFlag(kFlexibleRepresentation);
+    SetFlag(kAllowUndefinedAsNaN);
   }
 
   virtual void RepresentationChanged(Representation to) {
@@ -5736,12 +5738,11 @@
     }
     if (is_external()) {
       SetGVNFlag(kChangesSpecializedArrayElements);
+      SetFlag(kAllowUndefinedAsNaN);
     } else if (IsFastDoubleElementsKind(elements_kind)) {
       SetGVNFlag(kChangesDoubleArrayElements);
-      SetFlag(kDeoptimizeOnUndefined);
     } else if (IsFastSmiElementsKind(elements_kind)) {
       SetGVNFlag(kChangesArrayElements);
-      SetFlag(kDeoptimizeOnUndefined);
     } else {
       SetGVNFlag(kChangesArrayElements);
     }
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 60ba595..54a5225 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -593,11 +593,10 @@
 #endif
 
 
-HConstant* HGraph::GetConstantInt32(SetOncePointer<HConstant>* pointer,
-                                    int32_t value) {
+HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
+                               int32_t value) {
   if (!pointer->is_set()) {
-    HConstant* constant =
-        new(zone()) HConstant(value, Representation::Integer32());
+    HConstant* constant = new(zone()) HConstant(value);
     constant->InsertAfter(GetConstantUndefined());
     pointer->set(constant);
   }
@@ -606,17 +605,17 @@
 
 
 HConstant* HGraph::GetConstant0() {
-  return GetConstantInt32(&constant_0_, 0);
+  return GetConstant(&constant_0_, 0);
 }
 
 
 HConstant* HGraph::GetConstant1() {
-  return GetConstantInt32(&constant_1_, 1);
+  return GetConstant(&constant_1_, 1);
 }
 
 
 HConstant* HGraph::GetConstantMinus1() {
-  return GetConstantInt32(&constant_minus1_, -1);
+  return GetConstant(&constant_minus1_, -1);
 }
 
 
@@ -648,7 +647,7 @@
 
 
 HConstant* HGraph::GetInvalidContext() {
-  return GetConstantInt32(&constant_invalid_context_, 0xFFFFC0C7);
+  return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
 }
 
 
@@ -823,9 +822,10 @@
 
 void HGraphBuilder::IfBuilder::Return(HValue* value) {
   HBasicBlock* block = builder_->current_block();
-  block->Finish(new(zone()) HReturn(value,
-                                    builder_->environment()->LookupContext(),
-                                    builder_->graph()->GetConstantMinus1()));
+  HValue* context = builder_->environment()->LookupContext();
+  HValue* parameter_count = builder_->graph()->GetConstantMinus1();
+  block->FinishExit(new(zone()) HReturn(value, context, parameter_count));
+  builder_->set_current_block(NULL);
   if (did_else_) {
     first_false_block_ = NULL;
   } else {
@@ -979,11 +979,8 @@
 }
 
 
-HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index,
-                                            HValue* length,
-                                            BoundsCheckKeyMode key_mode) {
-  HBoundsCheck* result = new(graph()->zone()) HBoundsCheck(
-      index, length, key_mode);
+HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, HValue* length) {
+  HBoundsCheck* result = new(graph()->zone()) HBoundsCheck(index, length);
   AddInstruction(result);
   return result;
 }
@@ -1129,7 +1126,7 @@
   Zone* zone = this->zone();
   IfBuilder length_checker(this);
 
-  length_checker.IfCompare(length, key, Token::EQ, Representation::Smi());
+  length_checker.IfCompare(length, key, Token::EQ);
   length_checker.Then();
 
   HValue* current_capacity =
@@ -1137,8 +1134,7 @@
 
   IfBuilder capacity_checker(this);
 
-  capacity_checker.IfCompare(
-      length, current_capacity, Token::EQ, Representation::Smi());
+  capacity_checker.IfCompare(length, current_capacity, Token::EQ);
   capacity_checker.Then();
 
   HValue* context = environment()->LookupContext();
@@ -1170,7 +1166,7 @@
 
   length_checker.Else();
 
-  AddBoundsCheck(key, length, ALLOW_SMI_KEY);
+  AddBoundsCheck(key, length);
   environment()->Push(elements);
 
   length_checker.End();
@@ -1260,11 +1256,11 @@
           new(zone) HLoadExternalArrayPointer(elements);
       AddInstruction(external_elements);
       IfBuilder length_checker(this);
-      length_checker.IfCompare(key, length, Token::LT, Representation::Smi());
+      length_checker.IfCompare(key, length, Token::LT);
       length_checker.Then();
       IfBuilder negative_checker(this);
       HValue* bounds_check = negative_checker.IfCompare(
-          key, graph()->GetConstant0(), Token::GTE, Representation::Smi());
+          key, graph()->GetConstant0(), Token::GTE);
       negative_checker.Then();
       HInstruction* result = BuildExternalArrayElementAccess(
           external_elements, key, val, bounds_check,
@@ -1275,7 +1271,7 @@
       return result;
     } else {
       ASSERT(store_mode == STANDARD_STORE);
-      checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
+      checked_key = AddBoundsCheck(key, length);
       HLoadExternalArrayPointer* external_elements =
           new(zone) HLoadExternalArrayPointer(elements);
       AddInstruction(external_elements);
@@ -1303,7 +1299,7 @@
                                          length, key, is_js_array);
     checked_key = key;
   } else {
-    checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
+    checked_key = AddBoundsCheck(key, length);
 
     if (is_store && (fast_elements || fast_smi_only_elements)) {
       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
@@ -1471,13 +1467,11 @@
                                                     : kPointerSize;
   int max_size = heap->MaxRegularSpaceAllocationSize() / element_size;
   max_size -= JSArray::kSize / element_size;
-  HConstant* max_size_constant =
-      new(zone) HConstant(max_size, Representation::Integer32());
+  HConstant* max_size_constant = new(zone) HConstant(max_size);
   AddInstruction(max_size_constant);
   // Since we're forcing Integer32 representation for this HBoundsCheck,
   // there's no need to Smi-check the index.
-  AddInstruction(new(zone) HBoundsCheck(
-      length, max_size_constant, DONT_ALLOW_SMI_KEY));
+  AddInstruction(new(zone) HBoundsCheck(length, max_size_constant));
 }
 
 
@@ -1545,8 +1539,7 @@
 
   if (unfold_loop) {
     for (int i = 0; i < initial_capacity; i++) {
-      HInstruction* key = AddInstruction(new(zone)
-                             HConstant(i, Representation::Integer32()));
+      HInstruction* key = AddInstruction(new(zone) HConstant(i));
       AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind));
     }
   } else {
@@ -1593,7 +1586,10 @@
       ? FAST_HOLEY_ELEMENTS : to_elements_kind;
   HInstruction* holey_store = AddInstruction(
       new(zone()) HStoreKeyed(to_elements, key, element, holey_kind));
-  holey_store->ClearFlag(HValue::kDeoptimizeOnUndefined);
+  // Allow NaN hole values to converted to their tagged counterparts.
+  if (IsFastHoleyElementsKind(to_elements_kind)) {
+    holey_store->SetFlag(HValue::kAllowUndefinedAsNaN);
+  }
 
   builder.EndBody();
 
@@ -1669,8 +1665,7 @@
     // copying loops with constant length up to a given boundary and use this
     // helper here instead.
     for (int i = 0; i < length; i++) {
-      HValue* key_constant =
-          AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
+      HValue* key_constant = AddInstruction(new(zone) HConstant(i));
       HInstruction* value =
           AddInstruction(new(zone) HLoadKeyed(boilerplate_elements,
                                               key_constant,
@@ -3108,8 +3103,8 @@
   // change instructions for them.
   HInstruction* new_value = NULL;
   bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32);
-  bool deoptimize_on_undefined =
-      use_value->CheckFlag(HValue::kDeoptimizeOnUndefined);
+  bool allow_undefined_as_nan =
+      use_value->CheckFlag(HValue::kAllowUndefinedAsNaN);
   if (value->IsConstant()) {
     HConstant* constant = HConstant::cast(value);
     // Try to create a new copy of the constant with the new representation.
@@ -3120,7 +3115,7 @@
 
   if (new_value == NULL) {
     new_value = new(zone()) HChange(value, to,
-                                    is_truncating, deoptimize_on_undefined);
+                                    is_truncating, allow_undefined_as_nan);
   }
 
   new_value->InsertBefore(next);
@@ -3227,8 +3222,8 @@
 
 
 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
-  if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return;
-  phi->SetFlag(HValue::kDeoptimizeOnUndefined);
+  if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return;
+  phi->ClearFlag(HValue::kAllowUndefinedAsNaN);
   for (int i = 0; i < phi->OperandCount(); ++i) {
     HValue* input = phi->OperandAt(i);
     if (input->IsPhi()) {
@@ -3248,16 +3243,11 @@
   // if one of its uses has this flag set.
   for (int i = 0; i < phi_list()->length(); i++) {
     HPhi* phi = phi_list()->at(i);
-    if (phi->representation().IsDouble()) {
-      for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
-        int use_index = it.index();
-        HValue* use_value = it.value();
-        Representation req = use_value->RequiredInputRepresentation(use_index);
-        if (!req.IsDouble() ||
-            use_value->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
-          RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
-          break;
-        }
+    for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
+      HValue* use_value = it.value();
+      if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
+        RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
+        break;
       }
     }
   }
@@ -5348,8 +5338,7 @@
 
   HInstruction* enum_length = AddInstruction(new(zone()) HMapEnumLength(map));
 
-  HInstruction* start_index = AddInstruction(new(zone()) HConstant(
-      Handle<Object>(Smi::FromInt(0), isolate()), Representation::Integer32()));
+  HInstruction* start_index = AddInstruction(new(zone()) HConstant(0));
 
   Push(map);
   Push(array);
@@ -6086,9 +6075,7 @@
 
     elements = AddLoadElements(literal);
 
-    HValue* key = AddInstruction(
-        new(zone()) HConstant(Handle<Object>(Smi::FromInt(i), isolate()),
-                              Representation::Integer32()));
+    HValue* key = AddInstruction(new(zone()) HConstant(i));
 
     switch (boilerplate_elements_kind) {
       case FAST_SMI_ELEMENTS:
@@ -7283,7 +7270,7 @@
             typecheck, Representation::Smi());
         length->set_type(HType::Smi());
 
-        checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
+        checked_key = AddBoundsCheck(key, length);
         access = AddInstruction(BuildFastElementAccess(
             elements, checked_key, val, elements_kind_branch,
             elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
@@ -7301,7 +7288,7 @@
 
         set_current_block(if_fastobject);
         length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
-        checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
+        checked_key = AddBoundsCheck(key, length);
         access = AddInstruction(BuildFastElementAccess(
             elements, checked_key, val, elements_kind_branch,
             elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
@@ -7439,9 +7426,7 @@
       // Number of arguments without receiver.
       int argument_count = environment()->
           arguments_environment()->parameter_count() - 1;
-      result = new(zone()) HConstant(
-          Handle<Object>(Smi::FromInt(argument_count), isolate()),
-          Representation::Integer32());
+      result = new(zone()) HConstant(argument_count);
     }
   } else {
     Push(graph()->GetArgumentsObject());
@@ -7464,8 +7449,7 @@
       int argument_count = environment()->
           arguments_environment()->parameter_count() - 1;
       HInstruction* length = AddInstruction(new(zone()) HConstant(
-          Handle<Object>(Smi::FromInt(argument_count), isolate()),
-          Representation::Integer32()));
+          argument_count));
       HInstruction* checked_key = AddBoundsCheck(key, length);
       result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
     }
@@ -8335,10 +8319,8 @@
             result =
                 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf);
           } else if (exponent == -0.5) {
-            HConstant* double_one =
-                new(zone()) HConstant(Handle<Object>(Smi::FromInt(1),
-                                                     isolate()),
-                                      Representation::Double());
+            HConstant* double_one = new(zone()) HConstant(
+                1, Representation::Double());
             AddInstruction(double_one);
             HInstruction* sqrt =
                 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf);
@@ -9292,7 +9274,7 @@
       if (i < 0 || i >= s->length()) {
         return new(zone()) HConstant(OS::nan_value(), Representation::Double());
       }
-      return new(zone()) HConstant(s->Get(i), Representation::Integer32());
+      return new(zone()) HConstant(s->Get(i));
     }
   }
   BuildCheckNonSmi(string);
@@ -10094,8 +10076,7 @@
 
   int elements_length = elements->length();
   HValue* object_elements_length =
-      AddInstruction(new(zone) HConstant(
-          elements_length, Representation::Integer32()));
+      AddInstruction(new(zone) HConstant(elements_length));
 
   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
 
@@ -10120,14 +10101,13 @@
       elements, Representation::Tagged()));
   int elements_length = elements->length();
   for (int i = 0; i < elements_length; i++) {
-    HValue* key_constant =
-        AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
+    HValue* key_constant = AddInstruction(new(zone) HConstant(i));
     HInstruction* value_instruction =
         AddInstruction(new(zone) HLoadKeyed(
             boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE));
     HInstruction* store = AddInstruction(new(zone) HStoreKeyed(
         object_elements, key_constant, value_instruction, kind));
-    store->ClearFlag(HValue::kDeoptimizeOnUndefined);
+    store->SetFlag(HValue::kAllowUndefinedAsNaN);
   }
 }
 
@@ -10148,8 +10128,7 @@
       Handle<FixedArray>::cast(original_elements);
   for (int i = 0; i < elements_length; i++) {
     Handle<Object> value(fast_elements->get(i), isolate());
-    HValue* key_constant =
-        AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
+    HValue* key_constant = AddInstruction(new(zone) HConstant(i));
     if (value->IsJSObject()) {
       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
       Handle<JSObject> original_value_object = Handle<JSObject>::cast(
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 3037e57..7a57448 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -400,8 +400,8 @@
   }
 
  private:
-  HConstant* GetConstantInt32(SetOncePointer<HConstant>* pointer,
-                              int32_t integer_value);
+  HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
+                         int32_t integer_value);
 
   void MarkLive(HValue* ref, HValue* instr, ZoneList<HValue*>* worklist);
   void MarkLiveInstructions();
@@ -952,10 +952,7 @@
   HInstruction* AddInstruction(HInstruction* instr);
   void AddSimulate(BailoutId id,
                    RemovableSimulate removable = FIXED_SIMULATE);
-  HBoundsCheck* AddBoundsCheck(
-      HValue* index,
-      HValue* length,
-      BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY);
+  HBoundsCheck* AddBoundsCheck(HValue* index, HValue* length);
 
   HReturn* AddReturn(HValue* value);
 
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 598bf17..325e9b7 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -50,7 +50,6 @@
   static Register registers[] = { eax, ebx, ecx };
   descriptor->register_param_count_ = 3;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry;
 }
@@ -62,7 +61,6 @@
   static Register registers[] = { eax, ebx, ecx, edx };
   descriptor->register_param_count_ = 4;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry;
 }
@@ -74,7 +72,6 @@
   static Register registers[] = { edx, ecx };
   descriptor->register_param_count_ = 2;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure);
 }
@@ -86,7 +83,6 @@
   static Register registers[] = { edx };
   descriptor->register_param_count_ = 1;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ = NULL;
 }
 
@@ -97,7 +93,6 @@
   static Register registers[] = { edx };
   descriptor->register_param_count_ = 1;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ = NULL;
 }
 
@@ -180,6 +175,18 @@
       ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
 }
 
+void ToBooleanStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { eax };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(ToBooleanIC_Miss);
+  descriptor->SetMissHandler(
+      ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
+}
+
 
 #define __ ACCESS_MASM(masm)
 
@@ -469,116 +476,6 @@
 }
 
 
-// The stub expects its argument on the stack and returns its result in tos_:
-// zero for false, and a non-zero value for true.
-void ToBooleanStub::Generate(MacroAssembler* masm) {
-  // This stub overrides SometimesSetsUpAFrame() to return false.  That means
-  // we cannot call anything that could cause a GC from this stub.
-  Label patch;
-  Factory* factory = masm->isolate()->factory();
-  const Register argument = eax;
-  const Register map = edx;
-
-  if (!types_.IsEmpty()) {
-    __ mov(argument, Operand(esp, 1 * kPointerSize));
-  }
-
-  // undefined -> false
-  CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
-
-  // Boolean -> its value
-  CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
-  CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
-
-  // 'null' -> false.
-  CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
-
-  if (types_.Contains(SMI)) {
-    // Smis: 0 -> false, all other -> true
-    Label not_smi;
-    __ JumpIfNotSmi(argument, &not_smi, Label::kNear);
-    // argument contains the correct return value already.
-    if (!tos_.is(argument)) {
-      __ mov(tos_, argument);
-    }
-    __ ret(1 * kPointerSize);
-    __ bind(&not_smi);
-  } else if (types_.NeedsMap()) {
-    // If we need a map later and have a Smi -> patch.
-    __ JumpIfSmi(argument, &patch, Label::kNear);
-  }
-
-  if (types_.NeedsMap()) {
-    __ mov(map, FieldOperand(argument, HeapObject::kMapOffset));
-
-    if (types_.CanBeUndetectable()) {
-      __ test_b(FieldOperand(map, Map::kBitFieldOffset),
-                1 << Map::kIsUndetectable);
-      // Undetectable -> false.
-      Label not_undetectable;
-      __ j(zero, &not_undetectable, Label::kNear);
-      __ Set(tos_, Immediate(0));
-      __ ret(1 * kPointerSize);
-      __ bind(&not_undetectable);
-    }
-  }
-
-  if (types_.Contains(SPEC_OBJECT)) {
-    // spec object -> true.
-    Label not_js_object;
-    __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
-    __ j(below, &not_js_object, Label::kNear);
-    // argument contains the correct return value already.
-    if (!tos_.is(argument)) {
-      __ Set(tos_, Immediate(1));
-    }
-    __ ret(1 * kPointerSize);
-    __ bind(&not_js_object);
-  }
-
-  if (types_.Contains(STRING)) {
-    // String value -> false iff empty.
-    Label not_string;
-    __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
-    __ j(above_equal, &not_string, Label::kNear);
-    __ mov(tos_, FieldOperand(argument, String::kLengthOffset));
-    __ ret(1 * kPointerSize);  // the string length is OK as the return value
-    __ bind(&not_string);
-  }
-
-  if (types_.Contains(SYMBOL)) {
-    // Symbol value -> true.
-    Label not_symbol;
-    __ CmpInstanceType(map, SYMBOL_TYPE);
-    __ j(not_equal, &not_symbol, Label::kNear);
-    __ bind(&not_symbol);
-  }
-
-  if (types_.Contains(HEAP_NUMBER)) {
-    // heap number -> false iff +0, -0, or NaN.
-    Label not_heap_number, false_result;
-    __ cmp(map, factory->heap_number_map());
-    __ j(not_equal, &not_heap_number, Label::kNear);
-    __ fldz();
-    __ fld_d(FieldOperand(argument, HeapNumber::kValueOffset));
-    __ FCmp();
-    __ j(zero, &false_result, Label::kNear);
-    // argument contains the correct return value already.
-    if (!tos_.is(argument)) {
-      __ Set(tos_, Immediate(1));
-    }
-    __ ret(1 * kPointerSize);
-    __ bind(&false_result);
-    __ Set(tos_, Immediate(0));
-    __ ret(1 * kPointerSize);
-    __ bind(&not_heap_number);
-  }
-
-  __ bind(&patch);
-  GenerateTypeTransition(masm);
-}
-
-
 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
   // We don't allow a GC during a store buffer overflow so there is no need to
   // store the registers in any particular way, but we do have to store and
@@ -614,44 +511,6 @@
 }
 
 
-void ToBooleanStub::CheckOddball(MacroAssembler* masm,
-                                 Type type,
-                                 Heap::RootListIndex value,
-                                 bool result) {
-  const Register argument = eax;
-  if (types_.Contains(type)) {
-    // If we see an expected oddball, return its ToBoolean value tos_.
-    Label different_value;
-    __ CompareRoot(argument, value);
-    __ j(not_equal, &different_value, Label::kNear);
-    if (!result) {
-      // If we have to return zero, there is no way around clearing tos_.
-      __ Set(tos_, Immediate(0));
-    } else if (!tos_.is(argument)) {
-      // If we have to return non-zero, we can re-use the argument if it is the
-      // same register as the result, because we never see Smi-zero here.
-      __ Set(tos_, Immediate(1));
-    }
-    __ ret(1 * kPointerSize);
-    __ bind(&different_value);
-  }
-}
-
-
-void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
-  __ pop(ecx);  // Get return address, operand is now on top of stack.
-  __ push(Immediate(Smi::FromInt(tos_.code())));
-  __ push(Immediate(Smi::FromInt(types_.ToByte())));
-  __ push(ecx);  // Push return address.
-  // Patch the caller to an appropriate specialized stub and return the
-  // operation result to the caller of the stub.
-  __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
-      3,
-      1);
-}
-
-
 class FloatingPointHelper : public AllStatic {
  public:
   enum ArgLocation {
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index bf5e02b..9c08ef3 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -641,9 +641,8 @@
                                Label* if_true,
                                Label* if_false,
                                Label* fall_through) {
-  ToBooleanStub stub(result_register());
-  __ push(result_register());
-  __ CallStub(&stub, condition->test_id());
+  Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
+  CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
   __ test(result_register(), result_register());
   // The stub returns nonzero for true.
   Split(not_zero, if_true, if_false, fall_through);
@@ -2003,9 +2002,8 @@
       __ mov(ecx, isolate()->factory()->done_string());  // "done"
       Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
       CallIC(done_ic);                                   // result.done in eax
-      ToBooleanStub stub(eax);
-      __ push(eax);
-      __ CallStub(&stub);
+      Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
+      CallIC(bool_ic);
       __ test(eax, eax);
       __ j(zero, &l_try);
 
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 46dcec0..fb566d1 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -1751,7 +1751,11 @@
 
 
 void LCodeGen::DoConstantI(LConstantI* instr) {
-  ASSERT(instr->result()->IsRegister());
+  __ Set(ToRegister(instr->result()), Immediate(instr->value()));
+}
+
+
+void LCodeGen::DoConstantS(LConstantS* instr) {
   __ Set(ToRegister(instr->result()), Immediate(instr->value()));
 }
 
@@ -2124,14 +2128,16 @@
 void LCodeGen::DoBranch(LBranch* instr) {
   int true_block = chunk_->LookupDestination(instr->true_block_id());
   int false_block = chunk_->LookupDestination(instr->false_block_id());
-  CpuFeatureScope scope(masm(), SSE2);
 
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsSmiOrInteger32()) {
+    ASSERT(!info()->IsStub());
     Register reg = ToRegister(instr->value());
     __ test(reg, Operand(reg));
     EmitBranch(true_block, false_block, not_zero);
   } else if (r.IsDouble()) {
+    ASSERT(!info()->IsStub());
+    CpuFeatureScope scope(masm(), SSE2);
     XMMRegister reg = ToDoubleRegister(instr->value());
     __ xorps(xmm0, xmm0);
     __ ucomisd(reg, xmm0);
@@ -2141,9 +2147,11 @@
     Register reg = ToRegister(instr->value());
     HType type = instr->hydrogen()->value()->type();
     if (type.IsBoolean()) {
+      ASSERT(!info()->IsStub());
       __ cmp(reg, factory()->true_value());
       EmitBranch(true_block, false_block, equal);
     } else if (type.IsSmi()) {
+      ASSERT(!info()->IsStub());
       __ test(reg, Operand(reg));
       EmitBranch(true_block, false_block, not_equal);
     } else {
@@ -2227,8 +2235,15 @@
         __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
                factory()->heap_number_map());
         __ j(not_equal, &not_heap_number, Label::kNear);
-        __ xorps(xmm0, xmm0);
-        __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
+        if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+          CpuFeatureScope scope(masm(), SSE2);
+          __ xorps(xmm0, xmm0);
+          __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
+        } else {
+          __ fldz();
+          __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
+          __ FCmp();
+        }
         __ j(zero, false_label);
         __ jmp(true_label);
         __ bind(&not_heap_number);
@@ -5080,7 +5095,7 @@
 
 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
                                       Register temp_reg,
-                                      bool deoptimize_on_undefined,
+                                      bool allow_undefined_as_nan,
                                       bool deoptimize_on_minus_zero,
                                       LEnvironment* env,
                                       NumberUntagDMode mode) {
@@ -5095,7 +5110,7 @@
     // Heap number map check.
     __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
            factory()->heap_number_map());
-    if (deoptimize_on_undefined) {
+    if (!allow_undefined_as_nan) {
       DeoptimizeIf(not_equal, env);
     } else {
       Label heap_number, convert;
@@ -5152,7 +5167,7 @@
 void LCodeGen::EmitNumberUntagD(Register input_reg,
                                 Register temp_reg,
                                 XMMRegister result_reg,
-                                bool deoptimize_on_undefined,
+                                bool allow_undefined_as_nan,
                                 bool deoptimize_on_minus_zero,
                                 LEnvironment* env,
                                 NumberUntagDMode mode) {
@@ -5167,7 +5182,7 @@
     // Heap number map check.
     __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
            factory()->heap_number_map());
-    if (deoptimize_on_undefined) {
+    if (!allow_undefined_as_nan) {
       DeoptimizeIf(not_equal, env);
     } else {
       Label heap_number, convert;
@@ -5337,15 +5352,20 @@
   // Heap number map check.
   __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
          factory()->heap_number_map());
-  __ j(equal, &heap_number, Label::kNear);
-  // Check for undefined. Undefined is converted to zero for truncating
-  // conversions.
-  __ cmp(input_reg, factory()->undefined_value());
-  __ RecordComment("Deferred TaggedToI: cannot truncate");
-  DeoptimizeIf(not_equal, instr->environment());
-  __ xor_(result_reg, result_reg);
-  __ jmp(&done, Label::kFar);
-  __ bind(&heap_number);
+  if (instr->truncating()) {
+    __ j(equal, &heap_number, Label::kNear);
+    // Check for undefined. Undefined is converted to zero for truncating
+    // conversions.
+    __ cmp(input_reg, factory()->undefined_value());
+    __ RecordComment("Deferred TaggedToI: cannot truncate");
+    DeoptimizeIf(not_equal, instr->environment());
+    __ xor_(result_reg, result_reg);
+    __ jmp(&done, Label::kFar);
+    __ bind(&heap_number);
+  } else {
+    // Deoptimize if we don't have a heap number.
+    DeoptimizeIf(not_equal, instr->environment());
+  }
 
   // Surprisingly, all of this crazy bit manipulation is considerably
   // faster than using the built-in x86 CPU conversion functions (about 6x).
@@ -5515,14 +5535,14 @@
     EmitNumberUntagD(input_reg,
                      temp_reg,
                      result_reg,
-                     instr->hydrogen()->deoptimize_on_undefined(),
+                     instr->hydrogen()->allow_undefined_as_nan(),
                      deoptimize_on_minus_zero,
                      instr->environment(),
                      mode);
   } else {
     EmitNumberUntagDNoSSE2(input_reg,
                            temp_reg,
-                           instr->hydrogen()->deoptimize_on_undefined(),
+                           instr->hydrogen()->allow_undefined_as_nan(),
                            deoptimize_on_minus_zero,
                            instr->environment(),
                            mode);
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index dce225c..dec768b 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -331,7 +331,7 @@
       Register input,
       Register temp,
       XMMRegister result,
-      bool deoptimize_on_undefined,
+      bool allow_undefined_as_nan,
       bool deoptimize_on_minus_zero,
       LEnvironment* env,
       NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
@@ -339,7 +339,7 @@
   void EmitNumberUntagDNoSSE2(
       Register input,
       Register temp,
-      bool deoptimize_on_undefined,
+      bool allow_undefined_as_nan,
       bool deoptimize_on_minus_zero,
       LEnvironment* env,
       NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 1fd0f49..28c4d2c 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -2108,7 +2108,9 @@
 
 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
   Representation r = instr->representation();
-  if (r.IsInteger32()) {
+  if (r.IsSmi()) {
+    return DefineAsRegister(new(zone()) LConstantS);
+  } else if (r.IsInteger32()) {
     return DefineAsRegister(new(zone()) LConstantI);
   } else if (r.IsDouble()) {
     double value = instr->DoubleValue();
@@ -2119,7 +2121,7 @@
     } else {
       return DefineX87TOS(new(zone()) LConstantD(NULL));
     }
-  } else if (r.IsSmiOrTagged()) {
+  } else if (r.IsTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
     UNREACHABLE();
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 2ed4cd6..568ef87 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -82,6 +82,7 @@
   V(CmpConstantEqAndBranch)                     \
   V(ConstantD)                                  \
   V(ConstantI)                                  \
+  V(ConstantS)                                  \
   V(ConstantT)                                  \
   V(Context)                                    \
   V(DebugBreak)                                 \
@@ -1152,6 +1153,15 @@
 };
 
 
+class LConstantS: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
+};
+
+
 class LConstantD: public LTemplateInstruction<1, 0, 1> {
  public:
   explicit LConstantD(LOperand* temp) {
diff --git a/src/ic.cc b/src/ic.cc
index e81ea10..7061f4d 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -2945,18 +2945,11 @@
   } else {
     code = stub.GetCode(isolate());
   }
-
-  patch(*code);
-
+  set_target(*code);
   return DoCompareNilSlow(kind, nil, object);
 }
 
 
-void CompareNilIC::patch(Code* code) {
-  set_target(code);
-}
-
-
 RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss) {
   HandleScope scope(isolate);
   Handle<Object> object = args.at<Object>(0);
@@ -2972,28 +2965,23 @@
 }
 
 
-RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) {
-  ASSERT(args.length() == 3);
-
-  HandleScope scope(isolate);
-  Handle<Object> object = args.at<Object>(0);
-  Register tos = Register::from_code(args.smi_at(1));
-  ToBooleanStub::Types old_types(args.smi_at(2));
-
-  ToBooleanStub::Types new_types(old_types);
-  bool to_boolean_value = new_types.Record(object);
-  old_types.TraceTransition(new_types);
-
-  ToBooleanStub stub(tos, new_types);
-  Handle<Code> code = stub.GetCode(isolate);
-  ToBooleanIC ic(isolate);
-  ic.patch(*code);
+MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object,
+                                    Code::ExtraICState extra_ic_state) {
+  ToBooleanStub stub(extra_ic_state);
+  bool to_boolean_value = stub.Record(object);
+  Handle<Code> code = stub.GetCode(isolate());
+  set_target(*code);
   return Smi::FromInt(to_boolean_value ? 1 : 0);
 }
 
 
-void ToBooleanIC::patch(Code* code) {
-  set_target(code);
+RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
+  ASSERT(args.length() == 1);
+  HandleScope scope(isolate);
+  Handle<Object> object = args.at<Object>(0);
+  ToBooleanIC ic(isolate);
+  Code::ExtraICState ic_state = ic.target()->extended_extra_ic_state();
+  return ic.ToBoolean(object, ic_state);
 }
 
 
diff --git a/src/ic.h b/src/ic.h
index 8fd96a6..4715f0e 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -62,7 +62,7 @@
   ICU(CompareIC_Miss)                                 \
   ICU(CompareNilIC_Miss)                              \
   ICU(Unreachable)                                    \
-  ICU(ToBoolean_Patch)
+  ICU(ToBooleanIC_Miss)
 //
 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
 // and KeyedStoreIC.
@@ -789,8 +789,6 @@
 
   static void Clear(Address address, Code* target);
 
-  void patch(Code* code);
-
   static MUST_USE_RESULT MaybeObject* DoCompareNilSlow(EqualityKind kind,
                                                        NilValue nil,
                                                        Handle<Object> object);
@@ -799,9 +797,9 @@
 
 class ToBooleanIC: public IC {
  public:
-  explicit ToBooleanIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
+  explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
 
-  void patch(Code* code);
+  MaybeObject* ToBoolean(Handle<Object> object, Code::ExtraICState state);
 };
 
 
@@ -811,8 +809,8 @@
 
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_MissLight);
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
+DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);
 
 
 } }  // namespace v8::internal
diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc
index bacbb93..e19d6e2 100644
--- a/src/incremental-marking.cc
+++ b/src/incremental-marking.cc
@@ -54,7 +54,8 @@
       should_hurry_(false),
       marking_speed_(0),
       allocated_(0),
-      no_marking_scope_depth_(0) {
+      no_marking_scope_depth_(0),
+      unscanned_bytes_of_large_object_(0) {
 }
 
 
@@ -241,6 +242,7 @@
                              chunk->progress_bar());
       int end_offset = Min(object_size,
                            start_offset + kProgressBarScanningChunk);
+      int already_scanned_offset = start_offset;
       bool scan_until_end = false;
       do {
         VisitPointersWithAnchor(heap,
@@ -254,6 +256,8 @@
       chunk->set_progress_bar(start_offset);
       if (start_offset < object_size) {
         heap->incremental_marking()->marking_deque()->UnshiftGrey(object);
+        heap->incremental_marking()->NotifyIncompleteScanOfObject(
+            object_size - (start_offset - already_scanned_offset));
       }
     } else {
       FixedArrayVisitor::Visit(map, object);
@@ -739,8 +743,9 @@
     if (map == filler_map) continue;
 
     int size = obj->SizeFromMap(map);
-    bytes_to_process -= size;
+    unscanned_bytes_of_large_object_ = 0;
     VisitObject(map, obj, size);
+    bytes_to_process -= (size - unscanned_bytes_of_large_object_);
   }
 }
 
diff --git a/src/incremental-marking.h b/src/incremental-marking.h
index 47d5a51..d47c300 100644
--- a/src/incremental-marking.h
+++ b/src/incremental-marking.h
@@ -220,6 +220,10 @@
 
   void UncommitMarkingDeque();
 
+  void NotifyIncompleteScanOfObject(int unscanned_bytes) {
+    unscanned_bytes_of_large_object_ = unscanned_bytes;
+  }
+
  private:
   int64_t SpaceLeftInOldSpace();
 
@@ -274,6 +278,8 @@
 
   int no_marking_scope_depth_;
 
+  int unscanned_bytes_of_large_object_;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalMarking);
 };
 
diff --git a/src/isolate.cc b/src/isolate.cc
index 8ae0c74..4daeddc 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -2245,6 +2245,7 @@
     stub.InitializeInterfaceDescriptor(
         this, code_stub_interface_descriptor(CodeStub::FastCloneShallowArray));
     CompareNilICStub::InitializeForIsolate(this);
+    ToBooleanStub::InitializeForIsolate(this);
     ArrayConstructorStubBase::InstallDescriptors(this);
   }
 
diff --git a/src/messages.js b/src/messages.js
index 2ad68cb..ce075ce 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -543,11 +543,11 @@
  * If sourceURL comment is available and script starts at zero returns sourceURL
  * comment contents. Otherwise, script name is returned. See
  * http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt
- * for details on using //@ sourceURL comment to identify scritps that don't
- * have name.
+ * and Source Map Revision 3 proposal for details on using //# sourceURL and
+ * deprecated //@ sourceURL comment to identify scripts that don't have name.
  *
- * @return {?string} script name if present, value for //@ sourceURL comment
- * otherwise.
+ * @return {?string} script name if present, value for //# sourceURL or
+ * deprecated //@ sourceURL comment otherwise.
  */
 function ScriptNameOrSourceURL() {
   if (this.line_offset > 0 || this.column_offset > 0) {
@@ -572,7 +572,7 @@
   this.cachedNameOrSourceURL = this.name;
   if (sourceUrlPos > 4) {
     var sourceUrlPattern =
-        /\/\/@[\040\t]sourceURL=[\040\t]*([^\s\'\"]*)[\040\t]*$/gm;
+        /\/\/[#@][\040\t]sourceURL=[\040\t]*([^\s\'\"]*)[\040\t]*$/gm;
     // Don't reuse lastMatchInfo here, so we create a new array with room
     // for four captures (array with length one longer than the index
     // of the fourth capture, where the numbering is zero-based).
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 9b4170e..bd89d44 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -46,7 +46,6 @@
   static Register registers[] = { a3, a2, a1 };
   descriptor->register_param_count_ = 3;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry;
 }
@@ -58,7 +57,6 @@
   static Register registers[] = { a3, a2, a1, a0 };
   descriptor->register_param_count_ = 4;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry;
 }
@@ -81,7 +79,6 @@
   static Register registers[] = { a0 };
   descriptor->register_param_count_ = 1;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ = NULL;
 }
 
@@ -92,7 +89,6 @@
   static Register registers[] = { a1 };
   descriptor->register_param_count_ = 1;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ = NULL;
 }
 
@@ -176,6 +172,19 @@
 }
 
 
+void ToBooleanStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { a0 };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(ToBooleanIC_Miss);
+  descriptor->SetMissHandler(
+      ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
+}
+
+
 #define __ ACCESS_MASM(masm)
 
 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
@@ -1500,116 +1509,6 @@
 }
 
 
-// The stub expects its argument in the tos_ register and returns its result in
-// it, too: zero for false, and a non-zero value for true.
-void ToBooleanStub::Generate(MacroAssembler* masm) {
-  Label patch;
-  const Register map = t5.is(tos_) ? t3 : t5;
-
-  // undefined -> false.
-  CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
-
-  // Boolean -> its value.
-  CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
-  CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
-
-  // 'null' -> false.
-  CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
-
-  if (types_.Contains(SMI)) {
-    // Smis: 0 -> false, all other -> true
-    __ And(at, tos_, kSmiTagMask);
-    // tos_ contains the correct return value already
-    __ Ret(eq, at, Operand(zero_reg));
-  } else if (types_.NeedsMap()) {
-    // If we need a map later and have a Smi -> patch.
-    __ JumpIfSmi(tos_, &patch);
-  }
-
-  if (types_.NeedsMap()) {
-    __ lw(map, FieldMemOperand(tos_, HeapObject::kMapOffset));
-
-    if (types_.CanBeUndetectable()) {
-      __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
-      __ And(at, at, Operand(1 << Map::kIsUndetectable));
-      // Undetectable -> false.
-      __ Movn(tos_, zero_reg, at);
-      __ Ret(ne, at, Operand(zero_reg));
-    }
-  }
-
-  if (types_.Contains(SPEC_OBJECT)) {
-    // Spec object -> true.
-    __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
-    // tos_ contains the correct non-zero return value already.
-    __ Ret(ge, at, Operand(FIRST_SPEC_OBJECT_TYPE));
-  }
-
-  if (types_.Contains(STRING)) {
-    // String value -> false iff empty.
-    __ lbu(at, FieldMemOperand(map, Map::kInstanceTypeOffset));
-    Label skip;
-    __ Branch(&skip, ge, at, Operand(FIRST_NONSTRING_TYPE));
-    __ Ret(USE_DELAY_SLOT);  // the string length is OK as the return value
-    __ lw(tos_, FieldMemOperand(tos_, String::kLengthOffset));
-    __ bind(&skip);
-  }
-
-  if (types_.Contains(HEAP_NUMBER)) {
-    // Heap number -> false iff +0, -0, or NaN.
-    Label not_heap_number;
-    __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
-    __ Branch(&not_heap_number, ne, map, Operand(at));
-    Label zero_or_nan, number;
-    __ ldc1(f2, FieldMemOperand(tos_, HeapNumber::kValueOffset));
-    __ BranchF(&number, &zero_or_nan, ne, f2, kDoubleRegZero);
-    // "tos_" is a register, and contains a non zero value by default.
-    // Hence we only need to overwrite "tos_" with zero to return false for
-    // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
-    __ bind(&zero_or_nan);
-    __ mov(tos_, zero_reg);
-    __ bind(&number);
-    __ Ret();
-    __ bind(&not_heap_number);
-  }
-
-  __ bind(&patch);
-  GenerateTypeTransition(masm);
-}
-
-
-void ToBooleanStub::CheckOddball(MacroAssembler* masm,
-                                 Type type,
-                                 Heap::RootListIndex value,
-                                 bool result) {
-  if (types_.Contains(type)) {
-    // If we see an expected oddball, return its ToBoolean value tos_.
-    __ LoadRoot(at, value);
-    __ Subu(at, at, tos_);  // This is a check for equality for the movz below.
-    // The value of a root is never NULL, so we can avoid loading a non-null
-    // value into tos_ when we want to return 'true'.
-    if (!result) {
-      __ Movz(tos_, zero_reg, at);
-    }
-    __ Ret(eq, at, Operand(zero_reg));
-  }
-}
-
-
-void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
-  __ Move(a3, tos_);
-  __ li(a2, Operand(Smi::FromInt(tos_.code())));
-  __ li(a1, Operand(Smi::FromInt(types_.ToByte())));
-  __ Push(a3, a2, a1);
-  // Patch the caller to an appropriate specialized stub and return the
-  // operation result to the caller of the stub.
-  __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
-      3,
-      1);
-}
-
-
 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
   // We don't allow a GC during a store buffer overflow so there is no need to
   // store the registers in any particular way, but we do have to store and
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 6a3b72d..78f44ab 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -677,8 +677,9 @@
                                Label* if_true,
                                Label* if_false,
                                Label* fall_through) {
-  ToBooleanStub stub(result_register());
-  __ CallStub(&stub, condition->test_id());
+  __ mov(a0, result_register());
+  Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
+  CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
   __ mov(at, zero_reg);
   Split(ne, v0, Operand(at), if_true, if_false, fall_through);
 }
@@ -2061,8 +2062,9 @@
       Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
       CallIC(done_ic);                                   // result.done in v0
       __ Addu(sp, sp, Operand(kPointerSize));            // drop LoadIC state
-      ToBooleanStub stub(v0);
-      __ CallStub(&stub);
+      __ mov(a0, v0);
+      Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
+      CallIC(bool_ic);
       __ Branch(&l_try, eq, v0, Operand(zero_reg));
 
       // result.value
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 05fa792..25ba162 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -521,6 +521,12 @@
 }
 
 
+Smi* LCodeGen::ToSmi(LConstantOperand* op) const {
+  HConstant* constant = chunk_->LookupConstant(op);
+  return Smi::FromInt(constant->Integer32Value());
+}
+
+
 double LCodeGen::ToDouble(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
   ASSERT(constant->HasDoubleValue());
@@ -1494,7 +1500,11 @@
 
 
 void LCodeGen::DoConstantI(LConstantI* instr) {
-  ASSERT(instr->result()->IsRegister());
+  __ li(ToRegister(instr->result()), Operand(instr->value()));
+}
+
+
+void LCodeGen::DoConstantS(LConstantS* instr) {
   __ li(ToRegister(instr->result()), Operand(instr->value()));
 }
 
@@ -1867,9 +1877,11 @@
 
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsInteger32() || r.IsSmi()) {
+    ASSERT(!info()->IsStub());
     Register reg = ToRegister(instr->value());
     EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
   } else if (r.IsDouble()) {
+    ASSERT(!info()->IsStub());
     DoubleRegister reg = ToDoubleRegister(instr->value());
     // Test the double value. Zero and NaN are false.
     EmitBranchF(true_block, false_block, nue, reg, kDoubleRegZero);
@@ -1878,9 +1890,11 @@
     Register reg = ToRegister(instr->value());
     HType type = instr->hydrogen()->value()->type();
     if (type.IsBoolean()) {
+      ASSERT(!info()->IsStub());
       __ LoadRoot(at, Heap::kTrueValueRootIndex);
       EmitBranch(true_block, false_block, eq, reg, Operand(at));
     } else if (type.IsSmi()) {
+      ASSERT(!info()->IsStub());
       EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
     } else {
       Label* true_label = chunk_->GetAssemblyLabel(true_block);
@@ -2047,11 +2061,23 @@
       Operand cmp_right = Operand(0);
 
       if (right->IsConstantOperand()) {
-        cmp_left = ToRegister(left);
-        cmp_right = Operand(ToInteger32(LConstantOperand::cast(right)));
+        int32_t value = ToInteger32(LConstantOperand::cast(right));
+        if (instr->hydrogen_value()->representation().IsSmi()) {
+          cmp_left = ToRegister(left);
+          cmp_right = Operand(Smi::FromInt(value));
+        } else {
+          cmp_left = ToRegister(left);
+          cmp_right = Operand(value);
+        }
       } else if (left->IsConstantOperand()) {
-        cmp_left = ToRegister(right);
-        cmp_right = Operand(ToInteger32(LConstantOperand::cast(left)));
+        int32_t value = ToInteger32(LConstantOperand::cast(left));
+        if (instr->hydrogen_value()->representation().IsSmi()) {
+           cmp_left = ToRegister(right);
+           cmp_right = Operand(Smi::FromInt(value));
+        } else {
+          cmp_left = ToRegister(right);
+          cmp_right = Operand(value);
+        }
         // We transposed the operands. Reverse the condition.
         cond = ReverseCondition(cond);
       } else {
@@ -2566,8 +2592,8 @@
   int no_frame_start = -1;
   if (NeedsEagerFrame()) {
     __ mov(sp, fp);
-    __ Pop(ra, fp);
     no_frame_start = masm_->pc_offset();
+    __ Pop(ra, fp);
   }
   if (instr->has_constant_parameter_count()) {
     int parameter_count = ToInteger32(instr->constant_parameter_count());
@@ -4659,7 +4685,7 @@
 
 void LCodeGen::EmitNumberUntagD(Register input_reg,
                                 DoubleRegister result_reg,
-                                bool deoptimize_on_undefined,
+                                bool allow_undefined_as_nan,
                                 bool deoptimize_on_minus_zero,
                                 LEnvironment* env,
                                 NumberUntagDMode mode) {
@@ -4676,7 +4702,7 @@
     // Heap number map check.
     __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
     __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
-    if (deoptimize_on_undefined) {
+    if (!allow_undefined_as_nan) {
       DeoptimizeIf(ne, env, scratch, Operand(at));
     } else {
       Label heap_number, convert;
@@ -4849,7 +4875,7 @@
   }
 
   EmitNumberUntagD(input_reg, result_reg,
-                   instr->hydrogen()->deoptimize_on_undefined(),
+                   instr->hydrogen()->allow_undefined_as_nan(),
                    instr->hydrogen()->deoptimize_on_minus_zero(),
                    instr->environment(),
                    mode);
@@ -5211,7 +5237,10 @@
     flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
   }
   if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
+    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
     flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
+  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+    flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
   }
   if (instr->size()->IsConstantOperand()) {
     int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
@@ -5250,11 +5279,12 @@
   }
 
   if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
-    CallRuntimeFromDeferred(
-        Runtime::kAllocateInOldPointerSpace, 1, instr);
+    ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace());
+    CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr);
+  } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) {
+    CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr);
   } else {
-    CallRuntimeFromDeferred(
-        Runtime::kAllocateInNewSpace, 1, instr);
+    CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
   }
   __ StoreToSafepointRegisterSlot(v0, result);
 }
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index a575f5d..2f4e140 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -118,6 +118,7 @@
                                         FloatRegister flt_scratch,
                                         DoubleRegister dbl_scratch);
   int ToInteger32(LConstantOperand* op) const;
+  Smi* ToSmi(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
   Operand ToOperand(LOperand* op);
   MemOperand ToMemOperand(LOperand* op) const;
@@ -342,7 +343,7 @@
   void EmitCmpI(LOperand* left, LOperand* right);
   void EmitNumberUntagD(Register input,
                         DoubleRegister result,
-                        bool deoptimize_on_undefined,
+                        bool allow_undefined_as_nan,
                         bool deoptimize_on_minus_zero,
                         LEnvironment* env,
                         NumberUntagDMode mode);
diff --git a/src/mips/lithium-gap-resolver-mips.cc b/src/mips/lithium-gap-resolver-mips.cc
index 87efae5..23a8f32 100644
--- a/src/mips/lithium-gap-resolver-mips.cc
+++ b/src/mips/lithium-gap-resolver-mips.cc
@@ -252,7 +252,9 @@
     LConstantOperand* constant_source = LConstantOperand::cast(source);
     if (destination->IsRegister()) {
       Register dst = cgen_->ToRegister(destination);
-      if (cgen_->IsInteger32(constant_source)) {
+      if (cgen_->IsSmi(constant_source)) {
+        __ li(dst, Operand(cgen_->ToSmi(constant_source)));
+      } else if (cgen_->IsInteger32(constant_source)) {
         __ li(dst, Operand(cgen_->ToInteger32(constant_source)));
       } else {
         __ LoadObject(dst, cgen_->ToHandle(constant_source));
@@ -260,7 +262,9 @@
     } else {
       ASSERT(destination->IsStackSlot());
       ASSERT(!in_cycle_);  // Constant moves happen after all cycles are gone.
-      if (cgen_->IsInteger32(constant_source)) {
+      if (cgen_->IsSmi(constant_source)) {
+        __ li(kLithiumScratchReg, Operand(cgen_->ToSmi(constant_source)));
+      } else if (cgen_->IsInteger32(constant_source)) {
         __ li(kLithiumScratchReg,
               Operand(cgen_->ToInteger32(constant_source)));
       } else {
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 22adc2a..2325064 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -1554,9 +1554,10 @@
 LInstruction* LChunkBuilder::DoCompareIDAndBranch(
     HCompareIDAndBranch* instr) {
   Representation r = instr->representation();
-  if (r.IsInteger32()) {
-    ASSERT(instr->left()->representation().IsInteger32());
-    ASSERT(instr->right()->representation().IsInteger32());
+  if (r.IsSmiOrInteger32()) {
+    ASSERT(instr->left()->representation().IsSmiOrInteger32());
+    ASSERT(instr->left()->representation().Equals(
+        instr->right()->representation()));
     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
     return new(zone()) LCmpIDAndBranch(left, right);
@@ -1908,7 +1909,7 @@
   } else if (input_rep.IsInteger32()) {
     return DefineAsRegister(new(zone()) LClampIToUint8(reg));
   } else {
-    ASSERT(input_rep.IsTagged());
+    ASSERT(input_rep.IsSmiOrTagged());
     // Register allocator doesn't (yet) support allocation of double
     // temps. Reserve f22 explicitly.
     LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(f22));
@@ -1926,11 +1927,13 @@
 
 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
   Representation r = instr->representation();
-  if (r.IsInteger32()) {
+  if (r.IsSmi()) {
+    return DefineAsRegister(new(zone()) LConstantS);
+  } else if (r.IsInteger32()) {
     return DefineAsRegister(new(zone()) LConstantI);
   } else if (r.IsDouble()) {
     return DefineAsRegister(new(zone()) LConstantD);
-  } else if (r.IsSmiOrTagged()) {
+  } else if (r.IsTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
     UNREACHABLE();
@@ -2357,7 +2360,7 @@
     index = UseOrConstant(instr->index());
   } else {
     length = UseTempRegister(instr->length());
-    index = Use(instr->index());
+    index = UseRegisterAtStart(instr->index());
   }
   return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
 }
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index e3ada26..01dd6c2 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -87,6 +87,7 @@
   V(CmpT)                                       \
   V(ConstantD)                                  \
   V(ConstantI)                                  \
+  V(ConstantS)                                  \
   V(ConstantT)                                  \
   V(Context)                                    \
   V(DebugBreak)                                 \
@@ -1153,6 +1154,15 @@
 };
 
 
+class LConstantS: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
+};
+
+
 class LConstantD: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index 7592a89..978ea21 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -32,10 +32,6 @@
 #endif
 #include <signal.h>
 
-// TODO(dcarney): remove
-#define V8_ALLOW_ACCESS_TO_PERSISTENT_ARROW
-#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT
-
 #include "v8.h"
 
 #include "bootstrapper.h"
@@ -341,10 +337,10 @@
     exit(1);
   }
   if (i::FLAG_extra_code != NULL) {
-    context->Enter();
     // Capture 100 frames if anything happens.
     V8::SetCaptureStackTraceForUncaughtExceptions(true, 100);
     HandleScope scope(isolate);
+    v8::Context::Scope(v8::Local<v8::Context>::New(isolate, context));
     const char* name = i::FLAG_extra_code;
     FILE* file = i::OS::FOpen(name, "rb");
     if (file == NULL) {
@@ -381,7 +377,6 @@
       DumpException(try_catch.Message());
       exit(1);
     }
-    context->Exit();
   }
   // Make sure all builtin scripts are cached.
   { HandleScope scope(isolate);
@@ -393,7 +388,7 @@
   // context even after we have disposed of the context.
   HEAP->CollectAllGarbage(i::Heap::kNoGCFlags, "mksnapshot");
   i::Object* raw_context = *(v8::Utils::OpenHandle(*context));
-  context.Dispose(context->GetIsolate());
+  context.Dispose(isolate);
   CppByteSink sink(argv[1]);
   // This results in a somewhat smaller snapshot, probably because it gets rid
   // of some things that are cached between garbage collections.
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 3dd3fd6..d0958ee 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -3729,6 +3729,7 @@
 
 Code::ExtraICState Code::extended_extra_ic_state() {
   ASSERT(is_inline_cache_stub() || ic_state() == DEBUG_STUB);
+  ASSERT(needs_extended_extra_ic_state(kind()));
   return ExtractExtendedExtraICStateFromFlags(flags());
 }
 
@@ -3979,17 +3980,7 @@
 
 
 byte Code::to_boolean_state() {
-  ASSERT(is_to_boolean_ic_stub());
-  return ToBooleanStateField::decode(
-      READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
-}
-
-
-void Code::set_to_boolean_state(byte value) {
-  ASSERT(is_to_boolean_ic_stub());
-  int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
-  int updated = ToBooleanStateField::update(previous, value);
-  WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
+  return extended_extra_ic_state();
 }
 
 
@@ -4052,10 +4043,7 @@
       | TypeField::encode(type)
       | ExtendedExtraICStateField::encode(extra_ic_state)
       | CacheHolderField::encode(holder);
-  // TODO(danno): This is a bit of a hack right now since there are still
-  // clients of this API that pass "extra" values in for argc. These clients
-  // should be retrofitted to used ExtendedExtraICState.
-  if (kind != Code::COMPARE_NIL_IC) {
+  if (!Code::needs_extended_extra_ic_state(kind)) {
     bits |= (argc << kArgumentsCountShift);
   }
   return static_cast<Flags>(bits);
diff --git a/src/objects.h b/src/objects.h
index 34d0533..8420069 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -4534,8 +4534,16 @@
   inline Kind kind();
   inline InlineCacheState ic_state();  // Only valid for IC stubs.
   inline ExtraICState extra_ic_state();  // Only valid for IC stubs.
+
   inline ExtraICState extended_extra_ic_state();  // Only valid for
                                                   // non-call IC stubs.
+  static bool needs_extended_extra_ic_state(Kind kind) {
+    // TODO(danno): This is a bit of a hack right now since there are still
+    // clients of this API that pass "extra" values in for argc. These clients
+    // should be retrofitted to used ExtendedExtraICState.
+    return kind == COMPARE_NIL_IC || kind == TO_BOOLEAN_IC;
+  }
+
   inline StubType type();  // Only valid for monomorphic IC stubs.
   inline int arguments_count();  // Only valid for call IC stubs.
 
@@ -4628,7 +4636,6 @@
 
   // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
   inline byte to_boolean_state();
-  inline void set_to_boolean_state(byte value);
 
   // [compare_nil]: For kind COMPARE_NIL_IC tells what state the stub is in.
   byte compare_nil_types();
@@ -4860,9 +4867,6 @@
   static const int kUnaryOpTypeFirstBit =
       kStackSlotsFirstBit + kStackSlotsBitCount;
   static const int kUnaryOpTypeBitCount = 3;
-  static const int kToBooleanStateFirstBit =
-      kStackSlotsFirstBit + kStackSlotsBitCount;
-  static const int kToBooleanStateBitCount = 8;
   static const int kHasFunctionCacheFirstBit =
       kStackSlotsFirstBit + kStackSlotsBitCount;
   static const int kHasFunctionCacheBitCount = 1;
@@ -4872,7 +4876,6 @@
 
   STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32);
   STATIC_ASSERT(kUnaryOpTypeFirstBit + kUnaryOpTypeBitCount <= 32);
-  STATIC_ASSERT(kToBooleanStateFirstBit + kToBooleanStateBitCount <= 32);
   STATIC_ASSERT(kHasFunctionCacheFirstBit + kHasFunctionCacheBitCount <= 32);
   STATIC_ASSERT(kMarkedForDeoptimizationFirstBit +
                 kMarkedForDeoptimizationBitCount <= 32);
@@ -4881,8 +4884,6 @@
       kStackSlotsFirstBit, kStackSlotsBitCount> {};  // NOLINT
   class UnaryOpTypeField: public BitField<int,
       kUnaryOpTypeFirstBit, kUnaryOpTypeBitCount> {};  // NOLINT
-  class ToBooleanStateField: public BitField<int,
-      kToBooleanStateFirstBit, kToBooleanStateBitCount> {};  // NOLINT
   class HasFunctionCacheField: public BitField<bool,
       kHasFunctionCacheFirstBit, kHasFunctionCacheBitCount> {};  // NOLINT
   class MarkedForDeoptimizationField: public BitField<bool,
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index a4d03b0..22f2245 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -591,6 +591,10 @@
   // kernel log.
   int size = sysconf(_SC_PAGESIZE);
   FILE* f = fopen(FLAG_gc_fake_mmap, "w+");
+  if (f == NULL) {
+    OS::PrintError("Failed to open %s\n", FLAG_gc_fake_mmap);
+    OS::Abort();
+  }
   void* addr = mmap(OS::GetRandomMmapAddr(),
                     size,
                     PROT_READ | PROT_EXEC,
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index 380c15f..0a7cc80 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -344,6 +344,10 @@
   // kernel log.
   int size = sysconf(_SC_PAGESIZE);
   FILE* f = fopen(FLAG_gc_fake_mmap, "w+");
+  if (f == NULL) {
+    OS::PrintError("Failed to open %s\n", FLAG_gc_fake_mmap);
+    OS::Abort();
+  }
   void* addr = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_PRIVATE,
                     fileno(f), 0);
   ASSERT(addr != MAP_FAILED);
diff --git a/src/runtime.cc b/src/runtime.cc
index 3e77584..7e45753 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -28,8 +28,6 @@
 #include <stdlib.h>
 #include <limits>
 
-#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT
-
 #include "v8.h"
 
 #include "accessors.h"
@@ -708,7 +706,7 @@
   SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
 
   v8::Isolate* external_isolate = reinterpret_cast<v8::Isolate*>(isolate);
-  v8::Persistent<v8::Value> weak_handle = v8::Persistent<v8::Value>::New(
+  v8::Persistent<v8::Value> weak_handle(
       external_isolate, v8::Utils::ToLocal(Handle<Object>::cast(array_buffer)));
   weak_handle.MakeWeak(external_isolate, data, ArrayBufferWeakCallback);
   weak_handle.MarkIndependent(external_isolate);
@@ -13360,7 +13358,9 @@
 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
   NoHandleAllocation ha(isolate);
   ASSERT(args.length() == 1);
-  CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
+
+  if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
+  JSReceiver* obj = JSReceiver::cast(args[0]);
   if (obj->IsJSGlobalProxy()) {
     Object* proto = obj->GetPrototype();
     if (proto->IsNull()) return isolate->heap()->false_value();
diff --git a/src/sampler.cc b/src/sampler.cc
index da186b6..25478a6 100644
--- a/src/sampler.cc
+++ b/src/sampler.cc
@@ -234,13 +234,11 @@
   if (sample == NULL) sample = &sample_obj;
 
 #if defined(USE_SIMULATOR)
-#if V8_TARGET_ARCH_ARM
-  sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
+  sample->pc = reinterpret_cast<Address>(sim->get_pc());
   sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
+#if V8_TARGET_ARCH_ARM
   sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
 #elif V8_TARGET_ARCH_MIPS
-  sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
-  sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
   sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
 #endif  // V8_TARGET_ARCH_*
 #else
@@ -523,13 +521,11 @@
                          &count) == KERN_SUCCESS) {
       sample->state = isolate->current_vm_state();
 #if defined(USE_SIMULATOR)
-#if V8_TARGET_ARCH_ARM
-      sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
+      sample->pc = reinterpret_cast<Address>(sim->get_pc());
       sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
+#if V8_TARGET_ARCH_ARM
       sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
 #elif V8_TARGET_ARCH_MIPS
-      sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
-      sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
       sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
 #endif
 #else
@@ -577,13 +573,11 @@
     context.ContextFlags = CONTEXT_FULL;
     if (GetThreadContext(profiled_thread, &context) != 0) {
 #if defined(USE_SIMULATOR)
-#if V8_TARGET_ARCH_ARM
-      sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
+      sample->pc = reinterpret_cast<Address>(sim->get_pc());
       sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
+#if V8_TARGET_ARCH_ARM
       sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
 #elif V8_TARGET_ARCH_MIPS
-      sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
-      sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
       sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
 #endif
 #else
diff --git a/src/utils.h b/src/utils.h
index 93cded1..b16730b 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -232,6 +232,13 @@
 }
 
 
+// Returns the negative absolute value of its argument.
+template <typename T>
+T NegAbs(T a) {
+  return a < 0 ? a : -a;
+}
+
+
 inline int StrLength(const char* string) {
   size_t length = strlen(string);
   ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
diff --git a/src/version.cc b/src/version.cc
index aeb9599..7cd381f 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      6
-#define PATCH_LEVEL       1
+#define BUILD_NUMBER      7
+#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/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index e9f7e46..d2ed601 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -46,7 +46,6 @@
   static Register registers[] = { rax, rbx, rcx };
   descriptor->register_param_count_ = 3;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kCreateArrayLiteralShallow)->entry;
 }
@@ -58,7 +57,6 @@
   static Register registers[] = { rax, rbx, rcx, rdx };
   descriptor->register_param_count_ = 4;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry;
 }
@@ -81,7 +79,6 @@
   static Register registers[] = { rax };
   descriptor->register_param_count_ = 1;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ = NULL;
 }
 
@@ -92,7 +89,6 @@
   static Register registers[] = { rdx };
   descriptor->register_param_count_ = 1;
   descriptor->register_params_ = registers;
-  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ = NULL;
 }
 
@@ -175,6 +171,19 @@
 }
 
 
+void ToBooleanStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { rax };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+     FUNCTION_ADDR(ToBooleanIC_Miss);
+  descriptor->SetMissHandler(
+      ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
+}
+
+
 #define __ ACCESS_MASM(masm)
 
 
@@ -462,106 +471,6 @@
 }
 
 
-// The stub expects its argument on the stack and returns its result in tos_:
-// zero for false, and a non-zero value for true.
-void ToBooleanStub::Generate(MacroAssembler* masm) {
-  // This stub overrides SometimesSetsUpAFrame() to return false.  That means
-  // we cannot call anything that could cause a GC from this stub.
-  Label patch;
-  const Register argument = rax;
-  const Register map = rdx;
-
-  if (!types_.IsEmpty()) {
-    __ movq(argument, Operand(rsp, 1 * kPointerSize));
-  }
-
-  // undefined -> false
-  CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false);
-
-  // Boolean -> its value
-  CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false);
-  CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true);
-
-  // 'null' -> false.
-  CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false);
-
-  if (types_.Contains(SMI)) {
-    // Smis: 0 -> false, all other -> true
-    Label not_smi;
-    __ JumpIfNotSmi(argument, &not_smi, Label::kNear);
-    // argument contains the correct return value already
-    if (!tos_.is(argument)) {
-      __ movq(tos_, argument);
-    }
-    __ ret(1 * kPointerSize);
-    __ bind(&not_smi);
-  } else if (types_.NeedsMap()) {
-    // If we need a map later and have a Smi -> patch.
-    __ JumpIfSmi(argument, &patch, Label::kNear);
-  }
-
-  if (types_.NeedsMap()) {
-    __ movq(map, FieldOperand(argument, HeapObject::kMapOffset));
-
-    if (types_.CanBeUndetectable()) {
-      __ testb(FieldOperand(map, Map::kBitFieldOffset),
-               Immediate(1 << Map::kIsUndetectable));
-      // Undetectable -> false.
-      Label not_undetectable;
-      __ j(zero, &not_undetectable, Label::kNear);
-      __ Set(tos_, 0);
-      __ ret(1 * kPointerSize);
-      __ bind(&not_undetectable);
-    }
-  }
-
-  if (types_.Contains(SPEC_OBJECT)) {
-    // spec object -> true.
-    Label not_js_object;
-    __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
-    __ j(below, &not_js_object, Label::kNear);
-    // argument contains the correct return value already.
-    if (!tos_.is(argument)) {
-      __ Set(tos_, 1);
-    }
-    __ ret(1 * kPointerSize);
-    __ bind(&not_js_object);
-  }
-
-  if (types_.Contains(STRING)) {
-    // String value -> false iff empty.
-    Label not_string;
-    __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
-    __ j(above_equal, &not_string, Label::kNear);
-    __ movq(tos_, FieldOperand(argument, String::kLengthOffset));
-    __ ret(1 * kPointerSize);  // the string length is OK as the return value
-    __ bind(&not_string);
-  }
-
-  if (types_.Contains(HEAP_NUMBER)) {
-    // heap number -> false iff +0, -0, or NaN.
-    Label not_heap_number, false_result;
-    __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
-    __ j(not_equal, &not_heap_number, Label::kNear);
-    __ xorps(xmm0, xmm0);
-    __ ucomisd(xmm0, FieldOperand(argument, HeapNumber::kValueOffset));
-    __ j(zero, &false_result, Label::kNear);
-    // argument contains the correct return value already.
-    if (!tos_.is(argument)) {
-      __ Set(tos_, 1);
-    }
-    __ ret(1 * kPointerSize);
-    __ bind(&false_result);
-    __ Set(tos_, 0);
-    __ ret(1 * kPointerSize);
-    __ bind(&not_heap_number);
-  }
-
-  __ bind(&patch);
-  GenerateTypeTransition(masm);
-}
-
-
 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
   __ PushCallerSaved(save_doubles_);
   const int argument_count = 1;
@@ -578,44 +487,6 @@
 }
 
 
-void ToBooleanStub::CheckOddball(MacroAssembler* masm,
-                                 Type type,
-                                 Heap::RootListIndex value,
-                                 bool result) {
-  const Register argument = rax;
-  if (types_.Contains(type)) {
-    // If we see an expected oddball, return its ToBoolean value tos_.
-    Label different_value;
-    __ CompareRoot(argument, value);
-    __ j(not_equal, &different_value, Label::kNear);
-    if (!result) {
-      // If we have to return zero, there is no way around clearing tos_.
-      __ Set(tos_, 0);
-    } else if (!tos_.is(argument)) {
-      // If we have to return non-zero, we can re-use the argument if it is the
-      // same register as the result, because we never see Smi-zero here.
-      __ Set(tos_, 1);
-    }
-    __ ret(1 * kPointerSize);
-    __ bind(&different_value);
-  }
-}
-
-
-void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
-  __ pop(rcx);  // Get return address, operand is now on top of stack.
-  __ Push(Smi::FromInt(tos_.code()));
-  __ Push(Smi::FromInt(types_.ToByte()));
-  __ push(rcx);  // Push return address.
-  // Patch the caller to an appropriate specialized stub and return the
-  // operation result to the caller of the stub.
-  __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
-      3,
-      1);
-}
-
-
 class FloatingPointHelper : public AllStatic {
  public:
   enum ConvertUndefined {
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index e88e1a5..e03c023 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -652,9 +652,8 @@
                                Label* if_true,
                                Label* if_false,
                                Label* fall_through) {
-  ToBooleanStub stub(result_register());
-  __ push(result_register());
-  __ CallStub(&stub, condition->test_id());
+  Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
+  CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id());
   __ testq(result_register(), result_register());
   // The stub returns nonzero for true.
   Split(not_zero, if_true, if_false, fall_through);
@@ -2028,10 +2027,9 @@
       __ LoadRoot(rcx, Heap::kdone_stringRootIndex);     // "done"
       Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize();
       CallIC(done_ic);                                   // result.done in rax
-      ToBooleanStub stub(rax);
-      __ push(rax);
-      __ CallStub(&stub);
-      __ testq(rax, rax);
+      Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
+      CallIC(bool_ic);
+      __ testq(result_register(), result_register());
       __ j(zero, &l_try);
 
       // result.value
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 74834a0..c94af7d 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -1560,11 +1560,15 @@
 
 
 void LCodeGen::DoConstantI(LConstantI* instr) {
-  ASSERT(instr->result()->IsRegister());
   __ Set(ToRegister(instr->result()), instr->value());
 }
 
 
+void LCodeGen::DoConstantS(LConstantS* instr) {
+  __ Move(ToRegister(instr->result()), instr->value());
+}
+
+
 void LCodeGen::DoConstantD(LConstantD* instr) {
   ASSERT(instr->result()->IsDoubleRegister());
   XMMRegister res = ToDoubleRegister(instr->result());
@@ -1907,14 +1911,17 @@
 
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsInteger32()) {
+    ASSERT(!info()->IsStub());
     Register reg = ToRegister(instr->value());
     __ testl(reg, reg);
     EmitBranch(true_block, false_block, not_zero);
   } else if (r.IsSmi()) {
+    ASSERT(!info()->IsStub());
     Register reg = ToRegister(instr->value());
     __ testq(reg, reg);
     EmitBranch(true_block, false_block, not_zero);
   } else if (r.IsDouble()) {
+    ASSERT(!info()->IsStub());
     XMMRegister reg = ToDoubleRegister(instr->value());
     __ xorps(xmm0, xmm0);
     __ ucomisd(reg, xmm0);
@@ -1924,9 +1931,11 @@
     Register reg = ToRegister(instr->value());
     HType type = instr->hydrogen()->value()->type();
     if (type.IsBoolean()) {
+      ASSERT(!info()->IsStub());
       __ CompareRoot(reg, Heap::kTrueValueRootIndex);
       EmitBranch(true_block, false_block, equal);
     } else if (type.IsSmi()) {
+      ASSERT(!info()->IsStub());
       __ SmiCompare(reg, Smi::FromInt(0));
       EmitBranch(true_block, false_block, not_equal);
     } else {
@@ -4679,7 +4688,7 @@
 
 void LCodeGen::EmitNumberUntagD(Register input_reg,
                                 XMMRegister result_reg,
-                                bool deoptimize_on_undefined,
+                                bool allow_undefined_as_nan,
                                 bool deoptimize_on_minus_zero,
                                 LEnvironment* env,
                                 NumberUntagDMode mode) {
@@ -4694,7 +4703,7 @@
     // Heap number map check.
     __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
                    Heap::kHeapNumberMapRootIndex);
-    if (deoptimize_on_undefined) {
+    if (!allow_undefined_as_nan) {
       DeoptimizeIf(not_equal, env);
     } else {
       Label heap_number, convert;
@@ -4830,7 +4839,7 @@
   }
 
   EmitNumberUntagD(input_reg, result_reg,
-                   instr->hydrogen()->deoptimize_on_undefined(),
+                   instr->hydrogen()->allow_undefined_as_nan(),
                    instr->hydrogen()->deoptimize_on_minus_zero(),
                    instr->environment(),
                    mode);
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 697d49d..9890649 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -295,7 +295,7 @@
   void EmitNumberUntagD(
       Register input,
       XMMRegister result,
-      bool deoptimize_on_undefined,
+      bool allow_undefined_as_nan,
       bool deoptimize_on_minus_zero,
       LEnvironment* env,
       NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 9a88c5b..fe23709 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1969,12 +1969,14 @@
 
 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
   Representation r = instr->representation();
-  if (r.IsInteger32()) {
+  if (r.IsSmi()) {
+    return DefineAsRegister(new(zone()) LConstantS);
+  } else if (r.IsInteger32()) {
     return DefineAsRegister(new(zone()) LConstantI);
   } else if (r.IsDouble()) {
     LOperand* temp = TempRegister();
     return DefineAsRegister(new(zone()) LConstantD(temp));
-  } else if (r.IsSmiOrTagged()) {
+  } else if (r.IsTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
     UNREACHABLE();
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index c295e34..36b080f 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -87,6 +87,7 @@
   V(CmpT)                                       \
   V(ConstantD)                                  \
   V(ConstantI)                                  \
+  V(ConstantS)                                  \
   V(ConstantT)                                  \
   V(Context)                                    \
   V(DebugBreak)                                 \
@@ -1136,6 +1137,15 @@
 };
 
 
+class LConstantS: public LTemplateInstruction<1, 0, 0> {
+ public:
+  DECLARE_CONCRETE_INSTRUCTION(ConstantS, "constant-s")
+  DECLARE_HYDROGEN_ACCESSOR(Constant)
+
+  Smi* value() const { return Smi::FromInt(hydrogen()->Integer32Value()); }
+};
+
+
 class LConstantD: public LTemplateInstruction<1, 0, 1> {
  public:
   explicit LConstantD(LOperand* temp) {