Version 3.20.3

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@15538 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index 638a25f..c56bc05 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -298,6 +298,7 @@
   return (obj == 0) ? ReportEmptyHandle(location) : false;
 }
 
+
 // --- S t a t i c s ---
 
 
@@ -322,6 +323,7 @@
   return ApiCheck(InitializeHelper(isolate), location, "Error initializing V8");
 }
 
+
 // Some initializing API functions are called early and may be
 // called on a thread different from static initializer thread.
 // If Isolate API is used, Isolate::Enter() will initialize TLS so
@@ -401,6 +403,7 @@
   kCompressedStartupDataCount
 };
 
+
 int V8::GetCompressedStartupDataCount() {
 #ifdef COMPRESS_STARTUP_DATA_BZ2
   return kCompressedStartupDataCount;
@@ -670,6 +673,7 @@
   i::GlobalHandles::Destroy(obj);
 }
 
+
 // --- H a n d l e s ---
 
 
@@ -4422,6 +4426,7 @@
   return str->HasOnlyOneByteChars();
 }
 
+
 // Helpers for ContainsOnlyOneByteHelper
 template<size_t size> struct OneByteMask;
 template<> struct OneByteMask<4> {
@@ -4435,6 +4440,8 @@
 static inline bool Unaligned(const uint16_t* chars) {
   return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask;
 }
+
+
 static inline const uint16_t* Align(const uint16_t* chars) {
   return reinterpret_cast<uint16_t*>(
     reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
@@ -6281,6 +6288,7 @@
   return Utils::OpenHandle(this)->is_external();
 }
 
+
 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
   ApiCheck(!obj->is_external(),
@@ -6581,6 +6589,7 @@
   disallow_heap_allocation_ = new i::DisallowHeapAllocation();
 }
 
+
 v8::AssertNoGCScope::~AssertNoGCScope() {
   delete static_cast<i::DisallowHeapAllocation*>(disallow_heap_allocation_);
 }
@@ -6644,6 +6653,7 @@
   isolate->stats_table()->SetCounterFunction(callback);
 }
 
+
 void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
   i::Isolate* isolate = EnterIsolateIfNeeded();
   if (IsDeadCheck(isolate, "v8::V8::SetCreateHistogramFunction()")) return;
@@ -6652,6 +6662,7 @@
   isolate->counters()->ResetHistograms();
 }
 
+
 void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
   i::Isolate* isolate = EnterIsolateIfNeeded();
   if (IsDeadCheck(isolate, "v8::V8::SetAddHistogramSampleFunction()")) return;
@@ -6999,6 +7010,7 @@
   i::DeleteArray(str_);
 }
 
+
 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
   i::Isolate* isolate = i::Isolate::Current();
   LOG_API(isolate, "RangeError");
@@ -7015,6 +7027,7 @@
   return Utils::ToLocal(result);
 }
 
+
 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
   i::Isolate* isolate = i::Isolate::Current();
   LOG_API(isolate, "ReferenceError");
@@ -7032,6 +7045,7 @@
   return Utils::ToLocal(result);
 }
 
+
 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
   i::Isolate* isolate = i::Isolate::Current();
   LOG_API(isolate, "SyntaxError");
@@ -7048,6 +7062,7 @@
   return Utils::ToLocal(result);
 }
 
+
 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
   i::Isolate* isolate = i::Isolate::Current();
   LOG_API(isolate, "TypeError");
@@ -7064,6 +7079,7 @@
   return Utils::ToLocal(result);
 }
 
+
 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
   i::Isolate* isolate = i::Isolate::Current();
   LOG_API(isolate, "Error");
@@ -7437,7 +7453,7 @@
   i::CpuProfiler* profiler = isolate->cpu_profiler();
   ASSERT(profiler != NULL);
   profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
-  if (profiler->GetProfilesCount() == 0 && !profiler->HasDetachedProfiles()) {
+  if (profiler->GetProfilesCount() == 0) {
     // If this was the last profile, clean up all accessory data as well.
     profiler->DeleteAllProfiles();
   }
@@ -7484,27 +7500,9 @@
 }
 
 
-const CpuProfile* CpuProfiler::GetCpuProfile(int index,
-                                             Handle<Value> security_token) {
-  return reinterpret_cast<const CpuProfile*>(
-      reinterpret_cast<i::CpuProfiler*>(this)->GetProfile(
-          security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
-          index));
-}
-
-
 const CpuProfile* CpuProfiler::GetCpuProfile(int index) {
   return reinterpret_cast<const CpuProfile*>(
-      reinterpret_cast<i::CpuProfiler*>(this)->GetProfile(NULL, index));
-}
-
-
-const CpuProfile* CpuProfiler::FindCpuProfile(unsigned uid,
-                                              Handle<Value> security_token) {
-  return reinterpret_cast<const CpuProfile*>(
-      reinterpret_cast<i::CpuProfiler*>(this)->FindProfile(
-          security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
-          uid));
+      reinterpret_cast<i::CpuProfiler*>(this)->GetProfile(index));
 }
 
 
@@ -7514,19 +7512,9 @@
 }
 
 
-const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title,
-                                                Handle<Value> security_token) {
-  return reinterpret_cast<const CpuProfile*>(
-      reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
-          security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
-          *Utils::OpenHandle(*title)));
-}
-
-
 const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title) {
   return reinterpret_cast<const CpuProfile*>(
       reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
-          NULL,
           *Utils::OpenHandle(*title)));
 }
 
@@ -7808,6 +7796,7 @@
   internal::Testing::set_stress_type(type);
 }
 
+
 int Testing::GetStressRuns() {
   if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
 #ifdef DEBUG
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 89c0a3b..e8afc5d 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -56,6 +56,7 @@
   return ExternalReference(&CpuFeatures::supported_);
 }
 
+
 // Get the CPU features enabled by the build. For cross compilation the
 // preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS
 // can be defined to enable ARMv7 and VFPv3 instructions when building the
@@ -356,6 +357,7 @@
   am_ = am;
 }
 
+
 MemOperand::MemOperand(Register rn, Register rm, AddrMode am) {
   rn_ = rn;
   rm_ = rm;
@@ -677,6 +679,7 @@
   return instr & kOff12Mask;
 }
 
+
 // Labels refer to positions in the (to be) generated code.
 // There are bound, linked, and unused labels.
 //
@@ -1640,6 +1643,7 @@
   addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
 }
 
+
 // Load/Store multiple instructions.
 void Assembler::ldm(BlockAddrMode am,
                     Register base,
@@ -2074,6 +2078,7 @@
        0xA*B8 | count);
 }
 
+
 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
   uint64_t i;
   OS::MemCopy(&i, &d, 8);
@@ -2082,6 +2087,7 @@
   *hi = i >> 32;
 }
 
+
 // Only works for little endian floating point formats.
 // We don't support VFP on the mixed endian floating point platform.
 static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
@@ -2774,6 +2780,7 @@
 #endif
 }
 
+
 void Assembler::GrowBuffer() {
   if (!own_buffer_) FATAL("external code buffer is too small");
 
@@ -2894,6 +2901,7 @@
   }
 }
 
+
 void Assembler::RecordRelocInfo(double data) {
   // We do not try to reuse pool constants.
   RelocInfo rinfo(pc_, data);
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
old mode 100755
new mode 100644
index 6af5cce..c5e4db8
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -226,8 +226,31 @@
 }
 
 
+void UnaryOpStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { r0 };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(UnaryOpIC_Miss);
+}
+
+
+void StoreGlobalStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { r1, r2, r0 };
+  descriptor->register_param_count_ = 3;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(StoreIC_MissFromStubFailure);
+}
+
+
 #define __ ACCESS_MASM(masm)
 
+
 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
                                           Label* slow,
                                           Condition cond);
@@ -1289,277 +1312,6 @@
 }
 
 
-void UnaryOpStub::PrintName(StringStream* stream) {
-  const char* op_name = Token::Name(op_);
-  const char* overwrite_name = NULL;  // Make g++ happy.
-  switch (mode_) {
-    case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
-    case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
-  }
-  stream->Add("UnaryOpStub_%s_%s_%s",
-              op_name,
-              overwrite_name,
-              UnaryOpIC::GetName(operand_type_));
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::Generate(MacroAssembler* masm) {
-  switch (operand_type_) {
-    case UnaryOpIC::UNINITIALIZED:
-      GenerateTypeTransition(masm);
-      break;
-    case UnaryOpIC::SMI:
-      GenerateSmiStub(masm);
-      break;
-    case UnaryOpIC::NUMBER:
-      GenerateNumberStub(masm);
-      break;
-    case UnaryOpIC::GENERIC:
-      GenerateGenericStub(masm);
-      break;
-  }
-}
-
-
-void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
-  __ mov(r3, Operand(r0));  // the operand
-  __ mov(r2, Operand(Smi::FromInt(op_)));
-  __ mov(r1, Operand(Smi::FromInt(mode_)));
-  __ mov(r0, Operand(Smi::FromInt(operand_type_)));
-  __ Push(r3, r2, r1, r0);
-
-  __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateSmiStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateSmiStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeSub(masm, &non_smi, &slow);
-  __ bind(&non_smi);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
-  Label non_smi;
-  GenerateSmiCodeBitNot(masm, &non_smi);
-  __ bind(&non_smi);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
-                                     Label* non_smi,
-                                     Label* slow) {
-  __ JumpIfNotSmi(r0, non_smi);
-
-  // The result of negating zero or the smallest negative smi is not a smi.
-  __ bic(ip, r0, Operand(0x80000000), SetCC);
-  __ b(eq, slow);
-
-  // Return '0 - value'.
-  __ rsb(r0, r0, Operand::Zero());
-  __ Ret();
-}
-
-
-void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
-                                        Label* non_smi) {
-  __ JumpIfNotSmi(r0, non_smi);
-
-  // Flip bits and revert inverted smi-tag.
-  __ mvn(r0, Operand(r0));
-  __ bic(r0, r0, Operand(kSmiTagMask));
-  __ Ret();
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateNumberStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateNumberStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
-  Label non_smi, slow, call_builtin;
-  GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeSub(masm, &slow);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-  __ bind(&call_builtin);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateNumberStubBitNot(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeBitNot(masm, &non_smi);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeBitNot(masm, &slow);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-}
-
-void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
-                                            Label* slow) {
-  EmitCheckForHeapNumber(masm, r0, r1, r6, slow);
-  // r0 is a heap number.  Get a new heap number in r1.
-  if (mode_ == UNARY_OVERWRITE) {
-    __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
-    __ eor(r2, r2, Operand(HeapNumber::kSignMask));  // Flip sign.
-    __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
-  } else {
-    Label slow_allocate_heapnumber, heapnumber_allocated;
-    __ AllocateHeapNumber(r1, r2, r3, r6, &slow_allocate_heapnumber);
-    __ jmp(&heapnumber_allocated);
-
-    __ bind(&slow_allocate_heapnumber);
-    {
-      FrameScope scope(masm, StackFrame::INTERNAL);
-      __ push(r0);
-      __ CallRuntime(Runtime::kNumberAlloc, 0);
-      __ mov(r1, Operand(r0));
-      __ pop(r0);
-    }
-
-    __ bind(&heapnumber_allocated);
-    __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
-    __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
-    __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset));
-    __ eor(r2, r2, Operand(HeapNumber::kSignMask));  // Flip sign.
-    __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset));
-    __ mov(r0, Operand(r1));
-  }
-  __ Ret();
-}
-
-
-void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
-                                               Label* slow) {
-  EmitCheckForHeapNumber(masm, r0, r1, r6, slow);
-
-  // Convert the heap number in r0 to an untagged integer in r1.
-  __ vldr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset));
-  __ ECMAToInt32(r1, d0, r2, r3, r4, d1);
-
-  // Do the bitwise operation and check if the result fits in a smi.
-  Label try_float;
-  __ mvn(r1, Operand(r1));
-  __ cmn(r1, Operand(0x40000000));
-  __ b(mi, &try_float);
-
-  // Tag the result as a smi and we're done.
-  __ SmiTag(r0, r1);
-  __ Ret();
-
-  // Try to store the result in a heap number.
-  __ bind(&try_float);
-  if (mode_ == UNARY_NO_OVERWRITE) {
-    Label slow_allocate_heapnumber, heapnumber_allocated;
-    __ AllocateHeapNumber(r0, r3, r4, r6, &slow_allocate_heapnumber);
-    __ jmp(&heapnumber_allocated);
-
-    __ bind(&slow_allocate_heapnumber);
-    {
-      FrameScope scope(masm, StackFrame::INTERNAL);
-      // Push the lower bit of the result (left shifted to look like a smi).
-      __ mov(r2, Operand(r1, LSL, 31));
-      // Push the 31 high bits (bit 0 cleared to look like a smi).
-      __ bic(r1, r1, Operand(1));
-      __ Push(r2, r1);
-      __ CallRuntime(Runtime::kNumberAlloc, 0);
-      __ Pop(r2, r1);  // Restore the result.
-      __ orr(r1, r1, Operand(r2, LSR, 31));
-    }
-    __ bind(&heapnumber_allocated);
-  }
-
-  __ vmov(s0, r1);
-  __ vcvt_f64_s32(d0, s0);
-  __ vstr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset));
-  __ Ret();
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateGenericStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateGenericStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeSub(masm, &non_smi, &slow);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeSub(masm, &slow);
-  __ bind(&slow);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeBitNot(masm, &non_smi);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeBitNot(masm, &slow);
-  __ bind(&slow);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
-  // Handle the slow case by jumping to the JavaScript builtin.
-  __ push(r0);
-  switch (op_) {
-    case Token::SUB:
-      __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
-      break;
-    case Token::BIT_NOT:
-      __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
 // Generates code to call a C function to do a double operation.
 // This code never falls through, but returns with a heap number containing
 // the result in r0.
@@ -6711,6 +6463,7 @@
   RememberedSetAction action;
 };
 
+
 #define REG(Name) { kRegister_ ## Name ## _Code }
 
 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h
index 1f663f5..0202a8a 100644
--- a/src/arm/code-stubs-arm.h
+++ b/src/arm/code-stubs-arm.h
@@ -80,71 +80,6 @@
 };
 
 
-class UnaryOpStub: public PlatformCodeStub {
- public:
-  UnaryOpStub(Token::Value op,
-              UnaryOverwriteMode mode,
-              UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
-      : op_(op),
-        mode_(mode),
-        operand_type_(operand_type) {
-  }
-
- private:
-  Token::Value op_;
-  UnaryOverwriteMode mode_;
-
-  // Operand type information determined at runtime.
-  UnaryOpIC::TypeInfo operand_type_;
-
-  virtual void PrintName(StringStream* stream);
-
-  class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
-  class OpBits: public BitField<Token::Value, 1, 7> {};
-  class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
-
-  Major MajorKey() { return UnaryOp; }
-  int MinorKey() {
-    return ModeBits::encode(mode_)
-           | OpBits::encode(op_)
-           | OperandTypeInfoBits::encode(operand_type_);
-  }
-
-  // Note: A lot of the helper functions below will vanish when we use virtual
-  // function instead of switch more often.
-  void Generate(MacroAssembler* masm);
-
-  void GenerateTypeTransition(MacroAssembler* masm);
-
-  void GenerateSmiStub(MacroAssembler* masm);
-  void GenerateSmiStubSub(MacroAssembler* masm);
-  void GenerateSmiStubBitNot(MacroAssembler* masm);
-  void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow);
-  void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow);
-
-  void GenerateNumberStub(MacroAssembler* masm);
-  void GenerateNumberStubSub(MacroAssembler* masm);
-  void GenerateNumberStubBitNot(MacroAssembler* masm);
-  void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
-  void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
-
-  void GenerateGenericStub(MacroAssembler* masm);
-  void GenerateGenericStubSub(MacroAssembler* masm);
-  void GenerateGenericStubBitNot(MacroAssembler* masm);
-  void GenerateGenericCodeFallback(MacroAssembler* masm);
-
-  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
-
-  virtual InlineCacheState GetICState() {
-    return UnaryOpIC::ToState(operand_type_);
-  }
-
-  virtual void FinishCode(Handle<Code> code) {
-    code->set_unary_op_type(operand_type_);
-  }
-};
-
-
 class StringHelper : public AllStatic {
  public:
   // Generate code for copying characters using a simple loop. This should only
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 60de5fc..f411b13 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -120,6 +120,7 @@
   return &sqrt;
 }
 
+
 // -------------------------------------------------------------------------
 // Platform-specific RuntimeCallHelper functions.
 
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index 6101bec..b0f3ec0 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -187,11 +187,13 @@
   Print(converter_.NameOfCPURegister(reg));
 }
 
+
 // Print the VFP S register name according to the active name converter.
 void Decoder::PrintSRegister(int reg) {
   Print(VFPRegisters::Name(reg, false));
 }
 
+
 // Print the VFP D register name according to the active name converter.
 void Decoder::PrintDRegister(int reg) {
   Print(VFPRegisters::Name(reg, true));
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 41f02be..7716e85 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -4366,10 +4366,7 @@
                                            const char* comment) {
   // TODO(svenpanne): Allowing format strings in Comment would be nice here...
   Comment cmt(masm_, comment);
-  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
-  UnaryOverwriteMode overwrite =
-      can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
-  UnaryOpStub stub(expr->op(), overwrite);
+  UnaryOpStub stub(expr->op());
   // UnaryOpStub expects the argument to be in the
   // accumulator register r0.
   VisitForAccumulatorValue(expr->expression());
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index b08353e..c8d0fdb 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -182,7 +182,7 @@
 }
 
 
-void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
+void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if ");
   left()->PrintTo(stream);
   stream->Add(" %s ", Token::String(op()));
@@ -1685,8 +1685,8 @@
 }
 
 
-LInstruction* LChunkBuilder::DoCompareIDAndBranch(
-    HCompareIDAndBranch* instr) {
+LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
+    HCompareNumericAndBranch* instr) {
   Representation r = instr->representation();
   if (r.IsSmiOrInteger32()) {
     ASSERT(instr->left()->representation().IsSmiOrInteger32());
@@ -1694,14 +1694,14 @@
         instr->right()->representation()));
     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
-    return new(zone()) LCmpIDAndBranch(left, right);
+    return new(zone()) LCompareNumericAndBranch(left, right);
   } else {
     ASSERT(r.IsDouble());
     ASSERT(instr->left()->representation().IsDouble());
     ASSERT(instr->right()->representation().IsDouble());
     LOperand* left = UseRegisterAtStart(instr->left());
     LOperand* right = UseRegisterAtStart(instr->right());
-    return new(zone()) LCmpIDAndBranch(left, right);
+    return new(zone()) LCompareNumericAndBranch(left, right);
   }
 }
 
@@ -1998,6 +1998,18 @@
 }
 
 
+LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return AssignEnvironment(new(zone()) LCheckSmi(value));
+}
+
+
+LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) {
+  return new(zone())
+    LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value()));
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LInstruction* result = new(zone()) LCheckInstanceType(value);
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 39cab8f..4adf026 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -81,7 +81,7 @@
   V(ClampTToUint8)                              \
   V(ClassOfTestAndBranch)                       \
   V(CmpConstantEqAndBranch)                     \
-  V(CmpIDAndBranch)                             \
+  V(CompareNumericAndBranch)                    \
   V(CmpObjectEqAndBranch)                       \
   V(CmpMapAndBranch)                            \
   V(CmpT)                                       \
@@ -118,6 +118,7 @@
   V(IsConstructCallAndBranch)                   \
   V(IsObjectAndBranch)                          \
   V(IsStringAndBranch)                          \
+  V(IsNumberAndBranch)                          \
   V(IsSmiAndBranch)                             \
   V(IsUndetectableAndBranch)                    \
   V(Label)                                      \
@@ -719,9 +720,9 @@
 };
 
 
-class LCmpIDAndBranch: public LControlInstruction<2, 0> {
+class LCompareNumericAndBranch: public LControlInstruction<2, 0> {
  public:
-  LCmpIDAndBranch(LOperand* left, LOperand* right) {
+  LCompareNumericAndBranch(LOperand* left, LOperand* right) {
     inputs_[0] = left;
     inputs_[1] = right;
   }
@@ -729,8 +730,9 @@
   LOperand* left() { return inputs_[0]; }
   LOperand* right() { return inputs_[1]; }
 
-  DECLARE_CONCRETE_INSTRUCTION(CmpIDAndBranch, "cmp-id-and-branch")
-  DECLARE_HYDROGEN_ACCESSOR(CompareIDAndBranch)
+  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
+                               "compare-numeric-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
 
   Token::Value op() const { return hydrogen()->token(); }
   bool is_double() const {
@@ -925,6 +927,19 @@
 };
 
 
+class LIsNumberAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LIsNumberAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsNumberAndBranch, "is-number-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(IsNumberAndBranch)
+};
+
+
 class LIsStringAndBranch: public LControlInstruction<1, 1> {
  public:
   LIsStringAndBranch(LOperand* value, LOperand* temp) {
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 272db15..191ee49 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2130,12 +2130,12 @@
 
 template<class InstrType>
 void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
-  int right_block = instr->FalseDestination(chunk_);
   int left_block = instr->TrueDestination(chunk_);
+  int right_block = instr->FalseDestination(chunk_);
 
   int next_block = GetNextEmittedBlock();
 
-  if (right_block == left_block) {
+  if (right_block == left_block || cc == al) {
     EmitGoto(left_block);
   } else if (left_block == next_block) {
     __ b(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
@@ -2153,6 +2153,25 @@
 }
 
 
+void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
+  Representation r = instr->hydrogen()->value()->representation();
+  if (r.IsSmiOrInteger32() || r.IsDouble()) {
+    EmitBranch(instr, al);
+  } else {
+    ASSERT(r.IsTagged());
+    Register reg = ToRegister(instr->value());
+    HType type = instr->hydrogen()->value()->type();
+    if (type.IsTaggedNumber()) {
+      EmitBranch(instr, al);
+    }
+    __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
+    __ ldr(scratch0(), FieldMemOperand(reg, HeapObject::kMapOffset));
+    __ CompareRoot(scratch0(), Heap::kHeapNumberMapRootIndex);
+    EmitBranch(instr, eq);
+  }
+}
+
+
 void LCodeGen::DoBranch(LBranch* instr) {
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsInteger32() || r.IsSmi()) {
@@ -2329,7 +2348,7 @@
 }
 
 
-void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
+void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
   LOperand* left = instr->left();
   LOperand* right = instr->right();
   Condition cond = TokenToCondition(instr->op(), false);
diff --git a/src/arm/lithium-gap-resolver-arm.cc b/src/arm/lithium-gap-resolver-arm.cc
index 352fbb9..902817e 100644
--- a/src/arm/lithium-gap-resolver-arm.cc
+++ b/src/arm/lithium-gap-resolver-arm.cc
@@ -219,7 +219,6 @@
       ASSERT(destination->IsStackSlot());
       __ str(source_register, cgen_->ToMemOperand(destination));
     }
-
   } else if (source->IsStackSlot()) {
     MemOperand source_operand = cgen_->ToMemOperand(source);
     if (destination->IsRegister()) {
@@ -255,6 +254,10 @@
       } else {
         __ LoadObject(dst, cgen_->ToHandle(constant_source));
       }
+    } else if (source->IsDoubleRegister()) {
+      DwVfpRegister result = cgen_->ToDoubleRegister(destination);
+      double v = cgen_->ToDouble(constant_source);
+      __ Vmov(result, v, ip);
     } else {
       ASSERT(destination->IsStackSlot());
       ASSERT(!in_cycle_);  // Constant moves happen after all cycles are gone.
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index cce20ff..5e38785 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1033,6 +1033,7 @@
   }
 }
 
+
 void MacroAssembler::GetCFunctionDoubleResult(const DwVfpRegister dst) {
   if (use_eabi_hardfloat()) {
     Move(dst, d0);
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 238632a..b07e7be 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -1026,6 +1026,7 @@
   registers_[12] = 0x50Bad4U;
 }
 
+
 // Some Operating Systems allow unaligned access on ARMv7 targets. We
 // assume that unaligned accesses are not allowed unless the v8 build system
 // defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero.
@@ -1525,6 +1526,7 @@
   }
 }
 
+
 // Addressing Mode 4 - Load and Store Multiple
 void Simulator::HandleRList(Instruction* instr, bool load) {
   int rlist = instr->RlistValue();
@@ -1954,6 +1956,7 @@
     FixedDoubleArray::canonical_not_the_hole_nan_as_double() : value;
 }
 
+
 // Stop helper functions.
 bool Simulator::isStopInstruction(Instruction* instr) {
   return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
diff --git a/src/assembler.cc b/src/assembler.cc
index b669e09..16a73a7 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -381,6 +381,7 @@
   }
 }
 
+
 void RelocInfoWriter::WriteExtraTaggedConstPoolData(int data) {
   WriteExtraTag(kConstPoolExtraTag, kConstPoolTag);
   for (int i = 0; i < kIntSize; i++) {
@@ -390,6 +391,7 @@
   }
 }
 
+
 void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
   WriteExtraTag(kDataJumpExtraTag, top_tag);
   for (int i = 0; i < kIntptrSize; i++) {
@@ -1322,6 +1324,7 @@
   return ExternalReference(Redirect(isolate, function));
 }
 
+
 ExternalReference ExternalReference::re_grow_stack(Isolate* isolate) {
   return ExternalReference(
       Redirect(isolate, FUNCTION_ADDR(NativeRegExpMacroAssembler::GrowStack)));
@@ -1334,6 +1337,7 @@
       FUNCTION_ADDR(NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16)));
 }
 
+
 ExternalReference ExternalReference::re_word_character_map() {
   return ExternalReference(
       NativeRegExpMacroAssembler::word_character_map_address());
diff --git a/src/ast.cc b/src/ast.cc
index 589bd5a..7da9b33 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -675,6 +675,7 @@
   if (is_monomorphic_) {
     target_ = oracle->GetCallNewTarget(this);
     Object* value = allocation_info_cell_->value();
+    ASSERT(!value->IsTheHole());
     if (value->IsSmi()) {
       elements_kind_ = static_cast<ElementsKind>(Smi::cast(value)->value());
     }
diff --git a/src/ast.h b/src/ast.h
index b9a98e0..6336b3a 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1884,9 +1884,6 @@
   BailoutId RightId() const { return right_id_; }
 
   TypeFeedbackId BinaryOperationFeedbackId() const { return reuse(id()); }
-  // TODO(rossberg): result_type should be subsumed by lower_type.
-  Handle<Type> result_type() const { return result_type_; }
-  void set_result_type(Handle<Type> type) { result_type_ = type; }
   Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
   void set_fixed_right_arg(Maybe<int> arg) { fixed_right_arg_ = arg; }
 
@@ -1913,7 +1910,6 @@
   Expression* right_;
   int pos_;
 
-  Handle<Type> result_type_;
   // TODO(rossberg): the fixed arg should probably be represented as a Constant
   // type for the RHS.
   Maybe<int> fixed_right_arg_;
diff --git a/src/atomicops.h b/src/atomicops.h
index b18b54d..789721e 100644
--- a/src/atomicops.h
+++ b/src/atomicops.h
@@ -153,14 +153,11 @@
 // Include our platform specific implementation.
 #if defined(THREAD_SANITIZER)
 #include "atomicops_internals_tsan.h"
-#elif defined(_MSC_VER) && \
-  (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
+#elif defined(_MSC_VER) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
 #include "atomicops_internals_x86_msvc.h"
-#elif defined(__APPLE__) && \
-  (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
+#elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
 #include "atomicops_internals_x86_macosx.h"
-#elif defined(__GNUC__) && \
-  (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
+#elif defined(__GNUC__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
 #include "atomicops_internals_x86_gcc.h"
 #elif defined(__GNUC__) && V8_HOST_ARCH_ARM
 #include "atomicops_internals_arm_gcc.h"
diff --git a/src/atomicops_internals_x86_gcc.cc b/src/atomicops_internals_x86_gcc.cc
index b5078cf..950b423 100644
--- a/src/atomicops_internals_x86_gcc.cc
+++ b/src/atomicops_internals_x86_gcc.cc
@@ -124,6 +124,7 @@
   }
 };
 
+
 // A global to get use initialized on startup via static initialization :/
 AtomicOpsx86Initializer g_initer;
 
diff --git a/src/bignum.cc b/src/bignum.cc
index c8b61ee..af0edde 100644
--- a/src/bignum.cc
+++ b/src/bignum.cc
@@ -45,6 +45,7 @@
   return 8 * sizeof(value);
 }
 
+
 // Guaranteed to lie in one Bigit.
 void Bignum::AssignUInt16(uint16_t value) {
   ASSERT(kBigitSize >= BitSize(value));
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 49333eb..dd3e94b 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1289,7 +1289,7 @@
       Builtins::kIllegal, false, true);
 
   Handle<Map> initial_map = isolate()->factory()->NewMap(
-      JS_TYPED_ARRAY_TYPE, JSTypedArray::kSize, elementsKind);
+      JS_TYPED_ARRAY_TYPE, JSTypedArray::kSizeWithInternalFields, elementsKind);
   result->set_initial_map(*initial_map);
   initial_map->set_constructor(*result);
   return result;
@@ -1373,7 +1373,7 @@
     Handle<JSFunction> data_view_fun =
         InstallFunction(
             global, "DataView", JS_DATA_VIEW_TYPE,
-            JSDataView::kSize,
+            JSDataView::kSizeWithInternalFields,
             isolate()->initial_object_prototype(),
             Builtins::kIllegal, true, true);
     native_context()->set_data_view_fun(*data_view_fun);
@@ -1586,6 +1586,7 @@
                  to_complete_property_descriptor);
 }
 
+
 void Genesis::InstallExperimentalNativeFunctions() {
   if (FLAG_harmony_proxies) {
     INSTALL_NATIVE(JSFunction, "DerivedHasTrap", derived_has_trap);
@@ -2239,10 +2240,12 @@
 #endif
 }
 
+
 static uint32_t Hash(RegisteredExtension* extension) {
   return v8::internal::ComputePointerHash(extension);
 }
 
+
 static bool MatchRegisteredExtensions(void* key1, void* key2) {
   return key1 == key2;
 }
diff --git a/src/builtins.cc b/src/builtins.cc
index be04ddf..f4ebdc2 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -182,6 +182,7 @@
   return result;
 }
 
+
 // ----------------------------------------------------------------------------
 
 BUILTIN(Illegal) {
@@ -1153,6 +1154,7 @@
       "strict_poison_pill", HandleVector<Object>(NULL, 0)));
 }
 
+
 // -----------------------------------------------------------------------------
 //
 
@@ -1432,14 +1434,17 @@
   KeyedLoadIC::GeneratePreMonomorphic(masm);
 }
 
+
 static void Generate_KeyedLoadIC_IndexedInterceptor(MacroAssembler* masm) {
   KeyedLoadIC::GenerateIndexedInterceptor(masm);
 }
 
+
 static void Generate_KeyedLoadIC_NonStrictArguments(MacroAssembler* masm) {
   KeyedLoadIC::GenerateNonStrictArguments(masm);
 }
 
+
 static void Generate_StoreIC_Slow(MacroAssembler* masm) {
   StoreIC::GenerateSlow(masm);
 }
@@ -1539,14 +1544,17 @@
   KeyedStoreIC::GenerateInitialize(masm);
 }
 
+
 static void Generate_KeyedStoreIC_NonStrictArguments(MacroAssembler* masm) {
   KeyedStoreIC::GenerateNonStrictArguments(masm);
 }
 
+
 static void Generate_TransitionElementsSmiToDouble(MacroAssembler* masm) {
   KeyedStoreIC::GenerateTransitionElementsSmiToDouble(masm);
 }
 
+
 static void Generate_TransitionElementsDoubleToObject(MacroAssembler* masm) {
   KeyedStoreIC::GenerateTransitionElementsDoubleToObject(masm);
 }
@@ -1716,6 +1724,7 @@
 #undef DEF_FUNCTION_PTR_A
 }
 
+
 void Builtins::SetUp(bool create_heap_objects) {
   ASSERT(!initialized_);
   Isolate* isolate = Isolate::Current();
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 96266af..9792096 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -329,7 +329,7 @@
     HValue* elements = AddLoadElements(boilerplate);
 
     IfBuilder if_fixed_cow(this);
-    if_fixed_cow.IfCompareMap(elements, factory->fixed_cow_array_map());
+    if_fixed_cow.If<HCompareMap>(elements, factory->fixed_cow_array_map());
     if_fixed_cow.Then();
     environment()->Push(BuildCloneShallowArray(context(),
                                                boilerplate,
@@ -339,7 +339,7 @@
     if_fixed_cow.Else();
 
     IfBuilder if_fixed(this);
-    if_fixed.IfCompareMap(elements, factory->fixed_array_map());
+    if_fixed.If<HCompareMap>(elements, factory->fixed_array_map());
     if_fixed.Then();
     environment()->Push(BuildCloneShallowArray(context(),
                                                boilerplate,
@@ -392,7 +392,8 @@
       AddInstruction(new(zone) HInstanceSize(boilerplate));
   HValue* size_in_words =
       AddInstruction(new(zone) HConstant(size >> kPointerSizeLog2));
-  checker.IfCompare(boilerplate_size, size_in_words, Token::EQ);
+  checker.If<HCompareNumericAndBranch>(boilerplate_size,
+                                       size_in_words, Token::EQ);
   checker.Then();
 
   HValue* size_in_bytes = AddInstruction(new(zone) HConstant(size));
@@ -501,7 +502,9 @@
 
   IfBuilder if_builder(this);
 
-  if_builder.IfCompare(array_length, graph()->GetConstant0(), Token::EQ);
+  if_builder.If<HCompareNumericAndBranch>(array_length,
+                                          graph()->GetConstant0(),
+                                          Token::EQ);
   if_builder.Then();
 
   // Nothing to do, just change the map.
@@ -606,7 +609,8 @@
 
   HBoundsCheck* checked_arg = Add<HBoundsCheck>(argument, max_alloc_length);
   IfBuilder if_builder(this);
-  if_builder.IfCompare(checked_arg, constant_zero, Token::EQ);
+  if_builder.If<HCompareNumericAndBranch>(checked_arg, constant_zero,
+                                          Token::EQ);
   if_builder.Then();
   Push(initial_capacity_node);  // capacity
   Push(constant_zero);  // length
@@ -764,13 +768,52 @@
 
 
 template <>
+HValue* CodeStubGraphBuilder<UnaryOpStub>::BuildCodeInitializedStub() {
+  UnaryOpStub* stub = casted_stub();
+  Handle<Type> type = stub->GetType(graph()->isolate());
+  HValue* input = GetParameter(0);
+
+  // Prevent unwanted HChange being inserted to ensure that the stub
+  // deopts on newly encountered types.
+  if (!type->Maybe(Type::Double())) {
+    input = AddInstruction(new(zone())
+        HForceRepresentation(input, Representation::Smi()));
+  }
+
+  if (!type->Is(Type::Number())) {
+    // If we expect to see other things than Numbers, we will create a generic
+    // stub, which handles all numbers and calls into the runtime for the rest.
+    IfBuilder if_number(this);
+    if_number.If<HIsNumberAndBranch>(input);
+    if_number.Then();
+    HInstruction* res = BuildUnaryMathOp(input, type, stub->operation());
+    if_number.Return(AddInstruction(res));
+    if_number.Else();
+    HValue* function = AddLoadJSBuiltin(stub->ToJSBuiltin(), context());
+    Add<HPushArgument>(GetParameter(0));
+    HValue* result = Add<HInvokeFunction>(context(), function, 1);
+    if_number.Return(result);
+    if_number.End();
+    return graph()->GetConstantUndefined();
+  }
+
+  return AddInstruction(BuildUnaryMathOp(input, type, stub->operation()));
+}
+
+
+Handle<Code> UnaryOpStub::GenerateCode() {
+  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.Return(graph()->GetConstant1());
   if_true.Else();
   if_true.End();
   return graph()->GetConstant0();
@@ -782,4 +825,50 @@
 }
 
 
+template <>
+HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
+  StoreGlobalStub* stub = casted_stub();
+  Handle<Object> hole(isolate()->heap()->the_hole_value(), isolate());
+  Handle<Object> placeholer_value(Smi::FromInt(0), isolate());
+  Handle<PropertyCell> placeholder_cell =
+      isolate()->factory()->NewPropertyCell(placeholer_value);
+
+  HParameter* receiver = GetParameter(0);
+  HParameter* value = GetParameter(2);
+
+  if (stub->is_constant()) {
+    // Assume every store to a constant value changes it.
+    current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
+    set_current_block(NULL);
+  } else {
+    HValue* cell = Add<HConstant>(placeholder_cell, Representation::Tagged());
+
+    // Check that the map of the global has not changed: use a placeholder map
+    // that will be replaced later with the global object's map.
+    Handle<Map> placeholder_map = isolate()->factory()->meta_map();
+    AddInstruction(HCheckMaps::New(receiver, placeholder_map, zone()));
+
+    // Load the payload of the global parameter cell. A hole indicates that the
+    // property has been deleted and that the store must be handled by the
+    // runtime.
+    HObjectAccess access(HObjectAccess::ForCellPayload(isolate()));
+    HValue* cell_contents = Add<HLoadNamedField>(cell, access);
+    IfBuilder builder(this);
+    HValue* hole_value = Add<HConstant>(hole, Representation::Tagged());
+    builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value);
+    builder.Then();
+    builder.Deopt();
+    builder.Else();
+    Add<HStoreNamedField>(cell, access, value);
+    builder.End();
+  }
+  return value;
+}
+
+
+Handle<Code> StoreGlobalStub::GenerateCode() {
+  return DoGenerateCode(this);
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 2ed2ba3..802e720 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -85,6 +85,14 @@
 }
 
 
+Handle<Code> CodeStub::GetCodeCopyFromTemplate(Isolate* isolate) {
+  Handle<Code> ic = GetCode(isolate);
+  ic = isolate->factory()->CopyCode(ic);
+  RecordCodeGeneration(*ic, isolate);
+  return ic;
+}
+
+
 Handle<Code> PlatformCodeStub::GenerateCode() {
   Isolate* isolate = Isolate::Current();
   Factory* factory = isolate->factory();
@@ -185,11 +193,82 @@
 }
 
 
-void CodeStub::PrintName(StringStream* stream) {
+void CodeStub::PrintBaseName(StringStream* stream) {
   stream->Add("%s", MajorName(MajorKey(), false));
 }
 
 
+void CodeStub::PrintName(StringStream* stream) {
+  PrintBaseName(stream);
+  PrintState(stream);
+}
+
+
+Builtins::JavaScript UnaryOpStub::ToJSBuiltin() {
+  switch (operation_) {
+    default:
+      UNREACHABLE();
+    case Token::SUB:
+      return Builtins::UNARY_MINUS;
+    case Token::BIT_NOT:
+      return Builtins::BIT_NOT;
+  }
+}
+
+
+Handle<JSFunction> UnaryOpStub::ToJSFunction(Isolate* isolate) {
+  Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
+  Object* builtin = builtins->javascript_builtin(ToJSBuiltin());
+  return Handle<JSFunction>(JSFunction::cast(builtin), isolate);
+}
+
+
+MaybeObject* UnaryOpStub::Result(Handle<Object> object, Isolate* isolate) {
+  Handle<JSFunction> builtin_function = ToJSFunction(isolate);
+  bool caught_exception;
+  Handle<Object> result = Execution::Call(builtin_function, object,
+                                          0, NULL, &caught_exception);
+  if (caught_exception) {
+    return Failure::Exception();
+  }
+  return *result;
+}
+
+
+void UnaryOpStub::UpdateStatus(Handle<Object> object) {
+  State old_state(state_);
+  if (object->IsSmi()) {
+    state_.Add(SMI);
+    if (operation_ == Token::SUB && *object == 0) {
+      // The result (-0) has to be represented as double.
+      state_.Add(HEAP_NUMBER);
+    }
+  } else if (object->IsHeapNumber()) {
+    state_.Add(HEAP_NUMBER);
+  } else {
+    state_.Add(GENERIC);
+  }
+  TraceTransition(old_state, state_);
+}
+
+
+Handle<Type> UnaryOpStub::GetType(Isolate* isolate) {
+  if (state_.Contains(GENERIC)) {
+    return handle(Type::Any(), isolate);
+  }
+  Handle<Type> type = handle(Type::None(), isolate);
+  if (state_.Contains(SMI)) {
+    type = handle(
+        Type::Union(type, handle(Type::Smi(), isolate)), isolate);
+  }
+  if (state_.Contains(HEAP_NUMBER)) {
+    type = handle(
+        Type::Union(type, handle(Type::Double(), isolate)), isolate);
+  }
+  return type;
+}
+
+
 void BinaryOpStub::Generate(MacroAssembler* masm) {
   // Explicitly allow generation of nested stubs. It is safe here because
   // generation code does not use any raw pointers.
@@ -275,6 +354,29 @@
 #undef __
 
 
+void UnaryOpStub::PrintBaseName(StringStream* stream) {
+  CodeStub::PrintBaseName(stream);
+  if (operation_ == Token::SUB) stream->Add("Minus");
+  if (operation_ == Token::BIT_NOT) stream->Add("Not");
+}
+
+
+void UnaryOpStub::PrintState(StringStream* stream) {
+  state_.Print(stream);
+}
+
+
+void UnaryOpStub::State::Print(StringStream* stream) const {
+  stream->Add("(");
+  SimpleListPrinter printer(stream);
+  if (IsEmpty()) printer.Add("None");
+  if (Contains(GENERIC)) printer.Add("Generic");
+  if (Contains(HEAP_NUMBER)) printer.Add("HeapNumber");
+  if (Contains(SMI)) printer.Add("Smi");
+  stream->Add(")");
+}
+
+
 void BinaryOpStub::PrintName(StringStream* stream) {
   const char* op_name = Token::Name(op_);
   const char* overwrite_name;
@@ -431,8 +533,9 @@
 }
 
 
-void CompareNilICStub::Record(Handle<Object> object) {
+void CompareNilICStub::UpdateStatus(Handle<Object> object) {
   ASSERT(state_ != State::Generic());
+  State old_state(state_);
   if (object->IsNull()) {
     state_.Add(NULL_TYPE);
   } else if (object->IsUndefined()) {
@@ -446,18 +549,22 @@
   } else {
     state_.Add(MONOMORPHIC_MAP);
   }
+  TraceTransition(old_state, state_);
 }
 
 
-void CompareNilICStub::State::TraceTransition(State to) const {
+template<class StateType>
+void HydrogenCodeStub::TraceTransition(StateType from, StateType to) {
   #ifdef DEBUG
   if (!FLAG_trace_ic) return;
   char buffer[100];
   NoAllocationStringAllocator allocator(buffer,
                                         static_cast<unsigned>(sizeof(buffer)));
   StringStream stream(&allocator);
-  stream.Add("[CompareNilIC : ");
-  Print(&stream);
+  stream.Add("[");
+  PrintBaseName(&stream);
+  stream.Add(": ");
+  from.Print(&stream);
   stream.Add("=>");
   to.Print(&stream);
   stream.Add("]\n");
@@ -466,11 +573,15 @@
 }
 
 
-void CompareNilICStub::PrintName(StringStream* stream) {
-  stream->Add("CompareNilICStub_");
+void CompareNilICStub::PrintBaseName(StringStream* stream) {
+  CodeStub::PrintBaseName(stream);
+  stream->Add((nil_value_ == kNullValue) ? "(NullValue)":
+                                           "(UndefinedValue)");
+}
+
+
+void CompareNilICStub::PrintState(StringStream* stream) {
   state_.Print(stream);
-  stream->Add((nil_value_ == kNullValue) ? "(NullValue|":
-                                           "(UndefinedValue|");
 }
 
 
@@ -615,16 +726,15 @@
 }
 
 
-bool ToBooleanStub::Record(Handle<Object> object) {
+bool ToBooleanStub::UpdateStatus(Handle<Object> object) {
   Types old_types(types_);
-  bool to_boolean_value = types_.Record(object);
-  old_types.TraceTransition(types_);
+  bool to_boolean_value = types_.UpdateStatus(object);
+  TraceTransition(old_types, types_);
   return to_boolean_value;
 }
 
 
-void ToBooleanStub::PrintName(StringStream* stream) {
-  stream->Add("ToBooleanStub_");
+void ToBooleanStub::PrintState(StringStream* stream) {
   types_.Print(stream);
 }
 
@@ -645,24 +755,7 @@
 }
 
 
-void ToBooleanStub::Types::TraceTransition(Types to) const {
-  #ifdef DEBUG
-  if (!FLAG_trace_ic) return;
-  char buffer[100];
-  NoAllocationStringAllocator allocator(buffer,
-                                        static_cast<unsigned>(sizeof(buffer)));
-  StringStream stream(&allocator);
-  stream.Add("[ToBooleanIC : ");
-  Print(&stream);
-  stream.Add("=>");
-  to.Print(&stream);
-  stream.Add("]\n");
-  stream.OutputToStdOut();
-  #endif
-}
-
-
-bool ToBooleanStub::Types::Record(Handle<Object> object) {
+bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
   if (object->IsUndefined()) {
     Add(UNDEFINED);
     return false;
diff --git a/src/code-stubs.h b/src/code-stubs.h
index d197c84..0eefe8c 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -90,6 +90,7 @@
   V(ArrayConstructor)                    \
   V(InternalArrayConstructor)            \
   V(ProfileEntryHook)                    \
+  V(StoreGlobal)                         \
   /* IC Handler stubs */                 \
   V(LoadField)                           \
   V(KeyedLoadField)
@@ -123,8 +124,6 @@
 
 // Mode to overwrite BinaryExpression values.
 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
-enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
-
 
 // Stub is base classes of all stubs.
 class CodeStub BASE_EMBEDDED {
@@ -140,6 +139,8 @@
   // Retrieve the code for the stub. Generate the code if needed.
   Handle<Code> GetCode(Isolate* isolate);
 
+  // Retrieve the code for the stub, make and return a copy of the code.
+  Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate);
   static Major MajorKeyFromKey(uint32_t key) {
     return static_cast<Major>(MajorKeyBits::decode(key));
   }
@@ -197,6 +198,8 @@
     return -1;
   }
 
+  virtual void PrintName(StringStream* stream);
+
  protected:
   static bool CanUseFPRegisters();
 
@@ -208,6 +211,11 @@
   // a fixed (non-moveable) code object.
   virtual bool NeedsImmovableCode() { return false; }
 
+  // Returns a name for logging/debugging purposes.
+  SmartArrayPointer<const char> GetName();
+  virtual void PrintBaseName(StringStream* stream);
+  virtual void PrintState(StringStream* stream) { }
+
  private:
   // Perform bookkeeping required after code generation when stub code is
   // initially generated.
@@ -236,10 +244,6 @@
   // If a stub uses a special cache override this.
   virtual bool UseSpecialCache() { return false; }
 
-  // Returns a name for logging/debugging purposes.
-  SmartArrayPointer<const char> GetName();
-  virtual void PrintName(StringStream* stream);
-
   // Computes the key based on major and minor.
   uint32_t GetKey() {
     ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
@@ -354,6 +358,9 @@
 
   Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
 
+  template<class StateType>
+  void TraceTransition(StateType from, StateType to);
+
  private:
   class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
   class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
@@ -519,6 +526,117 @@
   int MinorKey() { return slots_; }
 };
 
+class StoreGlobalStub : public HydrogenCodeStub {
+ public:
+  StoreGlobalStub(StrictModeFlag strict_mode, bool is_constant) {
+    bit_field_ = StrictModeBits::encode(strict_mode) |
+        IsConstantBits::encode(is_constant);
+  }
+
+  virtual Handle<Code> GenerateCode();
+
+  virtual void InitializeInterfaceDescriptor(
+      Isolate* isolate,
+      CodeStubInterfaceDescriptor* descriptor);
+
+  virtual Code::Kind GetCodeKind() const { return Code::STORE_IC; }
+  virtual InlineCacheState GetICState() { return MONOMORPHIC; }
+  virtual Code::ExtraICState GetExtraICState() { return bit_field_; }
+
+  bool is_constant() {
+    return IsConstantBits::decode(bit_field_);
+  }
+  void set_is_constant(bool value) {
+    bit_field_ = IsConstantBits::update(bit_field_, value);
+  }
+
+  Representation representation() {
+    return Representation::FromKind(RepresentationBits::decode(bit_field_));
+  }
+  void set_representation(Representation r) {
+    bit_field_ = RepresentationBits::update(bit_field_, r.kind());
+  }
+
+ private:
+  virtual int NotMissMinorKey() { return GetExtraICState(); }
+  Major MajorKey() { return StoreGlobal; }
+
+  class StrictModeBits: public BitField<StrictModeFlag, 0, 1> {};
+  class IsConstantBits: public BitField<bool, 1, 1> {};
+  class RepresentationBits: public BitField<Representation::Kind, 2, 8> {};
+
+  int bit_field_;
+
+  DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
+};
+
+
+class UnaryOpStub : public HydrogenCodeStub {
+ public:
+  // Stub without type info available -> construct uninitialized
+  explicit UnaryOpStub(Token::Value operation)
+      : HydrogenCodeStub(UNINITIALIZED), operation_(operation) { }
+  explicit UnaryOpStub(Code::ExtraICState ic_state) :
+      state_(StateBits::decode(ic_state)),
+      operation_(OperatorBits::decode(ic_state)) { }
+
+  virtual void InitializeInterfaceDescriptor(
+      Isolate* isolate,
+      CodeStubInterfaceDescriptor* descriptor);
+
+  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
+  virtual InlineCacheState GetICState() {
+    if (state_.Contains(GENERIC)) {
+      return MEGAMORPHIC;
+    } else if (state_.IsEmpty()) {
+      return PREMONOMORPHIC;
+    } else {
+      return MONOMORPHIC;
+    }
+  }
+  virtual Code::ExtraICState GetExtraICState() {
+    return OperatorBits::encode(operation_) |
+           StateBits::encode(state_.ToIntegral());
+  }
+
+  Token::Value operation() { return operation_; }
+  Handle<JSFunction> ToJSFunction(Isolate* isolate);
+  Builtins::JavaScript ToJSBuiltin();
+
+  void UpdateStatus(Handle<Object> object);
+  MaybeObject* Result(Handle<Object> object, Isolate* isolate);
+  Handle<Code> GenerateCode();
+  Handle<Type> GetType(Isolate* isolate);
+
+ protected:
+  void PrintState(StringStream* stream);
+  void PrintBaseName(StringStream* stream);
+
+ private:
+  enum UnaryOpType {
+    SMI,
+    HEAP_NUMBER,
+    GENERIC,
+    NUMBER_OF_TYPES
+  };
+
+  class State : public EnumSet<UnaryOpType, byte> {
+   public:
+    State() : EnumSet<UnaryOpType, byte>() { }
+    explicit State(byte bits) : EnumSet<UnaryOpType, byte>(bits) { }
+    void Print(StringStream* stream) const;
+  };
+
+  class StateBits : public BitField<int, 0, NUMBER_OF_TYPES> { };
+  class OperatorBits : public BitField<Token::Value, NUMBER_OF_TYPES, 8> { };
+
+  State state_;
+  Token::Value operation_;
+
+  virtual CodeStub::Major MajorKey() { return UnaryOp; }
+  virtual int NotMissMinorKey() { return GetExtraICState(); }
+};
+
 
 class FastCloneShallowArrayStub : public HydrogenCodeStub {
  public:
@@ -1143,7 +1261,6 @@
     }
 
     void Print(StringStream* stream) const;
-    void TraceTransition(State to) const;
   };
 
   static Handle<Type> StateToType(
@@ -1206,14 +1323,15 @@
     return NilValueField::decode(state);
   }
 
-  void Record(Handle<Object> object);
+  void UpdateStatus(Handle<Object> object);
 
   bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
   NilValue GetNilValue() const { return nil_value_; }
   State GetState() const { return state_; }
   void ClearState() { state_.RemoveAll(); }
 
-  virtual void PrintName(StringStream* stream);
+  virtual void PrintState(StringStream* stream);
+  virtual void PrintBaseName(StringStream* stream);
 
  private:
   friend class CompareNilIC;
@@ -2009,8 +2127,7 @@
 
     byte ToByte() const { return ToIntegral(); }
     void Print(StringStream* stream) const;
-    void TraceTransition(Types to) const;
-    bool Record(Handle<Object> object);
+    bool UpdateStatus(Handle<Object> object);
     bool NeedsMap() const;
     bool CanBeUndetectable() const;
     bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
@@ -2023,7 +2140,7 @@
   explicit ToBooleanStub(Code::ExtraICState state)
       : types_(static_cast<byte>(state)) { }
 
-  bool Record(Handle<Object> object);
+  bool UpdateStatus(Handle<Object> object);
   Types GetTypes() { return types_; }
 
   virtual Handle<Code> GenerateCode();
@@ -2032,7 +2149,7 @@
       CodeStubInterfaceDescriptor* descriptor);
 
   virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
-  virtual void PrintName(StringStream* stream);
+  virtual void PrintState(StringStream* stream);
 
   virtual bool SometimesSetsUpAFrame() { return false; }
 
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index 7ace2f7..18c82e9 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -86,6 +86,7 @@
   return result;
 }
 
+
 void CompilationSubCache::Age() {
   // Age the generations implicitly killing off the oldest.
   for (int i = generations_ - 1; i > 0; i--) {
diff --git a/src/compiler.cc b/src/compiler.cc
index 8edb41d..7497f09 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -449,6 +449,7 @@
   return SetLastStatus(SUCCEEDED);
 }
 
+
 OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
   DisallowHeapAllocation no_allocation;
   DisallowHandleAllocation no_handles;
@@ -1199,9 +1200,9 @@
     Handle<Code> code = info->code();
     if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
       return;
+    int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
+    USE(line_num);
     if (script->name()->IsString()) {
-      int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
-      USE(line_num);
       PROFILE(info->isolate(),
               CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
                               *code,
@@ -1215,7 +1216,8 @@
                               *code,
                               *shared,
                               info,
-                              shared->DebugName()));
+                              info->isolate()->heap()->empty_string(),
+                              line_num));
     }
   }
 
diff --git a/src/contexts.cc b/src/contexts.cc
index 5edbc5a..58f23e7 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -88,6 +88,7 @@
   return native_context()->global_proxy_object();
 }
 
+
 void Context::set_global_proxy(JSObject* object) {
   native_context()->set_global_proxy_object(object);
 }
diff --git a/src/counters.cc b/src/counters.cc
index fa192ba..1839412 100644
--- a/src/counters.cc
+++ b/src/counters.cc
@@ -56,6 +56,7 @@
       CreateHistogram(name_, min_, max_, num_buckets_);
 }
 
+
 // Start the timer.
 void HistogramTimer::Start() {
   if (Enabled()) {
@@ -67,6 +68,7 @@
   }
 }
 
+
 // Stop the timer and record the results.
 void HistogramTimer::Stop() {
   if (Enabled()) {
diff --git a/src/cpu-profiler-inl.h b/src/cpu-profiler-inl.h
index c3cc27c..bafea06 100644
--- a/src/cpu-profiler-inl.h
+++ b/src/cpu-profiler-inl.h
@@ -70,7 +70,7 @@
 TickSample* ProfilerEventsProcessor::TickSampleEvent() {
   generator_->Tick();
   TickSampleEventRecord* evt =
-      new(ticks_buffer_.Enqueue()) TickSampleEventRecord(enqueue_order_);
+      new(ticks_buffer_.Enqueue()) TickSampleEventRecord(last_code_event_id_);
   return &evt->sample;
 }
 
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index b3800f5..d3fadb5 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -52,18 +52,18 @@
       ticks_buffer_(sizeof(TickSampleEventRecord),
                     kTickSamplesBufferChunkSize,
                     kTickSamplesBufferChunksCount),
-      enqueue_order_(0) {
+      last_code_event_id_(0), last_processed_code_event_id_(0) {
 }
 
 
 void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) {
-  event.generic.order = ++enqueue_order_;
+  event.generic.order = ++last_code_event_id_;
   events_buffer_.Enqueue(event);
 }
 
 
 void ProfilerEventsProcessor::AddCurrentStack(Isolate* isolate) {
-  TickSampleEventRecord record(enqueue_order_);
+  TickSampleEventRecord record(last_code_event_id_);
   TickSample* sample = &record.sample;
   sample->state = isolate->current_vm_state();
   sample->pc = reinterpret_cast<Address>(sample);  // Not NULL.
@@ -76,7 +76,14 @@
 }
 
 
-bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
+void ProfilerEventsProcessor::StopSynchronously() {
+  if (!running_) return;
+  running_ = false;
+  Join();
+}
+
+
+bool ProfilerEventsProcessor::ProcessCodeEvent() {
   CodeEventsContainer record;
   if (events_buffer_.Dequeue(&record)) {
     switch (record.generic.type) {
@@ -90,17 +97,18 @@
 #undef PROFILER_TYPE_CASE
       default: return true;  // Skip record.
     }
-    *dequeue_order = record.generic.order;
+    last_processed_code_event_id_ = record.generic.order;
     return true;
   }
   return false;
 }
 
 
-bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) {
+bool ProfilerEventsProcessor::ProcessTicks() {
   while (true) {
     if (!ticks_from_vm_buffer_.IsEmpty()
-        && ticks_from_vm_buffer_.Peek()->order == dequeue_order) {
+        && ticks_from_vm_buffer_.Peek()->order ==
+           last_processed_code_event_id_) {
       TickSampleEventRecord record;
       ticks_from_vm_buffer_.Dequeue(&record);
       generator_->RecordTickSample(record.sample);
@@ -115,56 +123,46 @@
     // will get far behind, a record may be modified right under its
     // feet.
     TickSampleEventRecord record = *rec;
-    if (record.order == dequeue_order) {
-      // A paranoid check to make sure that we don't get a memory overrun
-      // in case of frames_count having a wild value.
-      if (record.sample.frames_count < 0
-          || record.sample.frames_count > TickSample::kMaxFramesCount)
-        record.sample.frames_count = 0;
-      generator_->RecordTickSample(record.sample);
-      ticks_buffer_.FinishDequeue();
-    } else {
-      return true;
-    }
+    if (record.order != last_processed_code_event_id_) return true;
+
+    // A paranoid check to make sure that we don't get a memory overrun
+    // in case of frames_count having a wild value.
+    if (record.sample.frames_count < 0
+        || record.sample.frames_count > TickSample::kMaxFramesCount)
+      record.sample.frames_count = 0;
+    generator_->RecordTickSample(record.sample);
+    ticks_buffer_.FinishDequeue();
   }
 }
 
 
 void ProfilerEventsProcessor::Run() {
-  unsigned dequeue_order = 0;
-
   while (running_) {
     // Process ticks until we have any.
-    if (ProcessTicks(dequeue_order)) {
-      // All ticks of the current dequeue_order are processed,
+    if (ProcessTicks()) {
+      // All ticks of the current last_processed_code_event_id_ are processed,
       // proceed to the next code event.
-      ProcessCodeEvent(&dequeue_order);
+      ProcessCodeEvent();
     }
     YieldCPU();
   }
 
   // Process remaining tick events.
   ticks_buffer_.FlushResidualRecords();
-  // Perform processing until we have tick events, skip remaining code events.
-  while (ProcessTicks(dequeue_order) && ProcessCodeEvent(&dequeue_order)) { }
+  do {
+    ProcessTicks();
+  } while (ProcessCodeEvent());
 }
 
 
 int CpuProfiler::GetProfilesCount() {
   // The count of profiles doesn't depend on a security token.
-  return profiles_->Profiles(TokenEnumerator::kNoSecurityToken)->length();
+  return profiles_->profiles()->length();
 }
 
 
-CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
-  const int token = token_enumerator_->GetTokenId(security_token);
-  return profiles_->Profiles(token)->at(index);
-}
-
-
-CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
-  const int token = token_enumerator_->GetTokenId(security_token);
-  return profiles_->GetProfile(token, uid);
+CpuProfile* CpuProfiler::GetProfile(int index) {
+  return profiles_->profiles()->at(index);
 }
 
 
@@ -186,11 +184,6 @@
 }
 
 
-bool CpuProfiler::HasDetachedProfiles() {
-  return profiles_->HasDetachedProfiles();
-}
-
-
 static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag) {
   return FLAG_prof_browser_mode
       && (tag != Logger::CALLBACK_TAG
@@ -208,8 +201,7 @@
   rec->start = entry_point;
   rec->entry = profiles_->NewCodeEntry(
       Logger::CALLBACK_TAG,
-      profiles_->GetName(name),
-      TokenEnumerator::kInheritsSecurityToken);
+      profiles_->GetName(name));
   rec->size = 1;
   rec->shared = NULL;
   processor_->Enqueue(evt_rec);
@@ -280,7 +272,6 @@
   rec->entry = profiles_->NewCodeEntry(
       tag,
       profiles_->GetFunctionName(shared->DebugName()),
-      TokenEnumerator::kNoSecurityToken,
       CodeEntry::kEmptyNamePrefix,
       profiles_->GetName(source),
       line);
@@ -306,7 +297,6 @@
   rec->entry = profiles_->NewCodeEntry(
       tag,
       profiles_->GetName(args_count),
-      TokenEnumerator::kInheritsSecurityToken,
       "args_count: ");
   rec->size = code->ExecutableSize();
   rec->shared = NULL;
@@ -345,7 +335,6 @@
   rec->entry = profiles_->NewCodeEntry(
       Logger::CALLBACK_TAG,
       profiles_->GetName(name),
-      TokenEnumerator::kInheritsSecurityToken,
       "get ");
   rec->size = 1;
   rec->shared = NULL;
@@ -361,7 +350,6 @@
   rec->entry = profiles_->NewCodeEntry(
       Logger::REG_EXP_TAG,
       profiles_->GetName(source),
-      TokenEnumerator::kInheritsSecurityToken,
       "RegExp: ");
   rec->size = code->ExecutableSize();
   processor_->Enqueue(evt_rec);
@@ -376,7 +364,6 @@
   rec->entry = profiles_->NewCodeEntry(
       Logger::CALLBACK_TAG,
       profiles_->GetName(name),
-      TokenEnumerator::kInheritsSecurityToken,
       "set ");
   rec->size = 1;
   rec->shared = NULL;
@@ -388,7 +375,6 @@
     : isolate_(isolate),
       profiles_(new CpuProfilesCollection()),
       next_profile_uid_(1),
-      token_enumerator_(new TokenEnumerator()),
       generator_(NULL),
       processor_(NULL),
       need_to_stop_sampler_(false),
@@ -403,7 +389,6 @@
     : isolate_(isolate),
       profiles_(test_profiles),
       next_profile_uid_(1),
-      token_enumerator_(new TokenEnumerator()),
       generator_(test_generator),
       processor_(test_processor),
       need_to_stop_sampler_(false),
@@ -413,7 +398,6 @@
 
 CpuProfiler::~CpuProfiler() {
   ASSERT(!is_profiling_);
-  delete token_enumerator_;
   delete profiles_;
 }
 
@@ -423,6 +407,7 @@
   profiles_ = new CpuProfilesCollection();
 }
 
+
 void CpuProfiler::StartProfiling(const char* title, bool record_samples) {
   if (profiles_->StartProfiling(title, next_profile_uid_++, record_samples)) {
     StartProcessorIfNotStarted();
@@ -469,10 +454,7 @@
   if (!is_profiling_) return NULL;
   const double actual_sampling_rate = generator_->actual_sampling_rate();
   StopProcessorIfLastProfile(title);
-  CpuProfile* result =
-      profiles_->StopProfiling(TokenEnumerator::kNoSecurityToken,
-                               title,
-                               actual_sampling_rate);
+  CpuProfile* result = profiles_->StopProfiling(title, actual_sampling_rate);
   if (result != NULL) {
     result->Print();
   }
@@ -480,13 +462,12 @@
 }
 
 
-CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
+CpuProfile* CpuProfiler::StopProfiling(String* title) {
   if (!is_profiling_) return NULL;
   const double actual_sampling_rate = generator_->actual_sampling_rate();
   const char* profile_title = profiles_->GetName(title);
   StopProcessorIfLastProfile(profile_title);
-  int token = token_enumerator_->GetTokenId(security_token);
-  return profiles_->StopProfiling(token, profile_title, actual_sampling_rate);
+  return profiles_->StopProfiling(profile_title, actual_sampling_rate);
 }
 
 
@@ -504,8 +485,7 @@
     need_to_stop_sampler_ = false;
   }
   is_profiling_ = false;
-  processor_->Stop();
-  processor_->Join();
+  processor_->StopSynchronously();
   delete processor_;
   delete generator_;
   processor_ = NULL;
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index 77fdb06..0718a89 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -44,7 +44,6 @@
 class CpuProfile;
 class CpuProfilesCollection;
 class ProfileGenerator;
-class TokenEnumerator;
 
 #define CODE_EVENTS_TYPE_LIST(V)                                   \
   V(CODE_CREATION,    CodeCreateEventRecord)                       \
@@ -156,7 +155,7 @@
 
   // Thread control.
   virtual void Run();
-  inline void Stop() { running_ = false; }
+  void StopSynchronously();
   INLINE(bool running()) { return running_; }
   void Enqueue(const CodeEventsContainer& event);
 
@@ -171,15 +170,16 @@
 
  private:
   // Called from events processing thread (Run() method.)
-  bool ProcessCodeEvent(unsigned* dequeue_order);
-  bool ProcessTicks(unsigned dequeue_order);
+  bool ProcessCodeEvent();
+  bool ProcessTicks();
 
   ProfileGenerator* generator_;
   bool running_;
   UnboundQueue<CodeEventsContainer> events_buffer_;
   SamplingCircularQueue ticks_buffer_;
   UnboundQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
-  unsigned enqueue_order_;
+  unsigned last_code_event_id_;
+  unsigned last_processed_code_event_id_;
 };
 
 
@@ -208,13 +208,11 @@
   void StartProfiling(const char* title, bool record_samples = false);
   void StartProfiling(String* title, bool record_samples);
   CpuProfile* StopProfiling(const char* title);
-  CpuProfile* StopProfiling(Object* security_token, String* title);
+  CpuProfile* StopProfiling(String* title);
   int GetProfilesCount();
-  CpuProfile* GetProfile(Object* security_token, int index);
-  CpuProfile* FindProfile(Object* security_token, unsigned uid);
+  CpuProfile* GetProfile(int index);
   void DeleteAllProfiles();
   void DeleteProfile(CpuProfile* profile);
-  bool HasDetachedProfiles();
 
   // Invoked from stack sampler (thread or signal handler.)
   TickSample* TickSampleEvent();
@@ -251,6 +249,9 @@
     return &is_profiling_;
   }
 
+  ProfileGenerator* generator() const { return generator_; }
+  ProfilerEventsProcessor* processor() const { return processor_; }
+
  private:
   void StartProcessorIfNotStarted();
   void StopProcessorIfLastProfile(const char* title);
@@ -261,7 +262,6 @@
   Isolate* isolate_;
   CpuProfilesCollection* profiles_;
   unsigned next_profile_uid_;
-  TokenEnumerator* token_enumerator_;
   ProfileGenerator* generator_;
   ProfilerEventsProcessor* processor_;
   int saved_logging_nesting_;
diff --git a/src/d8.cc b/src/d8.cc
index 65af987..cb43d2f 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -1087,6 +1087,7 @@
   array_buffer->Dispose();
 }
 
+
 void Shell::ReadBuffer(const v8::FunctionCallbackInfo<v8::Value>& args) {
   ASSERT(sizeof(char) == sizeof(uint8_t));  // NOLINT
   String::Utf8Value filename(args[0]);
diff --git a/src/dateparser.cc b/src/dateparser.cc
index 4a0721f..3964e81 100644
--- a/src/dateparser.cc
+++ b/src/dateparser.cc
@@ -112,6 +112,7 @@
   return true;
 }
 
+
 bool DateParser::TimeZoneComposer::Write(FixedArray* output) {
   if (sign_ != kNone) {
     if (hour_ == kNone) hour_ = 0;
diff --git a/src/debug.cc b/src/debug.cc
index 07c1a0c..5d39a1c 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1811,6 +1811,7 @@
   thread_local_.step_count_ = 0;
 }
 
+
 // Clears all the one-shot break points that are currently set. Normally this
 // function is called each time a break point is hit as one shot break points
 // are used to support stepping.
diff --git a/src/disassembler.cc b/src/disassembler.cc
index 5ec1dcb..fa8ae1f 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -360,6 +360,8 @@
 int Disassembler::Decode(Isolate* isolate, FILE* f, byte* begin, byte* end) {
   return 0;
 }
+
+
 void Disassembler::Decode(FILE* f, Code* code) {}
 
 #endif  // ENABLE_DISASSEMBLER
diff --git a/src/elements-kind.cc b/src/elements-kind.cc
index 7b1651a..213aa35 100644
--- a/src/elements-kind.cc
+++ b/src/elements-kind.cc
@@ -83,6 +83,7 @@
   return fast_elements_kind_sequence.Get()[sequence_number];
 }
 
+
 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
   for (int i = 0; i < kFastElementsKindCount; ++i) {
     if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
diff --git a/src/execution.cc b/src/execution.cc
index 38e7a3b..d7b9cf5 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -865,6 +865,7 @@
   return isolate->heap()->undefined_value();
 }
 
+
 void Execution::ProcessDebugMessages(bool debug_command_only) {
   Isolate* isolate = Isolate::Current();
   // Clear the debug command request flag.
diff --git a/src/extensions/i18n/break-iterator.cc b/src/extensions/i18n/break-iterator.cc
index 1225360..0681e26 100644
--- a/src/extensions/i18n/break-iterator.cc
+++ b/src/extensions/i18n/break-iterator.cc
@@ -82,6 +82,7 @@
   object->Dispose(isolate);
 }
 
+
 // Throws a JavaScript exception.
 static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
   // Returns undefined, and schedules an exception to be thrown.
@@ -90,6 +91,7 @@
                       "that is not a BreakIterator.")));
 }
 
+
 // Deletes the old value and sets the adopted text in corresponding
 // JavaScript object.
 icu::UnicodeString* ResetAdoptedText(
diff --git a/src/extensions/i18n/collator.cc b/src/extensions/i18n/collator.cc
index 4ffa414..61b1d63 100644
--- a/src/extensions/i18n/collator.cc
+++ b/src/extensions/i18n/collator.cc
@@ -76,6 +76,7 @@
   object->Dispose(isolate);
 }
 
+
 // Throws a JavaScript exception.
 static v8::Handle<v8::Value> ThrowUnexpectedObjectError() {
   // Returns undefined, and schedules an exception to be thrown.
@@ -84,11 +85,13 @@
                       "that is not a Collator.")));
 }
 
+
 // When there's an ICU error, throw a JavaScript error with |message|.
 static v8::Handle<v8::Value> ThrowExceptionForICUError(const char* message) {
   return v8::ThrowException(v8::Exception::Error(v8::String::New(message)));
 }
 
+
 // static
 void Collator::JSInternalCompare(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
diff --git a/src/extensions/i18n/i18n-extension.cc b/src/extensions/i18n/i18n-extension.cc
index eb7652e..1c77b88 100644
--- a/src/extensions/i18n/i18n-extension.cc
+++ b/src/extensions/i18n/i18n-extension.cc
@@ -108,6 +108,7 @@
   return v8::Handle<v8::FunctionTemplate>();
 }
 
+
 void Extension::Register() {
   static Extension i18n_extension;
   static v8::DeclareExtension extension_declaration(&i18n_extension);
diff --git a/src/extensions/i18n/i18n-utils.cc b/src/extensions/i18n/i18n-utils.cc
index d8d3c12..b720329 100644
--- a/src/extensions/i18n/i18n-utils.cc
+++ b/src/extensions/i18n/i18n-utils.cc
@@ -42,6 +42,7 @@
   dest[length - 1] = '\0';
 }
 
+
 // static
 bool Utils::V8StringToUnicodeString(const v8::Handle<v8::Value>& input,
                                     icu::UnicodeString* output) {
@@ -54,6 +55,7 @@
   return true;
 }
 
+
 // static
 bool Utils::ExtractStringSetting(const v8::Handle<v8::Object>& settings,
                                  const char* setting,
@@ -74,6 +76,7 @@
   return false;
 }
 
+
 // static
 bool Utils::ExtractIntegerSetting(const v8::Handle<v8::Object>& settings,
                                   const char* setting,
@@ -95,6 +98,7 @@
   return false;
 }
 
+
 // static
 bool Utils::ExtractBooleanSetting(const v8::Handle<v8::Object>& settings,
                                   const char* setting,
@@ -116,6 +120,7 @@
   return false;
 }
 
+
 // static
 void Utils::AsciiToUChar(const char* source,
                          int32_t source_length,
@@ -135,6 +140,7 @@
   target[length - 1] = 0x0u;
 }
 
+
 // static
 // Chrome Linux doesn't like static initializers in class, so we create
 // template on demand.
@@ -153,6 +159,7 @@
   return v8::Local<v8::ObjectTemplate>::New(isolate, icu_template);
 }
 
+
 // static
 // Chrome Linux doesn't like static initializers in class, so we create
 // template on demand. This one has 2 internal fields.
diff --git a/src/extensions/i18n/locale.cc b/src/extensions/i18n/locale.cc
index b32cc30..6b6f9ac 100644
--- a/src/extensions/i18n/locale.cc
+++ b/src/extensions/i18n/locale.cc
@@ -82,6 +82,7 @@
   args.GetReturnValue().Set(v8::String::New(result));
 }
 
+
 void JSAvailableLocalesOf(const v8::FunctionCallbackInfo<v8::Value>& args) {
   // Expect service name which is a string.
   if (args.Length() != 1 || !args[0]->IsString()) {
@@ -131,6 +132,7 @@
   args.GetReturnValue().Set(locales);
 }
 
+
 void JSGetDefaultICULocale(const v8::FunctionCallbackInfo<v8::Value>& args) {
   icu::Locale default_locale;
 
@@ -147,6 +149,7 @@
   args.GetReturnValue().Set(v8::String::New("und"));
 }
 
+
 void JSGetLanguageTagVariants(const v8::FunctionCallbackInfo<v8::Value>& args) {
   v8::TryCatch try_catch;
 
diff --git a/src/factory.cc b/src/factory.cc
index 63b2379..6efc2c2 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -178,6 +178,7 @@
                      String);
 }
 
+
 // Internalized strings are created in the old generation (data space).
 Handle<String> Factory::InternalizeString(Handle<String> string) {
   CALL_HEAP_FUNCTION(isolate(),
@@ -185,6 +186,7 @@
                      String);
 }
 
+
 Handle<String> Factory::InternalizeOneByteString(Vector<const uint8_t> string) {
   CALL_HEAP_FUNCTION(isolate(),
                      isolate()->heap()->InternalizeOneByteString(string),
@@ -1235,6 +1237,7 @@
                      JSMessageObject);
 }
 
+
 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
   CALL_HEAP_FUNCTION(isolate(),
                      isolate()->heap()->AllocateSharedFunctionInfo(*name),
diff --git a/src/factory.h b/src/factory.h
index 0cb7157..b39c4f4 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -564,6 +564,82 @@
 }
 
 
+// Used to "safely" transition from pointer-based runtime code to Handle-based
+// runtime code. When a GC happens during the called Handle-based code, a
+// failure object is returned to the pointer-based code to cause it abort and
+// re-trigger a gc of it's own. Since this double-gc will cause the Handle-based
+// code to be called twice, it must be idempotent.
+class IdempotentPointerToHandleCodeTrampoline {
+ public:
+  explicit IdempotentPointerToHandleCodeTrampoline(Isolate* isolate)
+      : isolate_(isolate) {}
+
+  template<typename R>
+  MUST_USE_RESULT MaybeObject* Call(R (*function)()) {
+    int collections = isolate_->heap()->gc_count();
+    (*function)();
+    return (collections == isolate_->heap()->gc_count())
+        ? isolate_->heap()->true_value()
+        : reinterpret_cast<MaybeObject*>(Failure::RetryAfterGC());
+  }
+
+  template<typename R>
+  MUST_USE_RESULT MaybeObject* CallWithReturnValue(R (*function)()) {
+    int collections = isolate_->heap()->gc_count();
+    Object* result = (*function)();
+    return (collections == isolate_->heap()->gc_count())
+        ? result
+        : reinterpret_cast<MaybeObject*>(Failure::RetryAfterGC());
+  }
+
+  template<typename R, typename P1>
+  MUST_USE_RESULT MaybeObject* Call(R (*function)(P1), P1 p1) {
+    int collections = isolate_->heap()->gc_count();
+    (*function)(p1);
+    return (collections == isolate_->heap()->gc_count())
+        ? isolate_->heap()->true_value()
+        : reinterpret_cast<MaybeObject*>(Failure::RetryAfterGC());
+  }
+
+  template<typename R, typename P1>
+  MUST_USE_RESULT MaybeObject* CallWithReturnValue(
+      R (*function)(P1),
+      P1 p1) {
+    int collections = isolate_->heap()->gc_count();
+    Object* result = (*function)(p1);
+    return (collections == isolate_->heap()->gc_count())
+        ? result
+        : reinterpret_cast<MaybeObject*>(Failure::RetryAfterGC());
+  }
+
+  template<typename R, typename P1, typename P2>
+  MUST_USE_RESULT MaybeObject* Call(
+      R (*function)(P1, P2),
+      P1 p1,
+      P2 p2) {
+    int collections = isolate_->heap()->gc_count();
+    (*function)(p1, p2);
+    return (collections == isolate_->heap()->gc_count())
+        ? isolate_->heap()->true_value()
+        : reinterpret_cast<MaybeObject*>(Failure::RetryAfterGC());
+  }
+
+  template<typename R, typename P1, typename P2>
+  MUST_USE_RESULT MaybeObject* CallWithReturnValue(
+      R (*function)(P1, P2),
+      P1 p1,
+      P2 p2) {
+    int collections = isolate_->heap()->gc_count();
+    Object* result = (*function)(p1, p2);
+    return (collections == isolate_->heap()->gc_count())
+        ? result
+        : reinterpret_cast<MaybeObject*>(Failure::RetryAfterGC());
+  }
+
+ private:
+  Isolate* isolate_;
+};
+
 
 } }  // namespace v8::internal
 
diff --git a/src/frames.cc b/src/frames.cc
index 0408aa9..b20a7ea 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -202,6 +202,7 @@
   }
 }
 
+
 bool StackTraceFrameIterator::IsValidFrame() {
     if (!frame()->function()->IsJSFunction()) return false;
     Object* script = JSFunction::cast(frame()->function())->shared()->script();
@@ -1568,6 +1569,7 @@
   ASSERT(i == kNumJSCallerSaved);
 }
 
+
 int JSCallerSavedCode(int n) {
   ASSERT(0 <= n && n < kNumJSCallerSaved);
   return caller_saved_code_data.reg_code[n];
@@ -1600,6 +1602,7 @@
   return NULL;
 }
 
+
 Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
   ZoneList<StackFrame*> list(10, zone);
   for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index c1350a1..82d4f7c 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -76,12 +76,15 @@
 void BreakableStatementChecker::VisitModuleLiteral(ModuleLiteral* module) {
 }
 
+
 void BreakableStatementChecker::VisitModuleVariable(ModuleVariable* module) {
 }
 
+
 void BreakableStatementChecker::VisitModulePath(ModulePath* module) {
 }
 
+
 void BreakableStatementChecker::VisitModuleUrl(ModuleUrl* module) {
 }
 
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index 825d1e7..74db807 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -2015,6 +2015,7 @@
   }
 }
 
+
 static void AddUnwindInfo(CodeDescription* desc) {
 #if V8_TARGET_ARCH_X64
   if (desc->tag() == GDBJITInterface::FUNCTION) {
diff --git a/src/global-handles.cc b/src/global-handles.cc
index b601e99..c69b9e2 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -799,6 +799,7 @@
   PrintF("  # total      = %d\n", total);
 }
 
+
 void GlobalHandles::Print() {
   PrintF("Global handles:\n");
   for (NodeIterator it(this); !it.done(); it.Advance()) {
diff --git a/src/handles.cc b/src/handles.cc
index 7d4b25f..fc45aaa 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -499,6 +499,7 @@
   return right + script->line_offset()->value();
 }
 
+
 // Convert code position into column number.
 int GetScriptColumnNumber(Handle<Script> script, int code_pos) {
   int line_number = GetScriptLineNumber(script, code_pos);
@@ -513,6 +514,7 @@
   return code_pos - (prev_line_end_pos + 1);
 }
 
+
 int GetScriptLineNumberSafe(Handle<Script> script, int code_pos) {
   DisallowHeapAllocation no_allocation;
   if (!script->line_ends()->IsUndefined()) {
diff --git a/src/handles.h b/src/handles.h
index 5976b75..140c34e 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -106,6 +106,13 @@
 }
 
 
+// Convenience wrapper.
+template<class T>
+inline Handle<T> handle(T* t) {
+  return Handle<T>(t, t->GetIsolate());
+}
+
+
 class DeferredHandles;
 class HandleScopeImplementer;
 
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index e517df4..e66af33 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -94,6 +94,7 @@
   return TakeSnapshot(snapshots_->names()->GetName(name), control, resolver);
 }
 
+
 void HeapProfiler::StartHeapObjectsTracking() {
   snapshots_->StartHeapObjectsTracking();
 }
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index f959aee..d65b814 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -459,6 +459,7 @@
   time_intervals_.Clear();
 }
 
+
 void HeapObjectsMap::UpdateHeapObjectsMap() {
   HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
                           "HeapSnapshotsCollection::UpdateHeapObjectsMap");
@@ -572,7 +573,6 @@
 
 HeapSnapshotsCollection::HeapSnapshotsCollection(Heap* heap)
     : is_tracking_objects_(false),
-      token_enumerator_(new TokenEnumerator()),
       ids_(heap) {
 }
 
@@ -583,7 +583,6 @@
 
 
 HeapSnapshotsCollection::~HeapSnapshotsCollection() {
-  delete token_enumerator_;
   snapshots_.Iterate(DeleteHeapSnapshot);
 }
 
@@ -1963,6 +1962,7 @@
   embedder_queried_ = true;
 }
 
+
 void NativeObjectsExplorer::FillImplicitReferences() {
   Isolate* isolate = Isolate::Current();
   List<ImplicitRefGroup*>* groups =
@@ -2588,6 +2588,7 @@
   w->AddCharacter(hex_chars[u & 0xf]);
 }
 
+
 void HeapSnapshotJSONSerializer::SerializeString(const unsigned char* s) {
   writer_->AddCharacter('\n');
   writer_->AddCharacter('\"');
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index cd1ec29..70881ef 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -306,7 +306,6 @@
   void RemoveSnapshot(HeapSnapshot* snapshot);
 
   StringsStorage* names() { return &names_; }
-  TokenEnumerator* token_enumerator() { return token_enumerator_; }
 
   SnapshotObjectId FindObjectId(Address object_addr) {
     return ids_.FindEntry(object_addr);
@@ -325,7 +324,6 @@
   bool is_tracking_objects_;  // Whether tracking object moves is needed.
   List<HeapSnapshot*> snapshots_;
   StringsStorage names_;
-  TokenEnumerator* token_enumerator_;
   // Mapping from HeapObject addresses to objects' uids.
   HeapObjectsMap ids_;
 
diff --git a/src/heap.cc b/src/heap.cc
index 9d1ac8c..90f8837 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2855,9 +2855,9 @@
 
 MaybeObject* Heap::AllocatePropertyCell(Object* value) {
   Object* result;
-  { MaybeObject* maybe_result = AllocateRawPropertyCell();
-    if (!maybe_result->ToObject(&result)) return maybe_result;
-  }
+  MaybeObject* maybe_result = AllocateRawPropertyCell();
+  if (!maybe_result->ToObject(&result)) return maybe_result;
+
   HeapObject::cast(result)->set_map_no_write_barrier(
       global_property_cell_map());
   PropertyCell* cell = PropertyCell::cast(result);
@@ -2865,6 +2865,8 @@
                            SKIP_WRITE_BARRIER);
   cell->set_value(value);
   cell->set_type(Type::None());
+  maybe_result = cell->SetValueInferType(value);
+  if (maybe_result->IsFailure()) return maybe_result;
   return result;
 }
 
@@ -3501,6 +3503,7 @@
   }
 }
 
+
 ExternalArray* Heap::EmptyExternalArrayForMap(Map* map) {
   return ExternalArray::cast(
       roots_[RootIndexForEmptyExternalArray(map->elements_kind())]);
@@ -5231,6 +5234,7 @@
   String::WriteToFlat(s, chars, 0, len);
 }
 
+
 static inline void WriteTwoByteData(String* s, uint16_t* chars, int len) {
   ASSERT(s->length() == len);
   String::WriteToFlat(s, chars, 0, len);
@@ -5415,6 +5419,7 @@
   return result;
 }
 
+
 MaybeObject* Heap::AllocateEmptyExternalArray(ExternalArrayType array_type) {
   return AllocateExternalArray(0, array_type, NULL, TENURED);
 }
@@ -6751,6 +6756,7 @@
   MarkCompactCollector::Initialize();
 }
 
+
 bool Heap::SetUp() {
 #ifdef DEBUG
   allocation_timeout_ = FLAG_gc_interval;
@@ -6861,6 +6867,7 @@
   return true;
 }
 
+
 bool Heap::CreateHeapObjects() {
   // Create initial maps.
   if (!CreateInitialMaps()) return false;
@@ -7026,6 +7033,7 @@
   }
 };
 
+
 void Heap::PrintHandles() {
   PrintF("Handles:\n");
   PrintHandleVisitor v;
diff --git a/src/heap.h b/src/heap.h
index d254b60..d6f41a8 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -261,6 +261,7 @@
   V(map_field_string, "%map")                                            \
   V(elements_field_string, "%elements")                                  \
   V(length_field_string, "%length")                                      \
+  V(cell_value_string, "%cell_value")                                    \
   V(function_class_string, "Function")                                   \
   V(properties_field_symbol, "%properties")                              \
   V(payload_field_symbol, "%payload")                                    \
@@ -1812,6 +1813,8 @@
   void QueueMemoryChunkForFree(MemoryChunk* chunk);
   void FreeQueuedChunks();
 
+  int gc_count() const { return gc_count_; }
+
   // Completely clear the Instanceof cache (to stop it keeping objects alive
   // around a GC).
   inline void CompletelyClearInstanceofCache();
diff --git a/src/hydrogen-dce.cc b/src/hydrogen-dce.cc
new file mode 100644
index 0000000..4ad32d2
--- /dev/null
+++ b/src/hydrogen-dce.cc
@@ -0,0 +1,125 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen-dce.h"
+#include "v8.h"
+
+namespace v8 {
+namespace internal {
+
+bool HDeadCodeEliminationPhase::MarkLive(HValue* ref, HValue* instr) {
+  if (instr->CheckFlag(HValue::kIsLive)) return false;
+  instr->SetFlag(HValue::kIsLive);
+
+  if (FLAG_trace_dead_code_elimination) {
+    HeapStringAllocator allocator;
+    StringStream stream(&allocator);
+    if (ref != NULL) {
+      ref->PrintTo(&stream);
+    } else {
+      stream.Add("root ");
+    }
+    stream.Add(" -> ");
+    instr->PrintTo(&stream);
+    PrintF("[MarkLive %s]\n", *stream.ToCString());
+  }
+
+  return true;
+}
+
+
+void HDeadCodeEliminationPhase::MarkLiveInstructions() {
+  ZoneList<HValue*> worklist(graph()->blocks()->length(), zone());
+
+  // Mark initial root instructions for dead code elimination.
+  for (int i = 0; i < graph()->blocks()->length(); ++i) {
+    HBasicBlock* block = graph()->blocks()->at(i);
+    for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+      HInstruction* instr = it.Current();
+      if (instr->CannotBeEliminated() && MarkLive(NULL, instr)) {
+        worklist.Add(instr, zone());
+      }
+    }
+    for (int j = 0; j < block->phis()->length(); j++) {
+      HPhi* phi = block->phis()->at(j);
+      if (phi->CannotBeEliminated() && MarkLive(NULL, phi)) {
+        worklist.Add(phi, zone());
+      }
+    }
+  }
+
+  // Transitively mark all inputs of live instructions live.
+  while (!worklist.is_empty()) {
+    HValue* instr = worklist.RemoveLast();
+    for (int i = 0; i < instr->OperandCount(); ++i) {
+      if (MarkLive(instr, instr->OperandAt(i))) {
+        worklist.Add(instr->OperandAt(i), zone());
+      }
+    }
+  }
+}
+
+
+void HDeadCodeEliminationPhase::RemoveDeadInstructions() {
+  ZoneList<HPhi*> worklist(graph()->blocks()->length(), zone());
+
+  // Remove any instruction not marked kIsLive.
+  for (int i = 0; i < graph()->blocks()->length(); ++i) {
+    HBasicBlock* block = graph()->blocks()->at(i);
+    for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+      HInstruction* instr = it.Current();
+      if (!instr->CheckFlag(HValue::kIsLive)) {
+        // Instruction has not been marked live; assume it is dead and remove.
+        // TODO(titzer): we don't remove constants because some special ones
+        // might be used by later phases and are assumed to be in the graph
+        if (!instr->IsConstant()) instr->DeleteAndReplaceWith(NULL);
+      } else {
+        // Clear the liveness flag to leave the graph clean for the next DCE.
+        instr->ClearFlag(HValue::kIsLive);
+      }
+    }
+    // Collect phis that are dead and remove them in the next pass.
+    for (int j = 0; j < block->phis()->length(); j++) {
+      HPhi* phi = block->phis()->at(j);
+      if (!phi->CheckFlag(HValue::kIsLive)) {
+        worklist.Add(phi, zone());
+      } else {
+        phi->ClearFlag(HValue::kIsLive);
+      }
+    }
+  }
+
+  // Process phis separately to avoid simultaneously mutating the phi list.
+  while (!worklist.is_empty()) {
+    HPhi* phi = worklist.RemoveLast();
+    HBasicBlock* block = phi->block();
+    phi->DeleteAndReplaceWith(NULL);
+    block->RecordDeletedPhi(phi->merged_index());
+  }
+}
+
+} }  // namespace v8::internal
diff --git a/src/hydrogen-dce.h b/src/hydrogen-dce.h
new file mode 100644
index 0000000..19749f2
--- /dev/null
+++ b/src/hydrogen-dce.h
@@ -0,0 +1,56 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_DCE_H_
+#define V8_HYDROGEN_DCE_H_
+
+#include "hydrogen.h"
+
+namespace v8 {
+namespace internal {
+
+
+class HDeadCodeEliminationPhase : public HPhase {
+ public:
+  explicit HDeadCodeEliminationPhase(HGraph* graph)
+      : HPhase("H_Dead code elimination", graph) { }
+
+  void Run() {
+    MarkLiveInstructions();
+    RemoveDeadInstructions();
+  }
+
+ private:
+  bool MarkLive(HValue* ref, HValue* instr);
+  void MarkLiveInstructions();
+  void RemoveDeadInstructions();
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HYDROGEN_DCE_H_
diff --git a/src/hydrogen-gvn.cc b/src/hydrogen-gvn.cc
index 7ea2f16..fd7430c 100644
--- a/src/hydrogen-gvn.cc
+++ b/src/hydrogen-gvn.cc
@@ -123,6 +123,7 @@
   va_end(arguments);
 }
 
+
 // Wrap TraceGVN in macros to avoid the expense of evaluating its arguments when
 // --trace-gvn is off.
 #define TRACE_GVN_1(msg, a1)                    \
@@ -339,6 +340,7 @@
   return *this;
 }
 
+
 void HSideEffectMap::Kill(GVNFlagSet flags) {
   for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
     GVNFlag changes_flag = HValue::ChangesFlagFromInt(i);
@@ -748,6 +750,7 @@
   int length_;
 };
 
+
 // This is a recursive traversal of the dominator tree but it has been turned
 // into a loop to avoid stack overflows.
 // The logical "stack frames" of the recursion are kept in a list of
diff --git a/src/hydrogen-infer-types.cc b/src/hydrogen-infer-types.cc
new file mode 100644
index 0000000..01c6084
--- /dev/null
+++ b/src/hydrogen-infer-types.cc
@@ -0,0 +1,77 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen-infer-types.h"
+
+namespace v8 {
+namespace internal {
+
+void HInferTypesPhase::InferTypes(int from_inclusive, int to_inclusive) {
+  for (int i = from_inclusive; i <= to_inclusive; ++i) {
+    HBasicBlock* block = graph()->blocks()->at(i);
+
+    const ZoneList<HPhi*>* phis = block->phis();
+    for (int j = 0; j < phis->length(); j++) {
+      phis->at(j)->UpdateInferredType();
+    }
+
+    for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+      it.Current()->UpdateInferredType();
+    }
+
+    if (block->IsLoopHeader()) {
+      HBasicBlock* last_back_edge =
+          block->loop_information()->GetLastBackEdge();
+      InferTypes(i + 1, last_back_edge->block_id());
+      // Skip all blocks already processed by the recursive call.
+      i = last_back_edge->block_id();
+      // Update phis of the loop header now after the whole loop body is
+      // guaranteed to be processed.
+      for (int j = 0; j < block->phis()->length(); ++j) {
+        HPhi* phi = block->phis()->at(j);
+        worklist_.Add(phi, zone());
+        in_worklist_.Add(phi->id());
+      }
+      while (!worklist_.is_empty()) {
+        HValue* current = worklist_.RemoveLast();
+        in_worklist_.Remove(current->id());
+        if (current->UpdateInferredType()) {
+          for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) {
+            HValue* use = it.value();
+            if (!in_worklist_.Contains(use->id())) {
+              in_worklist_.Add(use->id());
+              worklist_.Add(use, zone());
+            }
+          }
+        }
+      }
+      ASSERT(in_worklist_.IsEmpty());
+    }
+  }
+}
+
+} }  // namespace v8::internal
diff --git a/src/hydrogen-infer-types.h b/src/hydrogen-infer-types.h
new file mode 100644
index 0000000..cfcbf35
--- /dev/null
+++ b/src/hydrogen-infer-types.h
@@ -0,0 +1,59 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_INFER_TYPES_H_
+#define V8_HYDROGEN_INFER_TYPES_H_
+
+#include "hydrogen.h"
+
+namespace v8 {
+namespace internal {
+
+
+class HInferTypesPhase : public HPhase {
+ public:
+  explicit HInferTypesPhase(HGraph* graph)
+      : HPhase("H_Inferring types", graph), worklist_(8, zone()),
+        in_worklist_(graph->GetMaximumValueID(), zone()) { }
+
+  void Run() {
+    InferTypes(0, graph()->blocks()->length() - 1);
+  }
+
+ private:
+  void InferTypes(int from_inclusive, int to_inclusive);
+
+  ZoneList<HValue*> worklist_;
+  BitVector in_worklist_;
+
+  DISALLOW_COPY_AND_ASSIGN(HInferTypesPhase);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HYDROGEN_INFER_TYPES_H_
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 932fd47..041ef8b 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1701,6 +1701,7 @@
   return "";
 }
 
+
 void HCheckInstanceType::PrintDataTo(StringStream* stream) {
   stream->Add("%s ", GetCheckName());
   HUnaryOperation::PrintDataTo(stream);
@@ -2174,6 +2175,7 @@
     has_double_value_(false),
     is_internalized_string_(false),
     is_not_in_new_space_(true),
+    is_cell_(false),
     boolean_value_(handle->BooleanValue()) {
   if (handle_->IsHeapObject()) {
     Heap* heap = Handle<HeapObject>::cast(handle)->GetHeap();
@@ -2190,6 +2192,9 @@
     type_from_value_ = HType::TypeFromValue(handle_);
     is_internalized_string_ = handle_->IsInternalizedString();
   }
+
+  is_cell_ = !handle_.is_null() &&
+      (handle_->IsCell() || handle_->IsPropertyCell());
   Initialize(r);
 }
 
@@ -2200,6 +2205,7 @@
                      HType type,
                      bool is_internalize_string,
                      bool is_not_in_new_space,
+                     bool is_cell,
                      bool boolean_value)
     : handle_(handle),
       unique_id_(unique_id),
@@ -2208,6 +2214,7 @@
       has_double_value_(false),
       is_internalized_string_(is_internalize_string),
       is_not_in_new_space_(is_not_in_new_space),
+      is_cell_(is_cell),
       boolean_value_(boolean_value),
       type_from_value_(type) {
   ASSERT(!handle.is_null());
@@ -2227,6 +2234,7 @@
       has_double_value_(true),
       is_internalized_string_(false),
       is_not_in_new_space_(is_not_in_new_space),
+      is_cell_(false),
       boolean_value_(integer_value != 0),
       int32_value_(integer_value),
       double_value_(FastI2D(integer_value)) {
@@ -2245,6 +2253,7 @@
       has_double_value_(true),
       is_internalized_string_(false),
       is_not_in_new_space_(is_not_in_new_space),
+      is_cell_(false),
       boolean_value_(double_value != 0 && !std::isnan(double_value)),
       int32_value_(DoubleToInt32(double_value)),
       double_value_(double_value) {
@@ -2267,9 +2276,17 @@
   }
   set_representation(r);
   SetFlag(kUseGVN);
-  if (representation().IsInteger32()) {
-    ClearGVNFlag(kDependsOnOsrEntries);
+}
+
+
+bool HConstant::EmitAtUses() {
+  ASSERT(IsLinked());
+  if (block()->graph()->has_osr()) {
+    return block()->graph()->IsStandardConstant(this);
   }
+  if (IsCell()) return false;
+  if (representation().IsDouble()) return false;
+  return true;
 }
 
 
@@ -2290,6 +2307,7 @@
                              type_from_value_,
                              is_internalized_string_,
                              is_not_in_new_space_,
+                             is_cell_,
                              boolean_value_);
 }
 
@@ -2540,7 +2558,7 @@
 }
 
 
-void HCompareIDAndBranch::AddInformativeDefinitions() {
+void HCompareNumericAndBranch::AddInformativeDefinitions() {
   NumericRelation r = NumericRelation::FromToken(token());
   if (r.IsNone()) return;
 
@@ -2550,7 +2568,7 @@
 }
 
 
-void HCompareIDAndBranch::PrintDataTo(StringStream* stream) {
+void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add(Token::Name(token()));
   stream->Add(" ");
   left()->PrintNameTo(stream);
@@ -2573,7 +2591,7 @@
 }
 
 
-void HCompareIDAndBranch::InferRepresentation(
+void HCompareNumericAndBranch::InferRepresentation(
     HInferRepresentationPhase* h_infer) {
   Representation left_rep = left()->representation();
   Representation right_rep = right()->representation();
@@ -2595,9 +2613,9 @@
     // and !=) have special handling of undefined, e.g. undefined == undefined
     // is 'true'. Relational comparisons have a different semantic, first
     // calling ToPrimitive() on their arguments.  The standard Crankshaft
-    // tagged-to-double conversion to ensure the HCompareIDAndBranch's inputs
-    // are doubles caused 'undefined' to be converted to NaN. That's compatible
-    // out-of-the box with ordered relational comparisons (<, >, <=,
+    // tagged-to-double conversion to ensure the HCompareNumericAndBranch's
+    // inputs are doubles caused 'undefined' to be converted to NaN. That's
+    // compatible out-of-the box with ordered relational comparisons (<, >, <=,
     // >=). However, for equality comparisons (and for 'in' and 'instanceof'),
     // it is not consistent with the spec. For example, it would cause undefined
     // == undefined (should be true) to be evaluated as NaN == NaN
@@ -3078,6 +3096,11 @@
 }
 
 
+HType HCheckSmi::CalculateInferredType() {
+  return HType::Smi();
+}
+
+
 HType HPhi::CalculateInferredType() {
   HType result = HType::Uninitialized();
   for (int i = 0; i < OperandCount(); ++i) {
@@ -3824,6 +3847,13 @@
 }
 
 
+HObjectAccess HObjectAccess::ForCellPayload(Isolate* isolate) {
+  return HObjectAccess(
+      kInobject, Cell::kValueOffset,
+      Handle<String>(isolate->heap()->cell_value_string()));
+}
+
+
 void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) {
   // set the appropriate GVN flags for a given load or store instruction
   if (is_store) {
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 26bda87..4227b8e 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -92,10 +92,11 @@
   V(CheckHeapObject)                           \
   V(CheckInstanceType)                         \
   V(CheckMaps)                                 \
+  V(CheckSmi)                                  \
   V(CheckPrototypeMaps)                        \
   V(ClampToUint8)                              \
   V(ClassOfTestAndBranch)                      \
-  V(CompareIDAndBranch)                        \
+  V(CompareNumericAndBranch)                   \
   V(CompareGeneric)                            \
   V(CompareObjectEqAndBranch)                  \
   V(CompareMap)                                \
@@ -128,6 +129,7 @@
   V(InvokeFunction)                            \
   V(IsConstructCallAndBranch)                  \
   V(IsObjectAndBranch)                         \
+  V(IsNumberAndBranch)                         \
   V(IsStringAndBranch)                         \
   V(IsSmiAndBranch)                            \
   V(IsUndetectableAndBranch)                   \
@@ -1604,21 +1606,11 @@
 class HBranch: public HUnaryControlInstruction {
  public:
   HBranch(HValue* value,
-          HBasicBlock* true_target,
-          HBasicBlock* false_target,
-          ToBooleanStub::Types expected_input_types = ToBooleanStub::Types())
+          ToBooleanStub::Types expected_input_types = ToBooleanStub::Types(),
+          HBasicBlock* true_target = NULL,
+          HBasicBlock* false_target = NULL)
       : HUnaryControlInstruction(value, true_target, false_target),
         expected_input_types_(expected_input_types) {
-    ASSERT(true_target != NULL && false_target != NULL);
-    SetFlag(kAllowUndefinedAsNaN);
-  }
-  explicit HBranch(HValue* value)
-      : HUnaryControlInstruction(value, NULL, NULL) {
-    SetFlag(kAllowUndefinedAsNaN);
-  }
-  HBranch(HValue* value, ToBooleanStub::Types expected_input_types)
-      : HUnaryControlInstruction(value, NULL, NULL),
-        expected_input_types_(expected_input_types) {
     SetFlag(kAllowUndefinedAsNaN);
   }
 
@@ -1642,12 +1634,10 @@
  public:
   HCompareMap(HValue* value,
               Handle<Map> map,
-              HBasicBlock* true_target,
-              HBasicBlock* false_target)
+              HBasicBlock* true_target = NULL,
+              HBasicBlock* false_target = NULL)
       : HUnaryControlInstruction(value, true_target, false_target),
-        map_(map) {
-    ASSERT(true_target != NULL);
-    ASSERT(false_target != NULL);
+      map_(map) {
     ASSERT(!map.is_null());
   }
 
@@ -2934,6 +2924,49 @@
 };
 
 
+class HCheckSmi: public HUnaryOperation {
+ public:
+  explicit HCheckSmi(HValue* value) : HUnaryOperation(value) {
+    set_representation(Representation::Smi());
+    SetFlag(kUseGVN);
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) {
+    return Representation::Tagged();
+  }
+
+  virtual HType CalculateInferredType();
+
+  virtual HValue* Canonicalize() {
+    HType value_type = value()->type();
+    if (value_type.IsSmi()) {
+      return NULL;
+    }
+    return this;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckSmi)
+
+ protected:
+  virtual bool DataEquals(HValue* other) { return true; }
+};
+
+
+class HIsNumberAndBranch: public HUnaryControlInstruction {
+ public:
+  explicit HIsNumberAndBranch(HValue* value)
+    : HUnaryControlInstruction(value, NULL, NULL) {
+    SetFlag(kFlexibleRepresentation);
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) {
+    return Representation::None();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsNumberAndBranch)
+};
+
+
 class HCheckHeapObject: public HUnaryOperation {
  public:
   explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) {
@@ -3246,6 +3279,7 @@
             HType type,
             bool is_internalized_string,
             bool is_not_in_new_space,
+            bool is_cell,
             bool boolean_value);
 
   Handle<Object> handle() {
@@ -3294,6 +3328,10 @@
            unique_id_ == UniqueValueId(heap->empty_string());
   }
 
+  bool IsCell() const {
+    return is_cell_;
+  }
+
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
   }
@@ -3305,7 +3343,7 @@
     return Representation::Tagged();
   }
 
-  virtual bool EmitAtUses() { return !representation().IsDouble(); }
+  virtual bool EmitAtUses();
   virtual void PrintDataTo(StringStream* stream);
   virtual HType CalculateInferredType();
   bool IsInteger() { return handle()->IsSmi(); }
@@ -3420,6 +3458,7 @@
   bool has_double_value_ : 1;
   bool is_internalized_string_ : 1;  // TODO(yangguo): make this part of HType.
   bool is_not_in_new_space_ : 1;
+  bool is_cell_ : 1;
   bool boolean_value_ : 1;
   int32_t int32_value_;
   double double_value_;
@@ -3909,9 +3948,9 @@
 };
 
 
-class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> {
+class HCompareNumericAndBranch: public HTemplateControlInstruction<2, 2> {
  public:
-  HCompareIDAndBranch(HValue* left, HValue* right, Token::Value token)
+  HCompareNumericAndBranch(HValue* left, HValue* right, Token::Value token)
       : token_(token) {
     SetFlag(kFlexibleRepresentation);
     ASSERT(Token::IsCompareOp(token));
@@ -3941,7 +3980,7 @@
 
   virtual void AddInformativeDefinitions();
 
-  DECLARE_CONCRETE_INSTRUCTION(CompareIDAndBranch)
+  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
 
  private:
   Representation observed_input_representation_[2];
@@ -4718,6 +4757,7 @@
  public:
   explicit HOsrEntry(BailoutId ast_id) : ast_id_(ast_id) {
     SetGVNFlag(kChangesOsrEntries);
+    SetGVNFlag(kChangesNewSpacePromotion);
   }
 
   BailoutId ast_id() const { return ast_id_; }
@@ -5072,6 +5112,9 @@
         HInnerAllocatedObject::cast(object)->base_object(),
         new_space_dominator);
   }
+  if (object->IsConstant() && HConstant::cast(object)->IsCell()) {
+    return false;
+  }
   if (object != new_space_dominator) return true;
   if (object->IsAllocateObject()) return false;
   if (object->IsAllocate()) {
@@ -5333,6 +5376,9 @@
   static HObjectAccess ForField(Handle<Map> map,
       LookupResult *lookup, Handle<String> name = Handle<String>::null());
 
+  // Create an access for the payload of a Cell or JSGlobalPropertyCell.
+  static HObjectAccess ForCellPayload(Isolate* isolate);
+
   void PrintTo(StringStream* stream);
 
   inline bool Equals(HObjectAccess that) const {
diff --git a/src/hydrogen-osr.cc b/src/hydrogen-osr.cc
index 19a1c77..a2fa0bf 100644
--- a/src/hydrogen-osr.cc
+++ b/src/hydrogen-osr.cc
@@ -63,7 +63,8 @@
   HBasicBlock* non_osr_entry = graph->CreateBasicBlock();
   osr_entry_ = graph->CreateBasicBlock();
   HValue* true_value = graph->GetConstantTrue();
-  HBranch* test = new(zone) HBranch(true_value, non_osr_entry, osr_entry_);
+  HBranch* test = new(zone) HBranch(true_value, ToBooleanStub::Types(),
+                                    non_osr_entry, osr_entry_);
   builder_->current_block()->Finish(test);
 
   HBasicBlock* loop_predecessor = graph->CreateBasicBlock();
diff --git a/src/hydrogen-range-analysis.cc b/src/hydrogen-range-analysis.cc
index 0d4d970..ed254db 100644
--- a/src/hydrogen-range-analysis.cc
+++ b/src/hydrogen-range-analysis.cc
@@ -49,8 +49,9 @@
   // Infer range based on control flow.
   if (block->predecessors()->length() == 1) {
     HBasicBlock* pred = block->predecessors()->first();
-    if (pred->end()->IsCompareIDAndBranch()) {
-      InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block);
+    if (pred->end()->IsCompareNumericAndBranch()) {
+      InferControlFlowRange(HCompareNumericAndBranch::cast(pred->end()),
+                            block);
     }
   }
 
@@ -74,7 +75,7 @@
 }
 
 
-void HRangeAnalysisPhase::InferControlFlowRange(HCompareIDAndBranch* test,
+void HRangeAnalysisPhase::InferControlFlowRange(HCompareNumericAndBranch* test,
                                                 HBasicBlock* dest) {
   ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
   if (test->representation().IsSmiOrInteger32()) {
diff --git a/src/hydrogen-range-analysis.h b/src/hydrogen-range-analysis.h
index 52ce109..b699d3a 100644
--- a/src/hydrogen-range-analysis.h
+++ b/src/hydrogen-range-analysis.h
@@ -46,7 +46,8 @@
  private:
   void TraceRange(const char* msg, ...);
   void Analyze(HBasicBlock* block);
-  void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest);
+  void InferControlFlowRange(HCompareNumericAndBranch* test,
+                             HBasicBlock* dest);
   void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
   void InferRange(HValue* value);
   void RollBackTo(int index);
diff --git a/src/hydrogen-redundant-phi.cc b/src/hydrogen-redundant-phi.cc
new file mode 100644
index 0000000..9c38200
--- /dev/null
+++ b/src/hydrogen-redundant-phi.cc
@@ -0,0 +1,76 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen-redundant-phi.h"
+
+namespace v8 {
+namespace internal {
+
+void HRedundantPhiEliminationPhase::Run() {
+  // We do a simple fixed point iteration without any work list, because
+  // machine-generated JavaScript can lead to a very dense Hydrogen graph with
+  // an enormous work list and will consequently result in OOM. Experiments
+  // showed that this simple algorithm is good enough, and even e.g. tracking
+  // the set or range of blocks to consider is not a real improvement.
+  bool need_another_iteration;
+  const ZoneList<HBasicBlock*>* blocks(graph()->blocks());
+  ZoneList<HPhi*> redundant_phis(blocks->length(), zone());
+  do {
+    need_another_iteration = false;
+    for (int i = 0; i < blocks->length(); ++i) {
+      HBasicBlock* block = blocks->at(i);
+      for (int j = 0; j < block->phis()->length(); j++) {
+        HPhi* phi = block->phis()->at(j);
+        HValue* replacement = phi->GetRedundantReplacement();
+        if (replacement != NULL) {
+          // Remember phi to avoid concurrent modification of the block's phis.
+          redundant_phis.Add(phi, zone());
+          for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
+            HValue* value = it.value();
+            value->SetOperandAt(it.index(), replacement);
+            need_another_iteration |= value->IsPhi();
+          }
+        }
+      }
+      for (int i = 0; i < redundant_phis.length(); i++) {
+        block->RemovePhi(redundant_phis[i]);
+      }
+      redundant_phis.Clear();
+    }
+  } while (need_another_iteration);
+
+#if DEBUG
+  // Make sure that we *really* removed all redundant phis.
+  for (int i = 0; i < blocks->length(); ++i) {
+    for (int j = 0; j < blocks->at(i)->phis()->length(); j++) {
+      ASSERT(blocks->at(i)->phis()->at(j)->GetRedundantReplacement() == NULL);
+    }
+  }
+#endif
+}
+
+} }  // namespace v8::internal
diff --git a/src/hydrogen-redundant-phi.h b/src/hydrogen-redundant-phi.h
new file mode 100644
index 0000000..6291fa5
--- /dev/null
+++ b/src/hydrogen-redundant-phi.h
@@ -0,0 +1,53 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_REDUNDANT_PHI_H_
+#define V8_HYDROGEN_REDUNDANT_PHI_H_
+
+#include "hydrogen.h"
+
+namespace v8 {
+namespace internal {
+
+
+// Replace all phis consisting of a single non-loop operand plus any number of
+// loop operands by that single non-loop operand.
+class HRedundantPhiEliminationPhase : public HPhase {
+ public:
+  explicit HRedundantPhiEliminationPhase(HGraph* graph)
+      : HPhase("H_Redundant phi elimination", graph) { }
+
+  void Run();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HRedundantPhiEliminationPhase);
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HYDROGEN_REDUNDANT_PHI_H_
diff --git a/src/hydrogen-sce.cc b/src/hydrogen-sce.cc
new file mode 100644
index 0000000..a6995f6
--- /dev/null
+++ b/src/hydrogen-sce.cc
@@ -0,0 +1,62 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen-sce.h"
+#include "v8.h"
+
+namespace v8 {
+namespace internal {
+
+void HStackCheckEliminationPhase::Run() {
+  // For each loop block walk the dominator tree from the backwards branch to
+  // the loop header. If a call instruction is encountered the backwards branch
+  // is dominated by a call and the stack check in the backwards branch can be
+  // removed.
+  for (int i = 0; i < graph()->blocks()->length(); i++) {
+    HBasicBlock* block = graph()->blocks()->at(i);
+    if (block->IsLoopHeader()) {
+      HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
+      HBasicBlock* dominator = back_edge;
+      while (true) {
+        for (HInstructionIterator it(dominator); !it.Done(); it.Advance()) {
+          if (it.Current()->IsCall()) {
+            block->loop_information()->stack_check()->Eliminate();
+            break;
+          }
+        }
+
+        // Done when the loop header is processed.
+        if (dominator == block) break;
+
+        // Move up the dominator tree.
+        dominator = dominator->dominator();
+      }
+    }
+  }
+}
+
+} }  // namespace v8::internal
diff --git a/src/hydrogen-sce.h b/src/hydrogen-sce.h
new file mode 100644
index 0000000..55e153e
--- /dev/null
+++ b/src/hydrogen-sce.h
@@ -0,0 +1,48 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_SCE_H_
+#define V8_HYDROGEN_SCE_H_
+
+#include "hydrogen.h"
+
+namespace v8 {
+namespace internal {
+
+
+class HStackCheckEliminationPhase : public HPhase {
+ public:
+  explicit HStackCheckEliminationPhase(HGraph* graph)
+      : HPhase("H_Stack check elimination", graph) { }
+
+  void Run();
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HYDROGEN_SCE_H_
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 7679f93..3a785ac 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1,4 +1,4 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
+// Copyright 2013 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -33,12 +33,16 @@
 #include "codegen.h"
 #include "full-codegen.h"
 #include "hashmap.h"
+#include "hydrogen-dce.h"
 #include "hydrogen-environment-liveness.h"
 #include "hydrogen-escape-analysis.h"
 #include "hydrogen-infer-representation.h"
+#include "hydrogen-infer-types.h"
 #include "hydrogen-gvn.h"
 #include "hydrogen-osr.h"
 #include "hydrogen-range-analysis.h"
+#include "hydrogen-redundant-phi.h"
+#include "hydrogen-sce.h"
 #include "hydrogen-uint32-analysis.h"
 #include "lithium-allocator.h"
 #include "parser.h"
@@ -649,6 +653,7 @@
         htype,                                                                 \
         false,                                                                 \
         true,                                                                  \
+        false,                                                                 \
         boolean_value);                                                        \
     constant->InsertAfter(GetConstantUndefined());                             \
     constant_##name##_.set(constant);                                          \
@@ -671,6 +676,19 @@
 }
 
 
+bool HGraph::IsStandardConstant(HConstant* constant) {
+  if (constant == GetConstantUndefined()) return true;
+  if (constant == GetConstant0()) return true;
+  if (constant == GetConstant1()) return true;
+  if (constant == GetConstantMinus1()) return true;
+  if (constant == GetConstantTrue()) return true;
+  if (constant == GetConstantFalse()) return true;
+  if (constant == GetConstantHole()) return true;
+  if (constant == GetConstantNull()) return true;
+  return false;
+}
+
+
 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position)
     : builder_(builder),
       position_(position),
@@ -711,26 +729,6 @@
 }
 
 
-HInstruction* HGraphBuilder::IfBuilder::IfCompare(
-    HValue* left,
-    HValue* right,
-    Token::Value token) {
-  HCompareIDAndBranch* compare =
-      new(zone()) HCompareIDAndBranch(left, right, token);
-  AddCompare(compare);
-  return compare;
-}
-
-
-HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left,
-                                                     Handle<Map> map) {
-  HCompareMap* compare =
-      new(zone()) HCompareMap(left, map, first_true_block_, first_false_block_);
-  AddCompare(compare);
-  return compare;
-}
-
-
 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) {
   if (split_edge_merge_block_ != NULL) {
     HEnvironment* env = first_false_block_->last_environment();
@@ -811,8 +809,8 @@
     ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
     boolean_type.Add(ToBooleanStub::BOOLEAN);
     HBranch* branch =
-        new(zone()) HBranch(constant_false, first_true_block_,
-                            first_false_block_, boolean_type);
+        new(zone()) HBranch(constant_false, boolean_type, first_true_block_,
+                            first_false_block_);
     builder_->current_block()->Finish(branch);
   }
   builder_->set_current_block(first_true_block_);
@@ -916,8 +914,8 @@
   body_env->Pop();
 
   builder_->set_current_block(header_block_);
-  HCompareIDAndBranch* compare =
-      new(zone()) HCompareIDAndBranch(phi_, terminating, token);
+  HCompareNumericAndBranch* compare =
+      new(zone()) HCompareNumericAndBranch(phi_, terminating, token);
   compare->SetSuccessorAt(0, body_block_);
   compare->SetSuccessorAt(1, exit_block_);
   builder_->current_block()->Finish(compare);
@@ -1005,6 +1003,17 @@
 }
 
 
+void HGraphBuilder::AddSoftDeoptimize(SoftDeoptimizeMode mode) {
+  isolate()->counters()->soft_deopts_requested()->Increment();
+  if (FLAG_always_opt && mode == CAN_OMIT_SOFT_DEOPT) return;
+  if (current_block()->IsDeoptimizing()) return;
+  Add<HSoftDeoptimize>();
+  isolate()->counters()->soft_deopts_inserted()->Increment();
+  current_block()->MarkAsDeoptimizing();
+  graph()->set_has_soft_deoptimize(true);
+}
+
+
 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
   HBasicBlock* b = graph()->CreateBasicBlock();
   b->SetInitialEnvironment(env);
@@ -1131,14 +1140,15 @@
   Zone* zone = this->zone();
   IfBuilder length_checker(this);
 
-  length_checker.IfCompare(length, key, Token::EQ);
+  length_checker.If<HCompareNumericAndBranch>(length, key, Token::EQ);
   length_checker.Then();
 
   HValue* current_capacity = AddLoadFixedArrayLength(elements);
 
   IfBuilder capacity_checker(this);
 
-  capacity_checker.IfCompare(length, current_capacity, Token::EQ);
+  capacity_checker.If<HCompareNumericAndBranch>(length, current_capacity,
+                                                Token::EQ);
   capacity_checker.Then();
 
   HValue* context = environment()->LookupContext();
@@ -1182,12 +1192,11 @@
                                                 HValue* elements,
                                                 ElementsKind kind,
                                                 HValue* length) {
-  Heap* heap = isolate()->heap();
+  Factory* factory = isolate()->factory();
 
   IfBuilder cow_checker(this);
 
-  cow_checker.IfCompareMap(elements,
-                           Handle<Map>(heap->fixed_cow_array_map()));
+  cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
   cow_checker.Then();
 
   HValue* capacity = AddLoadFixedArrayLength(elements);
@@ -1256,10 +1265,10 @@
       HLoadExternalArrayPointer* external_elements =
           Add<HLoadExternalArrayPointer>(elements);
       IfBuilder length_checker(this);
-      length_checker.IfCompare(key, length, Token::LT);
+      length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
       length_checker.Then();
       IfBuilder negative_checker(this);
-      HValue* bounds_check = negative_checker.IfCompare(
+      HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
           key, graph()->GetConstant0(), Token::GTE);
       negative_checker.Then();
       HInstruction* result = BuildExternalArrayElementAccess(
@@ -1654,6 +1663,39 @@
 }
 
 
+HInstruction* HGraphBuilder::BuildUnaryMathOp(
+    HValue* input, Handle<Type> type, Token::Value operation) {
+  // We only handle the numeric cases here
+  type = handle(
+      Type::Intersect(type, handle(Type::Number(), isolate())), isolate());
+
+  switch (operation) {
+    default:
+      UNREACHABLE();
+    case Token::SUB: {
+        HInstruction* instr =
+            HMul::New(zone(), environment()->LookupContext(),
+                      input, graph()->GetConstantMinus1());
+        Representation rep = Representation::FromType(type);
+        if (type->Is(Type::None())) {
+          AddSoftDeoptimize();
+        }
+        if (instr->IsBinaryOperation()) {
+          HBinaryOperation* binop = HBinaryOperation::cast(instr);
+          binop->set_observed_input_representation(1, rep);
+          binop->set_observed_input_representation(2, rep);
+        }
+        return instr;
+      }
+    case Token::BIT_NOT:
+      if (type->Is(Type::None())) {
+        AddSoftDeoptimize();
+      }
+      return new(zone()) HBitNot(input);
+  }
+}
+
+
 void HGraphBuilder::BuildCompareNil(
     HValue* value,
     Handle<Type> type,
@@ -1909,6 +1951,18 @@
 }
 
 
+HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin,
+                                        HContext* context) {
+  HGlobalObject* global_object = Add<HGlobalObject>(context);
+  HObjectAccess access = HObjectAccess::ForJSObjectOffset(
+      GlobalObject::kBuiltinsOffset);
+  HValue* builtins = AddLoad(global_object, access);
+  HObjectAccess function_access = HObjectAccess::ForJSObjectOffset(
+      JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
+  return AddLoad(builtins, function_access);
+}
+
+
 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
     : HGraphBuilder(info),
       function_state_(NULL),
@@ -2055,6 +2109,7 @@
   }
 }
 
+
 // Block ordering was implemented with two mutually recursive methods,
 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
 // The recursion could lead to stack overflow so the algorithm has been
@@ -2470,53 +2525,6 @@
 }
 
 
-// Replace all phis consisting of a single non-loop operand plus any number of
-// loop operands by that single non-loop operand.
-void HGraph::EliminateRedundantPhis() {
-  HPhase phase("H_Redundant phi elimination", this);
-
-  // We do a simple fixed point iteration without any work list, because
-  // machine-generated JavaScript can lead to a very dense Hydrogen graph with
-  // an enormous work list and will consequently result in OOM. Experiments
-  // showed that this simple algorithm is good enough, and even e.g. tracking
-  // the set or range of blocks to consider is not a real improvement.
-  bool need_another_iteration;
-  ZoneList<HPhi*> redundant_phis(blocks_.length(), zone());
-  do {
-    need_another_iteration = false;
-    for (int i = 0; i < blocks_.length(); ++i) {
-      HBasicBlock* block = blocks_[i];
-      for (int j = 0; j < block->phis()->length(); j++) {
-        HPhi* phi = block->phis()->at(j);
-        HValue* replacement = phi->GetRedundantReplacement();
-        if (replacement != NULL) {
-          // Remember phi to avoid concurrent modification of the block's phis.
-          redundant_phis.Add(phi, zone());
-          for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
-            HValue* value = it.value();
-            value->SetOperandAt(it.index(), replacement);
-            need_another_iteration |= value->IsPhi();
-          }
-        }
-      }
-      for (int i = 0; i < redundant_phis.length(); i++) {
-        block->RemovePhi(redundant_phis[i]);
-      }
-      redundant_phis.Clear();
-    }
-  } while (need_another_iteration);
-
-#if DEBUG
-  // Make sure that we *really* removed all redundant phis.
-  for (int i = 0; i < blocks_.length(); ++i) {
-    for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
-      ASSERT(blocks_[i]->phis()->at(j)->GetRedundantReplacement() == NULL);
-    }
-  }
-#endif
-}
-
-
 bool HGraph::CheckArgumentsPhiUses() {
   int block_count = blocks_.length();
   for (int i = 0; i < block_count; ++i) {
@@ -2557,70 +2565,6 @@
 }
 
 
-void HGraph::InferTypes(ZoneList<HValue*>* worklist) {
-  BitVector in_worklist(GetMaximumValueID(), zone());
-  for (int i = 0; i < worklist->length(); ++i) {
-    ASSERT(!in_worklist.Contains(worklist->at(i)->id()));
-    in_worklist.Add(worklist->at(i)->id());
-  }
-
-  while (!worklist->is_empty()) {
-    HValue* current = worklist->RemoveLast();
-    in_worklist.Remove(current->id());
-    if (current->UpdateInferredType()) {
-      for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) {
-        HValue* use = it.value();
-        if (!in_worklist.Contains(use->id())) {
-          in_worklist.Add(use->id());
-          worklist->Add(use, zone());
-        }
-      }
-    }
-  }
-}
-
-
-class HStackCheckEliminator BASE_EMBEDDED {
- public:
-  explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
-
-  void Process();
-
- private:
-  HGraph* graph_;
-};
-
-
-void HStackCheckEliminator::Process() {
-  HPhase phase("H_Stack check elimination", graph_);
-  // For each loop block walk the dominator tree from the backwards branch to
-  // the loop header. If a call instruction is encountered the backwards branch
-  // is dominated by a call and the stack check in the backwards branch can be
-  // removed.
-  for (int i = 0; i < graph_->blocks()->length(); i++) {
-    HBasicBlock* block = graph_->blocks()->at(i);
-    if (block->IsLoopHeader()) {
-      HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
-      HBasicBlock* dominator = back_edge;
-      while (true) {
-        for (HInstructionIterator it(dominator); !it.Done(); it.Advance()) {
-          if (it.Current()->IsCall()) {
-            block->loop_information()->stack_check()->Eliminate();
-            break;
-          }
-        }
-
-        // Done when the loop header is processed.
-        if (dominator == block) break;
-
-        // Move up the dominator tree.
-        dominator = dominator->dominator();
-      }
-    }
-  }
-}
-
-
 void HGraph::MergeRemovableSimulates() {
   HPhase phase("H_Merge removable simulates", this);
   ZoneList<HSimulate*> mergelist(2, zone());
@@ -2684,43 +2628,6 @@
 }
 
 
-void HGraph::InitializeInferredTypes() {
-  HPhase phase("H_Inferring types", this);
-  InitializeInferredTypes(0, this->blocks_.length() - 1);
-}
-
-
-void HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) {
-  for (int i = from_inclusive; i <= to_inclusive; ++i) {
-    HBasicBlock* block = blocks_[i];
-
-    const ZoneList<HPhi*>* phis = block->phis();
-    for (int j = 0; j < phis->length(); j++) {
-      phis->at(j)->UpdateInferredType();
-    }
-
-    for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
-      it.Current()->UpdateInferredType();
-    }
-
-    if (block->IsLoopHeader()) {
-      HBasicBlock* last_back_edge =
-          block->loop_information()->GetLastBackEdge();
-      InitializeInferredTypes(i + 1, last_back_edge->block_id());
-      // Skip all blocks already processed by the recursive call.
-      i = last_back_edge->block_id();
-      // Update phis of the loop header now after the whole loop body is
-      // guaranteed to be processed.
-      ZoneList<HValue*> worklist(block->phis()->length(), zone());
-      for (int j = 0; j < block->phis()->length(); ++j) {
-        worklist.Add(block->phis()->at(j), zone());
-      }
-      InferTypes(&worklist);
-    }
-  }
-}
-
-
 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
   HValue* current = value;
   while (current != NULL) {
@@ -2909,12 +2816,11 @@
 
 void HGraph::MarkDeoptimizeOnUndefined() {
   HPhase phase("H_MarkDeoptimizeOnUndefined", this);
-  // Compute DeoptimizeOnUndefined flag for phis.
-  // Any phi that can reach a use with DeoptimizeOnUndefined set must
-  // have DeoptimizeOnUndefined set.  Currently only HCompareIDAndBranch, with
-  // double input representation, has this flag set.
-  // The flag is used by HChange tagged->double, which must deoptimize
-  // if one of its uses has this flag set.
+  // Compute DeoptimizeOnUndefined flag for phis.  Any phi that can reach a use
+  // with DeoptimizeOnUndefined set must have DeoptimizeOnUndefined set.
+  // Currently only HCompareNumericAndBranch, with double input representation,
+  // has this flag set.  The flag is used by HChange tagged->double, which must
+  // deoptimize if one of its uses has this flag set.
   for (int i = 0; i < phi_list()->length(); i++) {
     HPhi* phi = phi_list()->at(i);
     for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
@@ -3215,7 +3121,7 @@
   HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
   HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
   ToBooleanStub::Types expected(condition()->to_boolean_types());
-  HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected);
+  HBranch* test = new(zone()) HBranch(value, expected, empty_true, empty_false);
   builder->current_block()->Finish(test);
 
   empty_true->Goto(if_true(), builder->function_state());
@@ -3406,7 +3312,7 @@
         "Unsupported phi use of const variable"));
     return false;
   }
-  EliminateRedundantPhis();
+  Run<HRedundantPhiEliminationPhase>();
   if (!CheckArgumentsPhiUses()) {
     *bailout_reason = SmartArrayPointer<char>(StrDup(
         "Unsupported phi use of arguments"));
@@ -3414,9 +3320,7 @@
   }
 
   // Remove dead code and phis
-  if (FLAG_dead_code_elimination) {
-    DeadCodeElimination("H_Eliminate early dead code");
-  }
+  if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   CollectPhis();
 
   if (has_osr()) osr()->FinishOsrValues();
@@ -3431,7 +3335,7 @@
   MarkDeoptimizeOnUndefined();
   InsertRepresentationChanges();
 
-  InitializeInferredTypes();
+  Run<HInferTypesPhase>();
 
   // Must be performed before canonicalization to ensure that Canonicalize
   // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
@@ -3449,17 +3353,14 @@
   ComputeMinusZeroChecks();
 
   // Eliminate redundant stack checks on backwards branches.
-  HStackCheckEliminator sce(this);
-  sce.Process();
+  Run<HStackCheckEliminationPhase>();
 
   if (FLAG_idefs) SetupInformativeDefinitions();
   if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) {
     EliminateRedundantBoundsChecks();
   }
   if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations();
-  if (FLAG_dead_code_elimination) {
-    DeadCodeElimination("H_Eliminate late dead code");
-  }
+  if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
 
   RestoreActualValues();
 
@@ -3940,99 +3841,6 @@
 }
 
 
-void HGraph::DeadCodeElimination(const char* phase_name) {
-  HPhase phase(phase_name, this);
-  MarkLiveInstructions();
-  RemoveDeadInstructions();
-}
-
-
-void HGraph::MarkLiveInstructions() {
-  ZoneList<HValue*> worklist(blocks_.length(), zone());
-
-  // Mark initial root instructions for dead code elimination.
-  for (int i = 0; i < blocks()->length(); ++i) {
-    HBasicBlock* block = blocks()->at(i);
-    for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
-      HInstruction* instr = it.Current();
-      if (instr->CannotBeEliminated()) MarkLive(NULL, instr, &worklist);
-    }
-    for (int j = 0; j < block->phis()->length(); j++) {
-      HPhi* phi = block->phis()->at(j);
-      if (phi->CannotBeEliminated()) MarkLive(NULL, phi, &worklist);
-    }
-  }
-
-  // Transitively mark all inputs of live instructions live.
-  while (!worklist.is_empty()) {
-    HValue* instr = worklist.RemoveLast();
-    for (int i = 0; i < instr->OperandCount(); ++i) {
-      MarkLive(instr, instr->OperandAt(i), &worklist);
-    }
-  }
-}
-
-
-void HGraph::MarkLive(HValue* ref, HValue* instr, ZoneList<HValue*>* worklist) {
-  if (!instr->CheckFlag(HValue::kIsLive)) {
-    instr->SetFlag(HValue::kIsLive);
-    worklist->Add(instr, zone());
-
-    if (FLAG_trace_dead_code_elimination) {
-      HeapStringAllocator allocator;
-      StringStream stream(&allocator);
-      if (ref != NULL) {
-        ref->PrintTo(&stream);
-      } else {
-        stream.Add("root ");
-      }
-      stream.Add(" -> ");
-      instr->PrintTo(&stream);
-      PrintF("[MarkLive %s]\n", *stream.ToCString());
-    }
-  }
-}
-
-
-void HGraph::RemoveDeadInstructions() {
-  ZoneList<HPhi*> dead_phis(blocks_.length(), zone());
-
-  // Remove any instruction not marked kIsLive.
-  for (int i = 0; i < blocks()->length(); ++i) {
-    HBasicBlock* block = blocks()->at(i);
-    for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
-      HInstruction* instr = it.Current();
-      if (!instr->CheckFlag(HValue::kIsLive)) {
-        // Instruction has not been marked live; assume it is dead and remove.
-        // TODO(titzer): we don't remove constants because some special ones
-        // might be used by later phases and are assumed to be in the graph
-        if (!instr->IsConstant()) instr->DeleteAndReplaceWith(NULL);
-      } else {
-        // Clear the liveness flag to leave the graph clean for the next DCE.
-        instr->ClearFlag(HValue::kIsLive);
-      }
-    }
-    // Collect phis that are dead and remove them in the next pass.
-    for (int j = 0; j < block->phis()->length(); j++) {
-      HPhi* phi = block->phis()->at(j);
-      if (!phi->CheckFlag(HValue::kIsLive)) {
-        dead_phis.Add(phi, zone());
-      } else {
-        phi->ClearFlag(HValue::kIsLive);
-      }
-    }
-  }
-
-  // Process phis separately to avoid simultaneously mutating the phi list.
-  while (!dead_phis.is_empty()) {
-    HPhi* phi = dead_phis.RemoveLast();
-    HBasicBlock* block = phi->block();
-    phi->DeleteAndReplaceWith(NULL);
-    block->RecordDeletedPhi(phi->merged_index());
-  }
-}
-
-
 void HGraph::RestoreActualValues() {
   HPhase phase("H_Restore actual values", this);
 
@@ -4067,17 +3875,6 @@
 }
 
 
-void HOptimizedGraphBuilder::AddSoftDeoptimize() {
-  isolate()->counters()->soft_deopts_requested()->Increment();
-  if (FLAG_always_opt) return;
-  if (current_block()->IsDeoptimizing()) return;
-  Add<HSoftDeoptimize>();
-  isolate()->counters()->soft_deopts_inserted()->Increment();
-  current_block()->MarkAsDeoptimizing();
-  graph()->set_has_soft_deoptimize(true);
-}
-
-
 template <class Instruction>
 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
   int count = call->argument_count();
@@ -4428,10 +4225,10 @@
         AddSoftDeoptimize();
       }
 
-      HCompareIDAndBranch* compare_ =
-          new(zone()) HCompareIDAndBranch(tag_value,
-                                          label_value,
-                                          Token::EQ_STRICT);
+      HCompareNumericAndBranch* compare_ =
+          new(zone()) HCompareNumericAndBranch(tag_value,
+                                               label_value,
+                                               Token::EQ_STRICT);
       compare_->set_observed_input_representation(
           Representation::Smi(), Representation::Smi());
       compare = compare_;
@@ -4715,8 +4512,8 @@
   HValue* limit = environment()->ExpressionStackAt(1);
 
   // Check that we still have more keys.
-  HCompareIDAndBranch* compare_index =
-      new(zone()) HCompareIDAndBranch(index, limit, Token::LT);
+  HCompareNumericAndBranch* compare_index =
+      new(zone()) HCompareNumericAndBranch(index, limit, Token::LT);
   compare_index->set_observed_input_representation(
       Representation::Smi(), Representation::Smi());
 
@@ -4952,9 +4749,20 @@
       if (type == kUseCell) {
         Handle<GlobalObject> global(current_info()->global_object());
         Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
-        HLoadGlobalCell* instr =
-            new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
-        return ast_context()->ReturnInstruction(instr, expr->id());
+        if (cell->type()->IsConstant()) {
+          cell->AddDependentCompilationInfo(top_info());
+          Handle<Object> constant_object = cell->type()->AsConstant();
+          if (constant_object->IsConsString()) {
+            constant_object =
+                FlattenGetString(Handle<String>::cast(constant_object));
+          }
+          HConstant* constant = new(zone()) HConstant(constant_object);
+          return ast_context()->ReturnInstruction(constant, expr->id());
+        } else {
+          HLoadGlobalCell* instr =
+              new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
+          return ast_context()->ReturnInstruction(instr, expr->id());
+        }
       } else {
         HValue* context = environment()->LookupContext();
         HGlobalObject* global_object = new(zone()) HGlobalObject(context);
@@ -5764,7 +5572,7 @@
       HBasicBlock* if_true = graph()->CreateBasicBlock();
       HBasicBlock* if_false = graph()->CreateBasicBlock();
       HCompareMap* compare =
-          new(zone()) HCompareMap(object, map, if_true, if_false);
+          new(zone()) HCompareMap(object, map,  if_true, if_false);
       current_block()->Finish(compare);
 
       set_current_block(if_true);
@@ -5865,8 +5673,21 @@
   if (type == kUseCell) {
     Handle<GlobalObject> global(current_info()->global_object());
     Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
-    HInstruction* instr = Add<HStoreGlobalCell>(value, cell,
-                                                lookup.GetPropertyDetails());
+    if (cell->type()->IsConstant()) {
+      IfBuilder builder(this);
+      HValue* constant = Add<HConstant>(cell->type()->AsConstant());
+      if (cell->type()->AsConstant()->IsNumber()) {
+        builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ);
+      } else {
+        builder.If<HCompareObjectEqAndBranch>(value, constant);
+      }
+      builder.Then();
+      builder.Else();
+      AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT);
+      builder.End();
+    }
+    HInstruction* instr =
+        Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
     instr->set_position(position);
     if (instr->HasObservableSideEffects()) {
       AddSimulate(ast_id, REMOVABLE_SIMULATE);
@@ -8292,18 +8113,8 @@
 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
   CHECK_ALIVE(VisitForValue(expr->expression()));
   HValue* value = Pop();
-  HValue* context = environment()->LookupContext();
-  HInstruction* instr =
-      HMul::New(zone(), context, value, graph()->GetConstantMinus1());
   Handle<Type> operand_type = expr->expression()->lower_type();
-  Representation rep = ToRepresentation(operand_type);
-  if (operand_type->Is(Type::None())) {
-    AddSoftDeoptimize();
-  }
-  if (instr->IsBinaryOperation()) {
-    HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep);
-    HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep);
-  }
+  HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB);
   return ast_context()->ReturnInstruction(instr, expr->id());
 }
 
@@ -8312,10 +8123,7 @@
   CHECK_ALIVE(VisitForValue(expr->expression()));
   HValue* value = Pop();
   Handle<Type> operand_type = expr->expression()->lower_type();
-  if (operand_type->Is(Type::None())) {
-    AddSoftDeoptimize();
-  }
-  HInstruction* instr = new(zone()) HBitNot(value);
+  HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT);
   return ast_context()->ReturnInstruction(instr, expr->id());
 }
 
@@ -8369,7 +8177,7 @@
     CountOperation* expr) {
   // The input to the count operation is on top of the expression stack.
   TypeInfo info = expr->type();
-  Representation rep = ToRepresentation(info);
+  Representation rep = Representation::FromType(info);
   if (rep.IsNone() || rep.IsTagged()) {
     rep = Representation::Smi();
   }
@@ -8610,6 +8418,7 @@
   return new(zone()) HStringCharCodeAt(context, string, checked_index);
 }
 
+
 // Checks if the given shift amounts have form: (sa) and (32 - sa).
 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
                                              HValue* const32_minus_sa) {
@@ -8675,11 +8484,12 @@
   HValue* context = environment()->LookupContext();
   Handle<Type> left_type = expr->left()->lower_type();
   Handle<Type> right_type = expr->right()->lower_type();
-  Handle<Type> result_type = expr->result_type();
+  Handle<Type> result_type = expr->lower_type();
   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
-  Representation left_rep = ToRepresentation(left_type);
-  Representation right_rep = ToRepresentation(right_type);
-  Representation result_rep = ToRepresentation(result_type);
+  Representation left_rep = Representation::FromType(left_type);
+  Representation right_rep = Representation::FromType(right_type);
+  Representation result_rep = Representation::FromType(result_type);
+
   if (left_type->Is(Type::None())) {
     AddSoftDeoptimize();
     // TODO(rossberg): we should be able to get rid of non-continuous defaults.
@@ -8840,8 +8650,8 @@
     HBasicBlock* eval_right = graph()->CreateBasicBlock();
     ToBooleanStub::Types expected(expr->left()->to_boolean_types());
     HBranch* test = is_logical_and
-      ? new(zone()) HBranch(left_value, eval_right, empty_block, expected)
-      : new(zone()) HBranch(left_value, empty_block, eval_right, expected);
+        ? new(zone()) HBranch(left_value, expected, eval_right, empty_block)
+        : new(zone()) HBranch(left_value, expected, empty_block, eval_right);
     current_block()->Finish(test);
 
     set_current_block(eval_right);
@@ -8907,26 +8717,6 @@
 }
 
 
-// TODO(rossberg): this should die eventually.
-Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) {
-  if (info.IsUninitialized()) return Representation::None();
-  // TODO(verwaest): Return Smi rather than Integer32.
-  if (info.IsSmi()) return Representation::Integer32();
-  if (info.IsInteger32()) return Representation::Integer32();
-  if (info.IsDouble()) return Representation::Double();
-  if (info.IsNumber()) return Representation::Double();
-  return Representation::Tagged();
-}
-
-
-Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) {
-  if (type->Is(Type::None())) return Representation::None();
-  if (type->Is(Type::Signed32())) return Representation::Integer32();
-  if (type->Is(Type::Number())) return Representation::Double();
-  return Representation::Tagged();
-}
-
-
 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
                                                         HTypeof* typeof_expr,
                                                         Handle<String> check) {
@@ -9019,9 +8809,9 @@
   Handle<Type> left_type = expr->left()->lower_type();
   Handle<Type> right_type = expr->right()->lower_type();
   Handle<Type> combined_type = expr->combined_type();
-  Representation combined_rep = ToRepresentation(combined_type);
-  Representation left_rep = ToRepresentation(left_type);
-  Representation right_rep = ToRepresentation(right_type);
+  Representation combined_rep = Representation::FromType(combined_type);
+  Representation left_rep = Representation::FromType(left_type);
+  Representation right_rep = Representation::FromType(right_type);
 
   CHECK_ALIVE(VisitForValue(expr->left()));
   CHECK_ALIVE(VisitForValue(expr->right()));
@@ -9150,12 +8940,12 @@
       result->set_position(expr->position());
       return ast_context()->ReturnInstruction(result, expr->id());
     } else {
-      // TODO(verwaest): Remove once ToRepresentation properly returns Smi when
-      // the IC measures Smi.
+      // TODO(verwaest): Remove once Representation::FromType properly
+      // returns Smi when the IC measures Smi.
       if (left_type->Is(Type::Smi())) left_rep = Representation::Smi();
       if (right_type->Is(Type::Smi())) right_rep = Representation::Smi();
-      HCompareIDAndBranch* result =
-          new(zone()) HCompareIDAndBranch(left, right, op);
+      HCompareNumericAndBranch* result =
+          new(zone()) HCompareNumericAndBranch(left, right, op);
       result->set_observed_input_representation(left_rep, right_rep);
       result->set_position(expr->position());
       return ast_context()->ReturnControl(result, expr->id());
@@ -9522,6 +9312,7 @@
   }
 }
 
+
 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
diff --git a/src/hydrogen.h b/src/hydrogen.h
index f80aca1..7e4c691 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -291,14 +291,12 @@
   HEnvironment* start_environment() const { return start_environment_; }
 
   void FinalizeUniqueValueIds();
-  void InitializeInferredTypes();
   void InsertTypeConversions();
   void MergeRemovableSimulates();
   void InsertRepresentationChanges();
   void MarkDeoptimizeOnUndefined();
   void ComputeMinusZeroChecks();
   bool ProcessArgumentsObject();
-  void EliminateRedundantPhis();
   void Canonicalize();
   void OrderBlocks();
   void AssignDominators();
@@ -306,7 +304,6 @@
   void EliminateRedundantBoundsChecks();
   void DehoistSimpleArrayIndexComputations();
   void RestoreActualValues();
-  void DeadCodeElimination(const char *phase_name);
   void PropagateDeoptimizingMark();
   void AnalyzeAndPruneEnvironmentLiveness();
 
@@ -333,6 +330,8 @@
   HConstant* GetConstantNull();
   HConstant* GetInvalidContext();
 
+  bool IsStandardConstant(HConstant* constant);
+
   HBasicBlock* CreateBasicBlock();
   HArgumentsObject* GetArgumentsObject() const {
     return arguments_object_.get();
@@ -449,9 +448,6 @@
     phase.Run();
   }
 
-  void MarkLive(HValue* ref, HValue* instr, ZoneList<HValue*>* worklist);
-  void MarkLiveInstructions();
-  void RemoveDeadInstructions();
   void MarkAsDeoptimizingRecursively(HBasicBlock* block);
   void NullifyUnreachableInstructions();
   void InsertTypeConversions(HInstruction* instr);
@@ -462,8 +458,6 @@
                                         int use_index,
                                         Representation to);
   void InsertRepresentationChangesForValue(HValue* value);
-  void InferTypes(ZoneList<HValue*>* worklist);
-  void InitializeInferredTypes(int from_inclusive, int to_inclusive);
   void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
   void SetupInformativeDefinitionsInBlock(HBasicBlock* block);
   void SetupInformativeDefinitionsRecursively(HBasicBlock* block);
@@ -1129,6 +1123,15 @@
 
   HLoadNamedField* AddLoadFixedArrayLength(HValue *object);
 
+  HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin, HContext* context);
+
+  enum SoftDeoptimizeMode {
+    MUST_EMIT_SOFT_DEOPT,
+    CAN_OMIT_SOFT_DEOPT
+  };
+
+  void AddSoftDeoptimize(SoftDeoptimizeMode mode = CAN_OMIT_SOFT_DEOPT);
+
   class IfBuilder {
    public:
     explicit IfBuilder(HGraphBuilder* builder,
@@ -1140,13 +1143,6 @@
       if (!finished_) End();
     }
 
-    HInstruction* IfCompare(
-        HValue* left,
-        HValue* right,
-        Token::Value token);
-
-    HInstruction* IfCompareMap(HValue* left, Handle<Map> map);
-
     template<class Condition>
     HInstruction* If(HValue *p) {
       HControlInstruction* compare = new(zone()) Condition(p);
@@ -1161,6 +1157,13 @@
       return compare;
     }
 
+    template<class Condition, class P2, class P3>
+    HInstruction* If(HValue* p1, P2 p2, P3 p3) {
+      HControlInstruction* compare = new(zone()) Condition(p1, p2, p3);
+      AddCompare(compare);
+      return compare;
+    }
+
     template<class Condition, class P2>
     HInstruction* IfNot(HValue* p1, P2 p2) {
       HControlInstruction* compare = new(zone()) Condition(p1, p2);
@@ -1172,17 +1175,15 @@
       return compare;
     }
 
-    HInstruction* OrIfCompare(
-        HValue* p1,
-        HValue* p2,
-        Token::Value token) {
-      Or();
-      return IfCompare(p1, p2, token);
-    }
-
-    HInstruction* OrIfCompareMap(HValue* left, Handle<Map> map) {
-      Or();
-      return IfCompareMap(left, map);
+    template<class Condition, class P2, class P3>
+    HInstruction* IfNot(HValue* p1, P2 p2, P3 p3) {
+      HControlInstruction* compare = new(zone()) Condition(p1, p2, p3);
+      AddCompare(compare);
+      HBasicBlock* block0 = compare->SuccessorAt(0);
+      HBasicBlock* block1 = compare->SuccessorAt(1);
+      compare->SetSuccessorAt(0, block1);
+      compare->SetSuccessorAt(1, block0);
+      return compare;
     }
 
     template<class Condition>
@@ -1197,17 +1198,10 @@
       return If<Condition>(p1, p2);
     }
 
-    HInstruction* AndIfCompare(
-        HValue* p1,
-        HValue* p2,
-        Token::Value token) {
-      And();
-      return IfCompare(p1, p2, token);
-    }
-
-    HInstruction* AndIfCompareMap(HValue* left, Handle<Map> map) {
-      And();
-      return IfCompareMap(left, map);
+    template<class Condition, class P2, class P3>
+    HInstruction* OrIf(HValue* p1, P2 p2, P3 p3) {
+      Or();
+      return If<Condition>(p1, p2, p3);
     }
 
     template<class Condition>
@@ -1222,6 +1216,12 @@
       return If<Condition>(p1, p2);
     }
 
+    template<class Condition, class P2, class P3>
+    HInstruction* AndIf(HValue* p1, P2 p2, P3 p3) {
+      And();
+      return If<Condition>(p1, p2, p3);
+    }
+
     void Or();
     void And();
 
@@ -1409,6 +1409,9 @@
                                  ElementsKind kind,
                                  int length);
 
+  HInstruction* BuildUnaryMathOp(
+      HValue* value, Handle<Type> type, Token::Value token);
+
   void BuildCompareNil(
       HValue* value,
       Handle<Type> type,
@@ -1495,8 +1498,6 @@
 
   bool inline_bailout() { return inline_bailout_; }
 
-  void AddSoftDeoptimize();
-
   void Bailout(const char* reason);
 
   HBasicBlock* CreateJoin(HBasicBlock* first,
@@ -1676,9 +1677,6 @@
   // to push them as outgoing parameters.
   template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
 
-  static Representation ToRepresentation(TypeInfo info);
-  static Representation ToRepresentation(Handle<Type> type);
-
   void SetUpScope(Scope* scope);
   virtual void VisitStatements(ZoneList<Statement*>* statements);
 
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index 7bb643a..60b525f 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -1055,6 +1055,7 @@
   }
 }
 
+
 void Assembler::ror(Register dst, uint8_t imm8) {
   EnsureSpace ensure_space(this);
   ASSERT(is_uint5(imm8));  // illegal shift count
@@ -1068,6 +1069,7 @@
   }
 }
 
+
 void Assembler::ror_cl(Register dst) {
   EnsureSpace ensure_space(this);
   EMIT(0xD3);
@@ -2137,6 +2139,7 @@
   EMIT(static_cast<byte>(mode) | 0x8);
 }
 
+
 void Assembler::movmskpd(Register dst, XMMRegister src) {
   ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 29a4be2..31f4f4b 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -230,6 +230,28 @@
 }
 
 
+void UnaryOpStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { eax };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(UnaryOpIC_Miss);
+}
+
+
+void StoreGlobalStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { edx, ecx, eax };
+  descriptor->register_param_count_ = 3;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(StoreIC_MissFromStubFailure);
+}
+
+
 #define __ ACCESS_MASM(masm)
 
 
@@ -759,325 +781,6 @@
 }
 
 
-void UnaryOpStub::PrintName(StringStream* stream) {
-  const char* op_name = Token::Name(op_);
-  const char* overwrite_name = NULL;  // Make g++ happy.
-  switch (mode_) {
-    case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
-    case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
-  }
-  stream->Add("UnaryOpStub_%s_%s_%s",
-              op_name,
-              overwrite_name,
-              UnaryOpIC::GetName(operand_type_));
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::Generate(MacroAssembler* masm) {
-  switch (operand_type_) {
-    case UnaryOpIC::UNINITIALIZED:
-      GenerateTypeTransition(masm);
-      break;
-    case UnaryOpIC::SMI:
-      GenerateSmiStub(masm);
-      break;
-    case UnaryOpIC::NUMBER:
-      GenerateNumberStub(masm);
-      break;
-    case UnaryOpIC::GENERIC:
-      GenerateGenericStub(masm);
-      break;
-  }
-}
-
-
-void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
-  __ pop(ecx);  // Save return address.
-
-  __ push(eax);  // the operand
-  __ push(Immediate(Smi::FromInt(op_)));
-  __ push(Immediate(Smi::FromInt(mode_)));
-  __ push(Immediate(Smi::FromInt(operand_type_)));
-
-  __ 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::kUnaryOp_Patch), masm->isolate()), 4, 1);
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateSmiStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateSmiStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
-  Label non_smi, undo, slow;
-  GenerateSmiCodeSub(masm, &non_smi, &undo, &slow,
-                     Label::kNear, Label::kNear, Label::kNear);
-  __ bind(&undo);
-  GenerateSmiCodeUndo(masm);
-  __ bind(&non_smi);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
-  Label non_smi;
-  GenerateSmiCodeBitNot(masm, &non_smi);
-  __ bind(&non_smi);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
-                                     Label* non_smi,
-                                     Label* undo,
-                                     Label* slow,
-                                     Label::Distance non_smi_near,
-                                     Label::Distance undo_near,
-                                     Label::Distance slow_near) {
-  // Check whether the value is a smi.
-  __ JumpIfNotSmi(eax, non_smi, non_smi_near);
-
-  // We can't handle -0 with smis, so use a type transition for that case.
-  __ test(eax, eax);
-  __ j(zero, slow, slow_near);
-
-  // Try optimistic subtraction '0 - value', saving operand in eax for undo.
-  __ mov(edx, eax);
-  __ Set(eax, Immediate(0));
-  __ sub(eax, edx);
-  __ j(overflow, undo, undo_near);
-  __ ret(0);
-}
-
-
-void UnaryOpStub::GenerateSmiCodeBitNot(
-    MacroAssembler* masm,
-    Label* non_smi,
-    Label::Distance non_smi_near) {
-  // Check whether the value is a smi.
-  __ JumpIfNotSmi(eax, non_smi, non_smi_near);
-
-  // Flip bits and revert inverted smi-tag.
-  __ not_(eax);
-  __ and_(eax, ~kSmiTagMask);
-  __ ret(0);
-}
-
-
-void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) {
-  __ mov(eax, edx);
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateNumberStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateNumberStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
-  Label non_smi, undo, slow, call_builtin;
-  GenerateSmiCodeSub(masm, &non_smi, &undo, &call_builtin, Label::kNear);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeSub(masm, &slow);
-  __ bind(&undo);
-  GenerateSmiCodeUndo(masm);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-  __ bind(&call_builtin);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateNumberStubBitNot(
-    MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeBitNot(masm, &slow);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
-                                            Label* slow) {
-  __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
-  __ cmp(edx, masm->isolate()->factory()->heap_number_map());
-  __ j(not_equal, slow);
-
-  if (mode_ == UNARY_OVERWRITE) {
-    __ xor_(FieldOperand(eax, HeapNumber::kExponentOffset),
-            Immediate(HeapNumber::kSignMask));  // Flip sign.
-  } else {
-    __ mov(edx, eax);
-    // edx: operand
-
-    Label slow_allocate_heapnumber, heapnumber_allocated;
-    __ AllocateHeapNumber(eax, ebx, ecx, &slow_allocate_heapnumber);
-    __ jmp(&heapnumber_allocated, Label::kNear);
-
-    __ bind(&slow_allocate_heapnumber);
-    {
-      FrameScope scope(masm, StackFrame::INTERNAL);
-      __ push(edx);
-      __ CallRuntime(Runtime::kNumberAlloc, 0);
-      __ pop(edx);
-    }
-
-    __ bind(&heapnumber_allocated);
-    // eax: allocated 'empty' number
-    __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset));
-    __ xor_(ecx, HeapNumber::kSignMask);  // Flip sign.
-    __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx);
-    __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset));
-    __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
-  }
-  __ ret(0);
-}
-
-
-void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
-                                               Label* slow) {
-  __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
-  __ cmp(edx, masm->isolate()->factory()->heap_number_map());
-  __ j(not_equal, slow);
-
-  // Convert the heap number in eax to an untagged integer in ecx.
-  IntegerConvert(masm, eax, CpuFeatures::IsSupported(SSE3), slow);
-
-  // Do the bitwise operation and check if the result fits in a smi.
-  Label try_float;
-  __ not_(ecx);
-  __ cmp(ecx, 0xc0000000);
-  __ j(sign, &try_float, Label::kNear);
-
-  // Tag the result as a smi and we're done.
-  STATIC_ASSERT(kSmiTagSize == 1);
-  __ lea(eax, Operand(ecx, times_2, kSmiTag));
-  __ ret(0);
-
-  // Try to store the result in a heap number.
-  __ bind(&try_float);
-  if (mode_ == UNARY_NO_OVERWRITE) {
-    Label slow_allocate_heapnumber, heapnumber_allocated;
-    __ mov(ebx, eax);
-    __ AllocateHeapNumber(eax, edx, edi, &slow_allocate_heapnumber);
-    __ jmp(&heapnumber_allocated);
-
-    __ bind(&slow_allocate_heapnumber);
-    {
-      FrameScope scope(masm, StackFrame::INTERNAL);
-      // Push the original HeapNumber on the stack. The integer value can't
-      // be stored since it's untagged and not in the smi range (so we can't
-      // smi-tag it). We'll recalculate the value after the GC instead.
-      __ push(ebx);
-      __ CallRuntime(Runtime::kNumberAlloc, 0);
-      // New HeapNumber is in eax.
-      __ pop(edx);
-    }
-    // IntegerConvert uses ebx and edi as scratch registers.
-    // This conversion won't go slow-case.
-    IntegerConvert(masm, edx, CpuFeatures::IsSupported(SSE3), slow);
-    __ not_(ecx);
-
-    __ bind(&heapnumber_allocated);
-  }
-  if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatureScope use_sse2(masm, SSE2);
-    __ cvtsi2sd(xmm0, ecx);
-    __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
-  } else {
-    __ push(ecx);
-    __ fild_s(Operand(esp, 0));
-    __ pop(ecx);
-    __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
-  }
-  __ ret(0);
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateGenericStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateGenericStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm)  {
-  Label non_smi, undo, slow;
-  GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, Label::kNear);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeSub(masm, &slow);
-  __ bind(&undo);
-  GenerateSmiCodeUndo(masm);
-  __ bind(&slow);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeBitNot(masm, &slow);
-  __ bind(&slow);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
-  // Handle the slow case by jumping to the corresponding JavaScript builtin.
-  __ pop(ecx);  // pop return address.
-  __ push(eax);
-  __ push(ecx);  // push return address
-  switch (op_) {
-    case Token::SUB:
-      __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
-      break;
-    case Token::BIT_NOT:
-      __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
 void BinaryOpStub::Initialize() {
   platform_specific_bit_ = CpuFeatures::IsSupported(SSE3);
 }
diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h
index 6dc63bd..dc21d40 100644
--- a/src/ia32/code-stubs-ia32.h
+++ b/src/ia32/code-stubs-ia32.h
@@ -86,80 +86,6 @@
 };
 
 
-class UnaryOpStub: public PlatformCodeStub {
- public:
-  UnaryOpStub(Token::Value op,
-              UnaryOverwriteMode mode,
-              UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
-      : op_(op),
-        mode_(mode),
-        operand_type_(operand_type) {
-  }
-
- private:
-  Token::Value op_;
-  UnaryOverwriteMode mode_;
-
-  // Operand type information determined at runtime.
-  UnaryOpIC::TypeInfo operand_type_;
-
-  virtual void PrintName(StringStream* stream);
-
-  class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
-  class OpBits: public BitField<Token::Value, 1, 7> {};
-  class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
-
-  Major MajorKey() { return UnaryOp; }
-  int MinorKey() {
-    return ModeBits::encode(mode_)
-           | OpBits::encode(op_)
-           | OperandTypeInfoBits::encode(operand_type_);
-  }
-
-  // Note: A lot of the helper functions below will vanish when we use virtual
-  // function instead of switch more often.
-  void Generate(MacroAssembler* masm);
-
-  void GenerateTypeTransition(MacroAssembler* masm);
-
-  void GenerateSmiStub(MacroAssembler* masm);
-  void GenerateSmiStubSub(MacroAssembler* masm);
-  void GenerateSmiStubBitNot(MacroAssembler* masm);
-  void GenerateSmiCodeSub(MacroAssembler* masm,
-                          Label* non_smi,
-                          Label* undo,
-                          Label* slow,
-                          Label::Distance non_smi_near = Label::kFar,
-                          Label::Distance undo_near = Label::kFar,
-                          Label::Distance slow_near = Label::kFar);
-  void GenerateSmiCodeBitNot(MacroAssembler* masm,
-                             Label* non_smi,
-                             Label::Distance non_smi_near = Label::kFar);
-  void GenerateSmiCodeUndo(MacroAssembler* masm);
-
-  void GenerateNumberStub(MacroAssembler* masm);
-  void GenerateNumberStubSub(MacroAssembler* masm);
-  void GenerateNumberStubBitNot(MacroAssembler* masm);
-  void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
-  void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
-
-  void GenerateGenericStub(MacroAssembler* masm);
-  void GenerateGenericStubSub(MacroAssembler* masm);
-  void GenerateGenericStubBitNot(MacroAssembler* masm);
-  void GenerateGenericCodeFallback(MacroAssembler* masm);
-
-  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
-
-  virtual InlineCacheState GetICState() {
-    return UnaryOpIC::ToState(operand_type_);
-  }
-
-  virtual void FinishCode(Handle<Code> code) {
-    code->set_unary_op_type(operand_type_);
-  }
-};
-
-
 class StringHelper : public AllStatic {
  public:
   // Generate code for copying characters using a simple loop. This should only
diff --git a/src/ia32/debug-ia32.cc b/src/ia32/debug-ia32.cc
index db1d5a6..68199f9 100644
--- a/src/ia32/debug-ia32.cc
+++ b/src/ia32/debug-ia32.cc
@@ -91,6 +91,7 @@
   rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength);
 }
 
+
 // All debug break stubs support padding for LiveEdit.
 const bool Debug::FramePaddingLayout::kIsSupported = true;
 
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index 14e5800..c43f11c 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -575,6 +575,7 @@
   }
 }
 
+
 int DisassemblerIA32::D1D3C1Instruction(byte* data) {
   byte op = *data;
   ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index cf3132d..5b14afb 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -107,6 +107,7 @@
 // formal parameter count expected by the function.
 //
 // The live registers are:
+//   o ecx: CallKind
 //   o edi: the JS function object being called (i.e. ourselves)
 //   o esi: our context
 //   o ebp: our caller's frame pointer
@@ -4363,10 +4364,7 @@
 void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
                                            const char* comment) {
   Comment cmt(masm_, comment);
-  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
-  UnaryOverwriteMode overwrite =
-      can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
-  UnaryOpStub stub(expr->op(), overwrite);
+  UnaryOpStub stub(expr->op());
   // UnaryOpStub expects the argument to be in the
   // accumulator register eax.
   VisitForAccumulatorValue(expr->expression());
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index defae1c..0b56e8f 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2036,6 +2036,16 @@
 }
 
 
+void LCodeGen::DoNegateNoSSE2D(LNegateNoSSE2D* instr) {
+  __ push(Immediate(-1));
+  __ fild_s(Operand(esp, 0));
+  __ add(esp, Immediate(kPointerSize));
+  __ fmulp();
+  CurrentInstructionReturnsX87Result();
+}
+
+
+
 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
   ASSERT(ToRegister(instr->context()).is(esi));
   ASSERT(ToRegister(instr->left()).is(edx));
@@ -2058,12 +2068,12 @@
 
 template<class InstrType>
 void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
-  int right_block = instr->FalseDestination(chunk_);
   int left_block = instr->TrueDestination(chunk_);
+  int right_block = instr->FalseDestination(chunk_);
 
   int next_block = GetNextEmittedBlock();
 
-  if (right_block == left_block) {
+  if (right_block == left_block || cc == no_condition) {
     EmitGoto(left_block);
   } else if (left_block == next_block) {
     __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
@@ -2076,6 +2086,25 @@
 }
 
 
+void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
+  Representation r = instr->hydrogen()->value()->representation();
+  if (r.IsSmiOrInteger32() || r.IsDouble()) {
+    EmitBranch(instr, no_condition);
+  } else {
+    ASSERT(r.IsTagged());
+    Register reg = ToRegister(instr->value());
+    HType type = instr->hydrogen()->value()->type();
+    if (type.IsTaggedNumber()) {
+      EmitBranch(instr, no_condition);
+    }
+    __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
+    __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
+           factory()->heap_number_map());
+    EmitBranch(instr, equal);
+  }
+}
+
+
 void LCodeGen::DoBranch(LBranch* instr) {
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsSmiOrInteger32()) {
@@ -2256,7 +2285,7 @@
 }
 
 
-void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
+void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
   LOperand* left = instr->left();
   LOperand* right = instr->right();
   Condition cc = TokenToCondition(instr->op(), instr->is_double());
@@ -3777,6 +3806,7 @@
   }
 }
 
+
 void LCodeGen::DoMathRound(LMathRound* instr) {
   CpuFeatureScope scope(masm(), SSE2);
   Register output_reg = ToRegister(instr->result());
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index d05da8a..7e66ac2 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -115,6 +115,7 @@
   Immediate ToSmiImmediate(LOperand* op) const {
     return Immediate(Smi::FromInt(ToInteger32(LConstantOperand::cast(op))));
   }
+  double ToDouble(LConstantOperand* op) const;
 
   // Support for non-sse2 (x87) floating point stack handling.
   // These functions maintain the depth of the stack (either 0 or 1)
@@ -293,7 +294,6 @@
   XMMRegister ToDoubleRegister(int index) const;
   int ToInteger32(LConstantOperand* op) const;
 
-  double ToDouble(LConstantOperand* op) const;
   Operand BuildFastArrayOperand(LOperand* elements_pointer,
                                 LOperand* key,
                                 Representation key_representation,
diff --git a/src/ia32/lithium-gap-resolver-ia32.cc b/src/ia32/lithium-gap-resolver-ia32.cc
index 86bfe2f..a75ce21 100644
--- a/src/ia32/lithium-gap-resolver-ia32.cc
+++ b/src/ia32/lithium-gap-resolver-ia32.cc
@@ -313,6 +313,31 @@
       } else {
         __ LoadObject(dst, cgen_->ToHandle(constant_source));
       }
+    } else if (destination->IsDoubleRegister()) {
+      double v = cgen_->ToDouble(constant_source);
+      uint64_t int_val = BitCast<uint64_t, double>(v);
+      int32_t lower = static_cast<int32_t>(int_val);
+      int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
+      if (CpuFeatures::IsSupported(SSE2)) {
+        CpuFeatureScope scope(cgen_->masm(), SSE2);
+        XMMRegister dst = cgen_->ToDoubleRegister(destination);
+        if (int_val == 0) {
+          __ xorps(dst, dst);
+        } else {
+          __ push(Immediate(upper));
+          __ push(Immediate(lower));
+          __ movdbl(dst, Operand(esp, 0));
+          __ add(esp, Immediate(kDoubleSize));
+        }
+      } else {
+        __ push(Immediate(upper));
+        __ push(Immediate(lower));
+        if (cgen_->X87StackNonEmpty()) {
+          cgen_->PopX87();
+        }
+        cgen_->PushX87DoubleOperand(MemOperand(esp, 0));
+        __ add(esp, Immediate(kDoubleSize));
+      }
     } else {
       ASSERT(destination->IsStackSlot());
       Operand dst = cgen_->ToOperand(destination);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 8231c4e..1934e0a 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -201,7 +201,7 @@
 }
 
 
-void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
+void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if ");
   left()->PrintTo(stream);
   stream->Add(" %s ", Token::String(op()));
@@ -1578,7 +1578,17 @@
     }
     return DefineSameAsFirst(mul);
   } else if (instr->representation().IsDouble()) {
-    return DoArithmeticD(Token::MUL, instr);
+    if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+      return DoArithmeticD(Token::MUL, instr);
+    }
+    ASSERT(instr->right()->IsConstant() &&
+           static_cast<HConstant*>(instr->right())->DoubleValue() == -1);
+    // TODO(olivf) This is currently just a hack to support the UnaryOp Minus
+    // Stub. This will go away once we can use more than one X87 register,
+    // thus fully support binary instructions without SSE2.
+    LOperand* left = UseX87TopOfStack(instr->left());
+    LNegateNoSSE2D* result = new(zone()) LNegateNoSSE2D(left);
+    return DefineX87TOS(result);
   } else {
     ASSERT(instr->representation().IsSmiOrTagged());
     return DoArithmeticT(Token::MUL, instr);
@@ -1695,8 +1705,8 @@
 }
 
 
-LInstruction* LChunkBuilder::DoCompareIDAndBranch(
-    HCompareIDAndBranch* instr) {
+LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
+    HCompareNumericAndBranch* instr) {
   Representation r = instr->representation();
   if (r.IsSmiOrInteger32()) {
     ASSERT(instr->left()->representation().IsSmiOrInteger32());
@@ -1704,7 +1714,7 @@
         instr->right()->representation()));
     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
     LOperand* right = UseOrConstantAtStart(instr->right());
-    return new(zone()) LCmpIDAndBranch(left, right);
+    return new(zone()) LCompareNumericAndBranch(left, right);
   } else {
     ASSERT(r.IsDouble());
     ASSERT(instr->left()->representation().IsDouble());
@@ -1718,7 +1728,7 @@
       left = UseRegisterAtStart(instr->left());
       right = UseRegisterAtStart(instr->right());
     }
-    return new(zone()) LCmpIDAndBranch(left, right);
+    return new(zone()) LCompareNumericAndBranch(left, right);
   }
 }
 
@@ -2038,6 +2048,18 @@
 }
 
 
+LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return AssignEnvironment(new(zone()) LCheckSmi(value));
+}
+
+
+LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) {
+  return new(zone())
+    LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value()));
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LOperand* temp = TempRegister();
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index e48e881..7b332d2 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -75,7 +75,7 @@
   V(ClampTToUint8)                              \
   V(ClampTToUint8NoSSE2)                        \
   V(ClassOfTestAndBranch)                       \
-  V(CmpIDAndBranch)                             \
+  V(CompareNumericAndBranch)                    \
   V(CmpObjectEqAndBranch)                       \
   V(CmpMapAndBranch)                            \
   V(CmpT)                                       \
@@ -114,6 +114,7 @@
   V(IsObjectAndBranch)                          \
   V(IsStringAndBranch)                          \
   V(IsSmiAndBranch)                             \
+  V(IsNumberAndBranch)                          \
   V(IsUndetectableAndBranch)                    \
   V(Label)                                      \
   V(LazyBailout)                                \
@@ -142,6 +143,7 @@
   V(MathTan)                                    \
   V(ModI)                                       \
   V(MulI)                                       \
+  V(NegateNoSSE2D)                              \
   V(NumberTagD)                                 \
   V(NumberTagI)                                 \
   V(NumberTagU)                                 \
@@ -659,6 +661,18 @@
 };
 
 
+class LNegateNoSSE2D: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LNegateNoSSE2D(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(NegateNoSSE2D, "negate-no-sse2-d")
+};
+
+
 class LMulI: public LTemplateInstruction<1, 2, 1> {
  public:
   LMulI(LOperand* left, LOperand* right, LOperand* temp) {
@@ -676,9 +690,9 @@
 };
 
 
-class LCmpIDAndBranch: public LControlInstruction<2, 0> {
+class LCompareNumericAndBranch: public LControlInstruction<2, 0> {
  public:
-  LCmpIDAndBranch(LOperand* left, LOperand* right) {
+  LCompareNumericAndBranch(LOperand* left, LOperand* right) {
     inputs_[0] = left;
     inputs_[1] = right;
   }
@@ -686,8 +700,9 @@
   LOperand* left() { return inputs_[0]; }
   LOperand* right() { return inputs_[1]; }
 
-  DECLARE_CONCRETE_INSTRUCTION(CmpIDAndBranch, "cmp-id-and-branch")
-  DECLARE_HYDROGEN_ACCESSOR(CompareIDAndBranch)
+  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
+                               "compare-numeric-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
 
   Token::Value op() const { return hydrogen()->token(); }
   bool is_double() const {
@@ -883,6 +898,19 @@
 };
 
 
+class LIsNumberAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LIsNumberAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsNumberAndBranch, "is-number-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(IsNumberAndBranch)
+};
+
+
 class LIsStringAndBranch: public LControlInstruction<1, 1> {
  public:
   LIsStringAndBranch(LOperand* value, LOperand* temp) {
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index a9a0268..989b83e 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -842,6 +842,7 @@
   LeaveExitFrameEpilogue();
 }
 
+
 void MacroAssembler::LeaveExitFrameEpilogue() {
   // Restore current context from top and clear it in debug mode.
   ExternalReference context_address(Isolate::kContextAddress, isolate());
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index f478e57..dfcc869 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -1030,6 +1030,7 @@
   __ bind(&after_position);
 }
 
+
 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
   ASSERT(register_index >= num_saved_registers_);  // Reserved for positions!
   __ mov(register_location(register_index), Immediate(to));
diff --git a/src/ic.cc b/src/ic.cc
index ff3a94d..02f2f0f 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1668,7 +1668,7 @@
   ASSERT(!lookup->IsHandler());
 
   Handle<Code> code = ComputeStoreMonomorphic(
-      lookup, strict_mode, receiver, name);
+      lookup, strict_mode, receiver, name, value);
   if (code.is_null()) {
     Handle<Code> stub = strict_mode == kStrictMode
         ? generic_stub_strict() : generic_stub();
@@ -1684,7 +1684,8 @@
 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
                                               StrictModeFlag strict_mode,
                                               Handle<JSObject> receiver,
-                                              Handle<String> name) {
+                                              Handle<String> name,
+                                              Handle<Object> value) {
   Handle<JSObject> holder(lookup->holder());
   switch (lookup->type()) {
     case FIELD:
@@ -1699,7 +1700,7 @@
         Handle<PropertyCell> cell(
             global->GetPropertyCell(lookup), isolate());
         return isolate()->stub_cache()->ComputeStoreGlobal(
-            name, global, cell, strict_mode);
+            name, global, cell, value, strict_mode);
       }
       ASSERT(holder.is_identical_to(receiver));
       return isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
@@ -2093,7 +2094,8 @@
 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
                                                    StrictModeFlag strict_mode,
                                                    Handle<JSObject> receiver,
-                                                   Handle<String> name) {
+                                                   Handle<String> name,
+                                                   Handle<Object> value) {
   // If the property has a non-field type allowing map transitions
   // where there is extra room in the object, we leave the IC in its
   // current state.
@@ -2245,6 +2247,20 @@
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 3);
+  StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
+  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
+  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
+  return ic.Store(state,
+                  Code::GetStrictMode(extra_ic_state),
+                  args.at<Object>(0),
+                  args.at<String>(1),
+                  args.at<Object>(2));
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
   SealHandleScope shs(isolate);
 
@@ -2401,86 +2417,6 @@
 }
 
 
-void UnaryOpIC::patch(Code* code) {
-  set_target(code);
-}
-
-
-const char* UnaryOpIC::GetName(TypeInfo type_info) {
-  switch (type_info) {
-    case UNINITIALIZED: return "Uninitialized";
-    case SMI: return "Smi";
-    case NUMBER: return "Number";
-    case GENERIC: return "Generic";
-    default: return "Invalid";
-  }
-}
-
-
-UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) {
-  switch (type_info) {
-    case UNINITIALIZED:
-      return v8::internal::UNINITIALIZED;
-    case SMI:
-    case NUMBER:
-      return MONOMORPHIC;
-    case GENERIC:
-      return v8::internal::GENERIC;
-  }
-  UNREACHABLE();
-  return v8::internal::UNINITIALIZED;
-}
-
-
-Handle<Type> UnaryOpIC::TypeInfoToType(TypeInfo type_info, Isolate* isolate) {
-  switch (type_info) {
-    case UNINITIALIZED:
-      return handle(Type::None(), isolate);
-    case SMI:
-      return handle(Type::Smi(), isolate);
-    case NUMBER:
-      return handle(Type::Number(), isolate);
-    case GENERIC:
-      return handle(Type::Any(), isolate);
-  }
-  UNREACHABLE();
-  return handle(Type::Any(), isolate);
-}
-
-
-UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) {
-  v8::internal::TypeInfo operand_type =
-      v8::internal::TypeInfo::FromValue(operand);
-  if (operand_type.IsSmi()) {
-    return SMI;
-  } else if (operand_type.IsNumber()) {
-    return NUMBER;
-  } else {
-    return GENERIC;
-  }
-}
-
-
-UnaryOpIC::TypeInfo UnaryOpIC::ComputeNewType(
-    TypeInfo current_type,
-    TypeInfo previous_type) {
-  switch (previous_type) {
-    case UNINITIALIZED:
-      return current_type;
-    case SMI:
-      return (current_type == GENERIC) ? GENERIC : NUMBER;
-    case NUMBER:
-      return GENERIC;
-    case GENERIC:
-      // We should never do patching if we are in GENERIC state.
-      UNREACHABLE();
-      return GENERIC;
-  }
-  UNREACHABLE();
-  return GENERIC;
-}
-
-
 void BinaryOpIC::patch(Code* code) {
   set_target(code);
 }
@@ -2558,57 +2494,24 @@
 }
 
 
-RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) {
-  ASSERT(args.length() == 4);
+MaybeObject* UnaryOpIC::Transition(Handle<Object> object) {
+  Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
+  UnaryOpStub stub(extra_ic_state);
 
+  stub.UpdateStatus(object);
+
+  Handle<Code> code = stub.GetCode(isolate());
+  set_target(*code);
+
+  return stub.Result(object, isolate());
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss) {
   HandleScope scope(isolate);
-  Handle<Object> operand = args.at<Object>(0);
-  Token::Value op = static_cast<Token::Value>(args.smi_at(1));
-  UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2));
-  UnaryOpIC::TypeInfo previous_type =
-      static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3));
-
-  UnaryOpIC::TypeInfo type = UnaryOpIC::GetTypeInfo(operand);
-  type = UnaryOpIC::ComputeNewType(type, previous_type);
-
-  UnaryOpStub stub(op, mode, type);
-  Handle<Code> code = stub.GetCode(isolate);
-  if (!code.is_null()) {
-    if (FLAG_trace_ic) {
-      PrintF("[UnaryOpIC in ");
-      JavaScriptFrame::PrintTop(isolate, stdout, false, true);
-      PrintF(" %s => %s #%s @ %p]\n",
-             UnaryOpIC::GetName(previous_type),
-             UnaryOpIC::GetName(type),
-             Token::Name(op),
-             static_cast<void*>(*code));
-    }
-    UnaryOpIC ic(isolate);
-    ic.patch(*code);
-  }
-
-  Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
-  Object* builtin = NULL;  // Initialization calms down the compiler.
-  switch (op) {
-    case Token::SUB:
-      builtin = builtins->javascript_builtin(Builtins::UNARY_MINUS);
-      break;
-    case Token::BIT_NOT:
-      builtin = builtins->javascript_builtin(Builtins::BIT_NOT);
-      break;
-    default:
-      UNREACHABLE();
-  }
-
-  Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
-
-  bool caught_exception;
-  Handle<Object> result = Execution::Call(builtin_function, operand, 0, NULL,
-                                          &caught_exception);
-  if (caught_exception) {
-    return Failure::Exception();
-  }
-  return *result;
+  Handle<Object> object = args.at<Object>(0);
+  UnaryOpIC ic(isolate);
+  return ic.Transition(object);
 }
 
 
@@ -3069,9 +2972,7 @@
   // types must be supported as a result of the miss.
   bool already_monomorphic = stub.IsMonomorphic();
 
-  CompareNilICStub::State old_state = stub.GetState();
-  stub.Record(object);
-  old_state.TraceTransition(stub.GetState());
+  stub.UpdateStatus(object);
 
   NilValue nil = stub.GetNilValue();
 
@@ -3108,7 +3009,7 @@
 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object,
                                     Code::ExtraICState extra_ic_state) {
   ToBooleanStub stub(extra_ic_state);
-  bool to_boolean_value = stub.Record(object);
+  bool to_boolean_value = stub.UpdateStatus(object);
   Handle<Code> code = stub.GetCode(isolate());
   set_target(*code);
   return Smi::FromInt(to_boolean_value ? 1 : 0);
diff --git a/src/ic.h b/src/ic.h
index 829c6b1..61bf848 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -57,7 +57,6 @@
   ICU(LoadPropertyWithInterceptorForCall)             \
   ICU(KeyedLoadPropertyWithInterceptor)               \
   ICU(StoreInterceptorProperty)                       \
-  ICU(UnaryOp_Patch)                                  \
   ICU(BinaryOp_Patch)                                 \
   ICU(CompareIC_Miss)                                 \
   ICU(CompareNilIC_Miss)                              \
@@ -560,7 +559,8 @@
   virtual Handle<Code> ComputeStoreMonomorphic(LookupResult* lookup,
                                                StrictModeFlag strict_mode,
                                                Handle<JSObject> receiver,
-                                               Handle<String> name);
+                                               Handle<String> name,
+                                               Handle<Object> value);
 
  private:
   void set_target(Code* code) {
@@ -627,7 +627,8 @@
   virtual Handle<Code> ComputeStoreMonomorphic(LookupResult* lookup,
                                                StrictModeFlag strict_mode,
                                                Handle<JSObject> receiver,
-                                               Handle<String> name);
+                                               Handle<String> name,
+                                               Handle<Object> value);
   virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
 
   virtual Handle<Code> megamorphic_stub() {
@@ -681,28 +682,9 @@
 
 class UnaryOpIC: public IC {
  public:
-  // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
-  // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
-  enum TypeInfo {
-    UNINITIALIZED,
-    SMI,
-    NUMBER,
-    GENERIC
-  };
+  explicit UnaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
 
-  static Handle<Type> TypeInfoToType(TypeInfo info, Isolate* isolate);
-
-  explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
-
-  void patch(Code* code);
-
-  static const char* GetName(TypeInfo type_info);
-
-  static State ToState(TypeInfo type_info);
-
-  static TypeInfo GetTypeInfo(Handle<Object> operand);
-
-  static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
+  MUST_USE_RESULT MaybeObject* Transition(Handle<Object> object);
 };
 
 
@@ -838,6 +820,8 @@
 
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
+DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss);
+DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure);
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);
 
diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc
index 80dc8ea..17e79fd 100644
--- a/src/incremental-marking.cc
+++ b/src/incremental-marking.cc
@@ -563,6 +563,7 @@
   }
 }
 
+
 void IncrementalMarking::UncommitMarkingDeque() {
   if (state_ == STOPPED && marking_deque_memory_committed_) {
     bool success = marking_deque_memory_->Uncommit(
diff --git a/src/isolate.cc b/src/isolate.cc
index 6a87580..cf0f3b3 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -509,6 +509,7 @@
   Iterate(v, current_t);
 }
 
+
 void Isolate::IterateDeferredHandles(ObjectVisitor* visitor) {
   for (DeferredHandles* deferred = deferred_handles_head_;
        deferred != NULL;
@@ -1876,6 +1877,10 @@
   if (state_ == INITIALIZED) {
     TRACE_ISOLATE(deinit);
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
+    debugger()->UnloadDebugger();
+#endif
+
     if (FLAG_parallel_recompilation) optimizing_compiler_thread_.Stop();
 
     if (FLAG_sweeper_threads > 0) {
diff --git a/src/lithium.cc b/src/lithium.cc
index b22fdf6..3df8d6c 100644
--- a/src/lithium.cc
+++ b/src/lithium.cc
@@ -306,6 +306,7 @@
   return label->label();
 }
 
+
 void LChunk::MarkEmptyBlocks() {
   LPhase phase("L_Mark empty blocks", this);
   for (int i = 0; i < graph()->blocks()->length(); ++i) {
diff --git a/src/liveedit.cc b/src/liveedit.cc
index 3ec2da3..95f0b00 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -61,6 +61,7 @@
   USE(no_failure);
 }
 
+
 // A simple implementation of dynamic programming algorithm. It solves
 // the problem of finding the difference of 2 arrays. It uses a table of results
 // of subproblems. Each cell contains a number together with 2-bit flag
@@ -1456,6 +1457,7 @@
   static const int kMaximalBufferSize = 512*MB;
 };
 
+
 // Patch positions in code (changes relocation info section) and possibly
 // returns new instance of code.
 static Handle<Code> PatchPositionsInCode(
@@ -1829,6 +1831,7 @@
   Handle<JSArray> m_result;
 };
 
+
 // Drops all call frame matched by target and all frames above them.
 template<typename TARGET>
 static const char* DropActivationsInActiveThreadImpl(
@@ -1925,6 +1928,7 @@
   return NULL;
 }
 
+
 // Fills result array with statuses of functions. Modifies the stack
 // removing all listed function if possible and if do_drop is true.
 static const char* DropActivationsInActiveThread(
diff --git a/src/log.cc b/src/log.cc
index e95b963..a44add6 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -491,6 +491,7 @@
   code_event_handler_(&event);
 }
 
+
 void* Logger::IssueStartCodePosInfoEvent() {
   JitCodeEvent event;
   memset(&event, 0, sizeof(event));
@@ -500,6 +501,7 @@
   return event.user_data;
 }
 
+
 void Logger::IssueEndCodePosInfoEvent(Code* code, void* jit_handler_data) {
   JitCodeEvent event;
   memset(&event, 0, sizeof(event));
@@ -828,6 +830,7 @@
   ApiEvent("api,%s,\"%s\",%u\n", tag, *class_name, index);
 }
 
+
 void Logger::ApiObjectAccess(const char* tag, JSObject* object) {
   if (!log_->IsEnabled() || !FLAG_log_api) return;
   String* class_name_obj = object->class_name();
@@ -1206,6 +1209,7 @@
   }
 }
 
+
 void Logger::CodeStartLinePosInfoRecordEvent(PositionsRecorder* pos_recorder) {
   if (code_event_handler_ != NULL) {
       pos_recorder->AttachJITHandlerData(IssueStartCodePosInfoEvent());
@@ -1219,6 +1223,7 @@
   }
 }
 
+
 void Logger::SnapshotPositionEvent(Address addr, int pos) {
   if (!log_->IsEnabled()) return;
   if (FLAG_ll_prof) LowLevelSnapshotPositionEvent(addr, pos);
@@ -1654,15 +1659,15 @@
   Handle<String> func_name(shared->DebugName());
   if (shared->script()->IsScript()) {
     Handle<Script> script(Script::cast(shared->script()));
+    int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
     if (script->name()->IsString()) {
       Handle<String> script_name(String::cast(script->name()));
-      int line_num = GetScriptLineNumber(script, shared->start_position());
       if (line_num > 0) {
         PROFILE(isolate_,
                 CodeCreateEvent(
                     Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
                     *code, *shared, NULL,
-                    *script_name, line_num + 1));
+                    *script_name, line_num));
       } else {
         // Can't distinguish eval and script here, so always use Script.
         PROFILE(isolate_,
@@ -1674,7 +1679,8 @@
       PROFILE(isolate_,
               CodeCreateEvent(
                   Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
-                  *code, *shared, NULL, *func_name));
+                  *code, *shared, NULL,
+                  isolate_->heap()->empty_string(), line_num));
     }
   } else if (shared->IsApiFunction()) {
     // API function.
diff --git a/src/macros.py b/src/macros.py
index e442b44..5174d5f 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -145,6 +145,7 @@
 macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
 macro NUMBER_IS_FINITE(arg) = (%_IsSmi(%IS_VAR(arg)) || ((arg == arg) && (arg != 1/0) && (arg != -1/0)));
 macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToInteger(ToNumber(arg)));
+macro TO_INTEGER_FOR_SIDE_EFFECT(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : ToNumber(arg));
 macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToIntegerMapMinusZero(ToNumber(arg)));
 macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
 macro TO_UINT32(arg) = (arg >>> 0);
diff --git a/src/messages.js b/src/messages.js
index 137d98f..6c9e2d7 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -73,7 +73,7 @@
   invalid_in_operator_use:       ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"],
   instanceof_function_expected:  ["Expecting a function in instanceof check, but got ", "%0"],
   instanceof_nonobject_proto:    ["Function has non-object prototype '", "%0", "' in instanceof check"],
-  null_to_object:                ["Cannot convert null to object"],
+  undefined_or_null_to_object:   ["Cannot convert undefined or null to object"],
   reduce_no_initial:             ["Reduce of empty array with no initial value"],
   getter_must_be_callable:       ["Getter must be a function: ", "%0"],
   setter_must_be_callable:       ["Setter must be a function: ", "%0"],
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index c4fefcc..a04d456 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -501,11 +501,13 @@
       (opcode == COP1 && rs_field == BC1);  // Coprocessor branch.
 }
 
+
 bool Assembler::IsEmittedConstant(Instr instr) {
   uint32_t label_constant = GetLabelConst(instr);
   return label_constant == 0;  // Emitted label const in reg-exp engine.
 }
 
+
 bool Assembler::IsBeq(Instr instr) {
   return GetOpcodeField(instr) == BEQ;
 }
@@ -539,10 +541,12 @@
   return GetOpcodeField(instr) == JAL;
 }
 
+
 bool Assembler::IsJr(Instr instr) {
   return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR;
 }
 
+
 bool Assembler::IsJalr(Instr instr) {
   return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR;
 }
@@ -825,6 +829,7 @@
   }
 }
 
+
 bool Assembler::is_near(Label* L) {
   if (L->is_bound()) {
     return ((pc_offset() - L->pos()) < kMaxBranchOffset - 4 * kInstrSize);
@@ -832,6 +837,7 @@
   return false;
 }
 
+
 // We have to use a temporary register for things that can be relocated even
 // if they can be encoded in the MIPS's 16 bits of immediate-offset instruction
 // space.  There is no guarantee that the relocated location can be similarly
@@ -1669,6 +1675,7 @@
   GenInstrRegister(COP1, CFC1, rt, fs);
 }
 
+
 void Assembler::DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
   uint64_t i;
   OS::MemCopy(&i, &d, 8);
@@ -1677,6 +1684,7 @@
   *hi = i >> 32;
 }
 
+
 // Arithmetic.
 
 void Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) {
@@ -2257,6 +2265,7 @@
   CPU::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t));
 }
 
+
 void Assembler::JumpLabelToJumpRegister(Address pc) {
   // Address pc points to lui/ori instructions.
   // Jump to label may follow at pc + 2 * kInstrSize.
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
old mode 100755
new mode 100644
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 69b957a..727dee5 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -227,8 +227,31 @@
 }
 
 
+void UnaryOpStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { a0 };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(UnaryOpIC_Miss);
+}
+
+
+void StoreGlobalStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { a1, a2, a0 };
+  descriptor->register_param_count_ = 3;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(StoreIC_MissFromStubFailure);
+}
+
+
 #define __ ACCESS_MASM(masm)
 
+
 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
                                           Label* slow,
                                           Condition cc);
@@ -1586,294 +1609,6 @@
 }
 
 
-void UnaryOpStub::PrintName(StringStream* stream) {
-  const char* op_name = Token::Name(op_);
-  const char* overwrite_name = NULL;  // Make g++ happy.
-  switch (mode_) {
-    case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
-    case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
-  }
-  stream->Add("UnaryOpStub_%s_%s_%s",
-              op_name,
-              overwrite_name,
-              UnaryOpIC::GetName(operand_type_));
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::Generate(MacroAssembler* masm) {
-  switch (operand_type_) {
-    case UnaryOpIC::UNINITIALIZED:
-      GenerateTypeTransition(masm);
-      break;
-    case UnaryOpIC::SMI:
-      GenerateSmiStub(masm);
-      break;
-    case UnaryOpIC::NUMBER:
-      GenerateNumberStub(masm);
-      break;
-    case UnaryOpIC::GENERIC:
-      GenerateGenericStub(masm);
-      break;
-  }
-}
-
-
-void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
-  // Argument is in a0 and v0 at this point, so we can overwrite a0.
-  __ li(a2, Operand(Smi::FromInt(op_)));
-  __ li(a1, Operand(Smi::FromInt(mode_)));
-  __ li(a0, Operand(Smi::FromInt(operand_type_)));
-  __ Push(v0, a2, a1, a0);
-
-  __ TailCallExternalReference(
-      ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateSmiStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateSmiStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeSub(masm, &non_smi, &slow);
-  __ bind(&non_smi);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
-  Label non_smi;
-  GenerateSmiCodeBitNot(masm, &non_smi);
-  __ bind(&non_smi);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
-                                     Label* non_smi,
-                                     Label* slow) {
-  __ JumpIfNotSmi(a0, non_smi);
-
-  // The result of negating zero or the smallest negative smi is not a smi.
-  __ And(t0, a0, ~0x80000000);
-  __ Branch(slow, eq, t0, Operand(zero_reg));
-
-  // Return '0 - value'.
-  __ Ret(USE_DELAY_SLOT);
-  __ subu(v0, zero_reg, a0);
-}
-
-
-void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
-                                        Label* non_smi) {
-  __ JumpIfNotSmi(a0, non_smi);
-
-  // Flip bits and revert inverted smi-tag.
-  __ Neg(v0, a0);
-  __ And(v0, v0, ~kSmiTagMask);
-  __ Ret();
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateNumberStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateNumberStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
-  Label non_smi, slow, call_builtin;
-  GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeSub(masm, &slow);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-  __ bind(&call_builtin);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateNumberStubBitNot(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeBitNot(masm, &non_smi);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeBitNot(masm, &slow);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
-                                            Label* slow) {
-  EmitCheckForHeapNumber(masm, a0, a1, t2, slow);
-  // a0 is a heap number.  Get a new heap number in a1.
-  if (mode_ == UNARY_OVERWRITE) {
-    __ lw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset));
-    __ Xor(a2, a2, Operand(HeapNumber::kSignMask));  // Flip sign.
-    __ Ret(USE_DELAY_SLOT);
-    __ sw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset));
-  } else {
-    Label slow_allocate_heapnumber, heapnumber_allocated;
-    __ AllocateHeapNumber(a1, a2, a3, t2, &slow_allocate_heapnumber);
-    __ jmp(&heapnumber_allocated);
-
-    __ bind(&slow_allocate_heapnumber);
-    {
-      FrameScope scope(masm, StackFrame::INTERNAL);
-      __ push(a0);
-      __ CallRuntime(Runtime::kNumberAlloc, 0);
-      __ mov(a1, v0);
-      __ pop(a0);
-    }
-
-    __ bind(&heapnumber_allocated);
-    __ lw(a3, FieldMemOperand(a0, HeapNumber::kMantissaOffset));
-    __ lw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset));
-    __ sw(a3, FieldMemOperand(a1, HeapNumber::kMantissaOffset));
-    __ Xor(a2, a2, Operand(HeapNumber::kSignMask));  // Flip sign.
-    __ sw(a2, FieldMemOperand(a1, HeapNumber::kExponentOffset));
-    __ Ret(USE_DELAY_SLOT);
-    __ mov(v0, a1);
-  }
-}
-
-
-void UnaryOpStub::GenerateHeapNumberCodeBitNot(
-    MacroAssembler* masm,
-    Label* slow) {
-  Label impossible;
-
-  EmitCheckForHeapNumber(masm, a0, a1, t2, slow);
-  // Convert the heap number in a0 to an untagged integer in a1.
-  __ ConvertToInt32(a0, a1, a2, a3, f0, slow);
-
-  // Do the bitwise operation and check if the result fits in a smi.
-  Label try_float;
-  __ Neg(a1, a1);
-  __ Addu(a2, a1, Operand(0x40000000));
-  __ Branch(&try_float, lt, a2, Operand(zero_reg));
-
-  // Tag the result as a smi and we're done.
-  __ Ret(USE_DELAY_SLOT);  // SmiTag emits one instruction in delay slot.
-  __ SmiTag(v0, a1);
-
-  // Try to store the result in a heap number.
-  __ bind(&try_float);
-  if (mode_ == UNARY_NO_OVERWRITE) {
-    Label slow_allocate_heapnumber, heapnumber_allocated;
-    // Allocate a new heap number without zapping v0, which we need if it fails.
-    __ AllocateHeapNumber(a2, a3, t0, t2, &slow_allocate_heapnumber);
-    __ jmp(&heapnumber_allocated);
-
-    __ bind(&slow_allocate_heapnumber);
-    {
-      FrameScope scope(masm, StackFrame::INTERNAL);
-      __ push(v0);  // Push the heap number, not the untagged int32.
-      __ CallRuntime(Runtime::kNumberAlloc, 0);
-      __ mov(a2, v0);  // Move the new heap number into a2.
-      // Get the heap number into v0, now that the new heap number is in a2.
-      __ pop(v0);
-    }
-
-    // Convert the heap number in v0 to an untagged integer in a1.
-    // This can't go slow-case because it's the same number we already
-    // converted once again.
-    __ ConvertToInt32(v0, a1, a3, t0, f0, &impossible);
-    // Negate the result.
-    __ Xor(a1, a1, -1);
-
-    __ bind(&heapnumber_allocated);
-    __ mov(v0, a2);  // Move newly allocated heap number to v0.
-  }
-
-  // Convert the int32 in a1 to the heap number in v0. a2 is corrupted.
-  __ mtc1(a1, f0);
-  __ cvt_d_w(f0, f0);
-  __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset));
-  __ Ret();
-
-  __ bind(&impossible);
-  if (FLAG_debug_code) {
-    __ stop("Incorrect assumption in bit-not stub");
-  }
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateGenericStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateGenericStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeSub(masm, &non_smi, &slow);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeSub(masm, &slow);
-  __ bind(&slow);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeBitNot(masm, &non_smi);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeBitNot(masm, &slow);
-  __ bind(&slow);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateGenericCodeFallback(
-    MacroAssembler* masm) {
-  // Handle the slow case by jumping to the JavaScript builtin.
-  __ push(a0);
-  switch (op_) {
-    case Token::SUB:
-      __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
-      break;
-    case Token::BIT_NOT:
-      __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
 void BinaryOpStub::Initialize() {
   platform_specific_bit_ = true;  // FPU is a base requirement for V8.
 }
@@ -6815,6 +6550,7 @@
   GenerateMiss(masm);
 }
 
+
 void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
   {
     // Call the runtime system in a fresh internal frame.
@@ -7145,6 +6881,7 @@
   RememberedSetAction action;
 };
 
+
 #define REG(Name) { kRegister_ ## Name ## _Code }
 
 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
diff --git a/src/mips/code-stubs-mips.h b/src/mips/code-stubs-mips.h
index bf5db10..afef979 100644
--- a/src/mips/code-stubs-mips.h
+++ b/src/mips/code-stubs-mips.h
@@ -81,71 +81,6 @@
 };
 
 
-class UnaryOpStub: public PlatformCodeStub {
- public:
-  UnaryOpStub(Token::Value op,
-              UnaryOverwriteMode mode,
-              UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
-      : op_(op),
-        mode_(mode),
-        operand_type_(operand_type) {
-  }
-
- private:
-  Token::Value op_;
-  UnaryOverwriteMode mode_;
-
-  // Operand type information determined at runtime.
-  UnaryOpIC::TypeInfo operand_type_;
-
-  virtual void PrintName(StringStream* stream);
-
-  class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
-  class OpBits: public BitField<Token::Value, 1, 7> {};
-  class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
-
-  Major MajorKey() { return UnaryOp; }
-  int MinorKey() {
-    return ModeBits::encode(mode_)
-           | OpBits::encode(op_)
-           | OperandTypeInfoBits::encode(operand_type_);
-  }
-
-  // Note: A lot of the helper functions below will vanish when we use virtual
-  // function instead of switch more often.
-  void Generate(MacroAssembler* masm);
-
-  void GenerateTypeTransition(MacroAssembler* masm);
-
-  void GenerateSmiStub(MacroAssembler* masm);
-  void GenerateSmiStubSub(MacroAssembler* masm);
-  void GenerateSmiStubBitNot(MacroAssembler* masm);
-  void GenerateSmiCodeSub(MacroAssembler* masm, Label* non_smi, Label* slow);
-  void GenerateSmiCodeBitNot(MacroAssembler* masm, Label* slow);
-
-  void GenerateNumberStub(MacroAssembler* masm);
-  void GenerateNumberStubSub(MacroAssembler* masm);
-  void GenerateNumberStubBitNot(MacroAssembler* masm);
-  void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
-  void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
-
-  void GenerateGenericStub(MacroAssembler* masm);
-  void GenerateGenericStubSub(MacroAssembler* masm);
-  void GenerateGenericStubBitNot(MacroAssembler* masm);
-  void GenerateGenericCodeFallback(MacroAssembler* masm);
-
-  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
-
-  virtual InlineCacheState GetICState() {
-    return UnaryOpIC::ToState(operand_type_);
-  }
-
-  virtual void FinishCode(Handle<Code> code) {
-    code->set_unary_op_type(operand_type_);
-  }
-};
-
-
 class StringHelper : public AllStatic {
  public:
   // Generate code for copying characters using a simple loop. This should only
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index 7a95bc4..523e87c 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -120,6 +120,7 @@
   return &sqrt;
 }
 
+
 // -------------------------------------------------------------------------
 // Platform-specific RuntimeCallHelper functions.
 
@@ -136,6 +137,7 @@
   masm->set_has_frame(false);
 }
 
+
 // -------------------------------------------------------------------------
 // Code generators
 
diff --git a/src/mips/constants-mips.cc b/src/mips/constants-mips.cc
index a20ec54..2dd7a31 100644
--- a/src/mips/constants-mips.cc
+++ b/src/mips/constants-mips.cc
@@ -58,6 +58,7 @@
   "pc"
 };
 
+
 // List of alias names which can be used when referring to MIPS registers.
 const Registers::RegisterAlias Registers::aliases_[] = {
   {0, "zero"},
@@ -67,6 +68,7 @@
   {kInvalidRegister, NULL}
 };
 
+
 const char* Registers::Name(int reg) {
   const char* result;
   if ((0 <= reg) && (reg < kNumSimuRegisters)) {
@@ -106,11 +108,13 @@
   "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
 };
 
+
 // List of alias names which can be used when referring to MIPS registers.
 const FPURegisters::RegisterAlias FPURegisters::aliases_[] = {
   {kInvalidRegister, NULL}
 };
 
+
 const char* FPURegisters::Name(int creg) {
   const char* result;
   if ((0 <= creg) && (creg < kNumFPURegisters)) {
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 032c1f5..43325df 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -4400,10 +4400,7 @@
                                            const char* comment) {
   // TODO(svenpanne): Allowing format strings in Comment would be nice here...
   Comment cmt(masm_, comment);
-  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
-  UnaryOverwriteMode overwrite =
-      can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
-  UnaryOpStub stub(expr->op(), overwrite);
+  UnaryOpStub stub(expr->op());
   // GenericUnaryOpStub expects the argument to be in a0.
   VisitForAccumulatorValue(expr->expression());
   SetSourcePosition(expr->position());
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 8109e8a..5dad77e 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -1971,11 +1971,11 @@
 template<class InstrType>
 void LCodeGen::EmitBranch(InstrType instr,
                           Condition cc, Register src1, const Operand& src2) {
-  int right_block = instr->FalseDestination(chunk_);
   int left_block = instr->TrueDestination(chunk_);
+  int right_block = instr->FalseDestination(chunk_);
 
   int next_block = GetNextEmittedBlock();
-  if (right_block == left_block) {
+  if (right_block == left_block || cc == al) {
     EmitGoto(left_block);
   } else if (left_block == next_block) {
     __ Branch(chunk_->GetAssemblyLabel(right_block),
@@ -2015,6 +2015,25 @@
 }
 
 
+void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
+  Representation r = instr->hydrogen()->value()->representation();
+  if (r.IsSmiOrInteger32() || r.IsDouble()) {
+    EmitBranch(instr, al, zero_reg, Operand(zero_reg));
+  } else {
+    ASSERT(r.IsTagged());
+    Register reg = ToRegister(instr->value());
+    HType type = instr->hydrogen()->value()->type();
+    if (type.IsTaggedNumber()) {
+      EmitBranch(instr, al, zero_reg, Operand(zero_reg));
+    }
+    __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
+    __ lw(scratch0(), FieldMemOperand(reg, HeapObject::kMapOffset));
+    __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
+    EmitBranch(instr, eq, scratch0(), Operand(at));
+  }
+}
+
+
 void LCodeGen::DoBranch(LBranch* instr) {
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsInteger32() || r.IsSmi()) {
@@ -2183,7 +2202,7 @@
 }
 
 
-void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
+void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
   LOperand* left = instr->left();
   LOperand* right = instr->right();
   Condition cond = TokenToCondition(instr->op(), false);
@@ -3360,6 +3379,7 @@
   __ bind(&receiver_ok);
 }
 
+
 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
   Register receiver = ToRegister(instr->receiver());
   Register function = ToRegister(instr->function());
@@ -3886,6 +3906,7 @@
   __ sub_d(f0, f12, f14);
 }
 
+
 void LCodeGen::DoDeferredRandom(LRandom* instr) {
   __ PrepareCallCFunction(1, scratch0());
   __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
diff --git a/src/mips/lithium-gap-resolver-mips.cc b/src/mips/lithium-gap-resolver-mips.cc
index 23a8f32..9705e1f 100644
--- a/src/mips/lithium-gap-resolver-mips.cc
+++ b/src/mips/lithium-gap-resolver-mips.cc
@@ -222,7 +222,6 @@
       ASSERT(destination->IsStackSlot());
       __ sw(source_register, cgen_->ToMemOperand(destination));
     }
-
   } else if (source->IsStackSlot()) {
     MemOperand source_operand = cgen_->ToMemOperand(source);
     if (destination->IsRegister()) {
@@ -259,6 +258,10 @@
       } else {
         __ LoadObject(dst, cgen_->ToHandle(constant_source));
       }
+    } else if (source->IsDoubleRegister()) {
+      DoubleRegister result = cgen_->ToDoubleRegister(destination);
+      double v = cgen_->ToDouble(constant_source);
+      __ Move(result, v);
     } else {
       ASSERT(destination->IsStackSlot());
       ASSERT(!in_cycle_);  // Constant moves happen after all cycles are gone.
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 638eaa4..0a7fb44 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -186,7 +186,8 @@
   return new(zone()) LDebugBreak();
 }
 
-void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
+
+void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if ");
   left()->PrintTo(stream);
   stream->Add(" %s ", Token::String(op()));
@@ -1605,8 +1606,8 @@
 }
 
 
-LInstruction* LChunkBuilder::DoCompareIDAndBranch(
-    HCompareIDAndBranch* instr) {
+LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
+    HCompareNumericAndBranch* instr) {
   Representation r = instr->representation();
   if (r.IsSmiOrInteger32()) {
     ASSERT(instr->left()->representation().IsSmiOrInteger32());
@@ -1614,14 +1615,14 @@
         instr->right()->representation()));
     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
-    return new(zone()) LCmpIDAndBranch(left, right);
+    return new(zone()) LCompareNumericAndBranch(left, right);
   } else {
     ASSERT(r.IsDouble());
     ASSERT(instr->left()->representation().IsDouble());
     ASSERT(instr->right()->representation().IsDouble());
     LOperand* left = UseRegisterAtStart(instr->left());
     LOperand* right = UseRegisterAtStart(instr->right());
-    return new(zone()) LCmpIDAndBranch(left, right);
+    return new(zone()) LCompareNumericAndBranch(left, right);
   }
 }
 
@@ -1918,6 +1919,18 @@
 }
 
 
+LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return AssignEnvironment(new(zone()) LCheckSmi(value));
+}
+
+
+LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) {
+  return new(zone())
+    LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value()));
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LInstruction* result = new(zone()) LCheckInstanceType(value);
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index 06d30d0..751cb23 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -81,7 +81,7 @@
   V(ClampTToUint8)                              \
   V(ClassOfTestAndBranch)                       \
   V(CmpConstantEqAndBranch)                     \
-  V(CmpIDAndBranch)                             \
+  V(CompareNumericAndBranch)                    \
   V(CmpObjectEqAndBranch)                       \
   V(CmpMapAndBranch)                            \
   V(CmpT)                                       \
@@ -118,6 +118,7 @@
   V(IsConstructCallAndBranch)                   \
   V(IsObjectAndBranch)                          \
   V(IsStringAndBranch)                          \
+  V(IsNumberAndBranch)                          \
   V(IsSmiAndBranch)                             \
   V(IsUndetectableAndBranch)                    \
   V(Label)                                      \
@@ -711,9 +712,9 @@
 };
 
 
-class LCmpIDAndBranch: public LControlInstruction<2, 0> {
+class LCompareNumericAndBranch: public LControlInstruction<2, 0> {
  public:
-  LCmpIDAndBranch(LOperand* left, LOperand* right) {
+  LCompareNumericAndBranch(LOperand* left, LOperand* right) {
     inputs_[0] = left;
     inputs_[1] = right;
   }
@@ -721,8 +722,9 @@
   LOperand* left() { return inputs_[0]; }
   LOperand* right() { return inputs_[1]; }
 
-  DECLARE_CONCRETE_INSTRUCTION(CmpIDAndBranch, "cmp-id-and-branch")
-  DECLARE_HYDROGEN_ACCESSOR(CompareIDAndBranch)
+  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
+                               "compare-numeric-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
 
   Token::Value op() const { return hydrogen()->token(); }
   bool is_double() const {
@@ -919,6 +921,19 @@
 };
 
 
+class LIsNumberAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LIsNumberAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsNumberAndBranch, "is-number-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(IsNumberAndBranch)
+};
+
+
 class LIsStringAndBranch: public LControlInstruction<1, 1> {
  public:
   LIsStringAndBranch(LOperand* value, LOperand* temp) {
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 47e6ff9..95eafae 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -768,6 +768,7 @@
   }
 }
 
+
 //------------Pseudo-instructions-------------
 
 void MacroAssembler::li(Register rd, Operand j, LiFlags mode) {
@@ -1021,6 +1022,7 @@
   mtc1(t8, fd);
 }
 
+
 void MacroAssembler::Trunc_w_d(FPURegister fd, FPURegister fs) {
   if (kArchVariant == kLoongson && fd.is(fs)) {
     mfc1(t8, FPURegister::from_code(fs.code() + 1));
@@ -1031,6 +1033,7 @@
   }
 }
 
+
 void MacroAssembler::Round_w_d(FPURegister fd, FPURegister fs) {
   if (kArchVariant == kLoongson && fd.is(fs)) {
     mfc1(t8, FPURegister::from_code(fs.code() + 1));
@@ -2639,6 +2642,7 @@
     nop();
 }
 
+
 void MacroAssembler::DropAndRet(int drop) {
   Ret(USE_DELAY_SLOT);
   addiu(sp, sp, drop * kPointerSize);
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index c0c0e47..a7189c5 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -755,6 +755,7 @@
   VerifyPointer(construct_trap());
 }
 
+
 void JSArrayBuffer::JSArrayBufferVerify() {
   CHECK(IsJSArrayBuffer());
   JSObjectVerify();
@@ -875,6 +876,7 @@
   VerifyPointer(property_list());
 }
 
+
 void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
   CHECK(IsFunctionTemplateInfo());
   TemplateInfoVerify();
@@ -1070,6 +1072,7 @@
   number_of_slow_unused_elements_ = 0;
 }
 
+
 void JSObject::SpillInformation::Print() {
   PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index fe054da..61ae90e 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -3787,6 +3787,7 @@
          kind() == BINARY_OP_IC ||
          kind() == COMPARE_IC ||
          kind() == COMPARE_NIL_IC ||
+         kind() == STORE_IC ||
          kind() == LOAD_IC ||
          kind() == KEYED_LOAD_IC ||
          kind() == TO_BOOLEAN_IC);
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index f1616da..1fae69b 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -760,6 +760,7 @@
   "???", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 };
 
+
 void JSDate::JSDatePrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSDate");
   PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index cfb7d44..612f937 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -136,8 +136,8 @@
       map->GetHeap(),
       HeapObject::RawField(object,
           JSTypedArray::kWeakNextOffset + kPointerSize),
-      HeapObject::RawField(object, JSTypedArray::kSize));
-  return JSTypedArray::kSize;
+      HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields));
+  return JSTypedArray::kSizeWithInternalFields;
 }
 
 
@@ -152,8 +152,8 @@
       map->GetHeap(),
       HeapObject::RawField(object,
           JSDataView::kWeakNextOffset + kPointerSize),
-      HeapObject::RawField(object, JSDataView::kSize));
-  return JSDataView::kSize;
+      HeapObject::RawField(object, JSDataView::kSizeWithInternalFields));
+  return JSDataView::kSizeWithInternalFields;
 }
 
 
@@ -522,7 +522,7 @@
       map->GetHeap(),
       HeapObject::RawField(object,
         JSTypedArray::kWeakNextOffset + kPointerSize),
-      HeapObject::RawField(object, JSTypedArray::kSize));
+      HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields));
 }
 
 
@@ -537,7 +537,7 @@
       map->GetHeap(),
       HeapObject::RawField(object,
         JSDataView::kWeakNextOffset + kPointerSize),
-      HeapObject::RawField(object, JSDataView::kSize));
+      HeapObject::RawField(object, JSDataView::kSizeWithInternalFields));
 }
 
 
diff --git a/src/objects.cc b/src/objects.cc
index aa67876..2611b57 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -630,12 +630,23 @@
 }
 
 
-Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
+Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object,
+                                               LookupResult* result,
+                                               Handle<Object> value) {
+  CALL_HEAP_FUNCTION(object->GetIsolate(),
+                     object->SetNormalizedProperty(result, *value),
+                     Object);
+}
+
+
+MaybeObject* JSObject::SetNormalizedProperty(LookupResult* result,
+                                             Object* value) {
   ASSERT(!HasFastProperties());
   if (IsGlobalObject()) {
     PropertyCell* cell = PropertyCell::cast(
         property_dictionary()->ValueAt(result->GetDictionaryEntry()));
-    cell->set_value(value);
+    MaybeObject* maybe_type = cell->SetValueInferType(value);
+    if (maybe_type->IsFailure()) return maybe_type;
   } else {
     property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
   }
@@ -691,7 +702,8 @@
   if (IsGlobalObject()) {
     PropertyCell* cell =
         PropertyCell::cast(property_dictionary()->ValueAt(entry));
-    cell->set_value(value);
+    MaybeObject* maybe_type = cell->SetValueInferType(value);
+    if (maybe_type->IsFailure()) return maybe_type;
     // Please note we have to update the property details.
     property_dictionary()->DetailsAtPut(entry, details);
   } else {
@@ -723,7 +735,9 @@
         set_map(new_map);
       }
       PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
-      cell->set_value(cell->GetHeap()->the_hole_value());
+      MaybeObject* maybe_type =
+          cell->SetValueInferType(cell->GetHeap()->the_hole_value());
+      if (maybe_type->IsFailure()) return maybe_type;
       dictionary->DetailsAtPut(entry, details.AsDeleted());
     } else {
       Object* deleted = dictionary->DeleteProperty(entry, mode);
@@ -1930,7 +1944,9 @@
     int entry = dict->FindEntry(name);
     if (entry != NameDictionary::kNotFound) {
       store_value = dict->ValueAt(entry);
-      PropertyCell::cast(store_value)->set_value(value);
+      MaybeObject* maybe_type =
+          PropertyCell::cast(store_value)->SetValueInferType(value);
+      if (maybe_type->IsFailure()) return maybe_type;
       // Assign an enumeration index to the property and update
       // SetNextEnumerationIndex.
       int index = dict->NextEnumerationIndex();
@@ -1944,7 +1960,9 @@
           heap->AllocatePropertyCell(value);
       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
     }
-    PropertyCell::cast(store_value)->set_value(value);
+    MaybeObject* maybe_type =
+        PropertyCell::cast(store_value)->SetValueInferType(value);
+    if (maybe_type->IsFailure()) return maybe_type;
   }
   PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
   Object* result;
@@ -9961,22 +9979,26 @@
   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
 }
 
+
 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
   ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
   VisitPointer(rinfo->target_object_address());
 }
 
+
 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
   Address* p = rinfo->target_reference_address();
   VisitExternalReferences(p, p + 1);
 }
 
+
 byte Code::compare_nil_state() {
   ASSERT(is_compare_nil_ic_stub());
   return CompareNilICStub::ExtractTypesFromExtraICState(
       extended_extra_ic_state());
 }
 
+
 byte Code::compare_nil_value() {
   ASSERT(is_compare_nil_ic_stub());
   return CompareNilICStub::ExtractNilValueFromExtraICState(
@@ -10610,6 +10632,7 @@
 
 
 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
+  PrintF(out, "extra_ic_state = ");
   const char* name = NULL;
   switch (kind) {
     case CALL_IC:
@@ -10627,9 +10650,9 @@
       break;
   }
   if (name != NULL) {
-    PrintF(out, "extra_ic_state = %s\n", name);
+    PrintF(out, "%s\n", name);
   } else {
-    PrintF(out, "extra_ic_state = %d\n", extra);
+    PrintF(out, "%d\n", extra);
   }
 }
 
@@ -10638,7 +10661,8 @@
   PrintF(out, "kind = %s\n", Kind2String(kind()));
   if (is_inline_cache_stub()) {
     PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
-    PrintExtraICState(out, kind(), extra_ic_state());
+    PrintExtraICState(out, kind(), needs_extended_extra_ic_state(kind()) ?
+        extended_extra_ic_state() : extra_ic_state());
     if (ic_state() == MONOMORPHIC) {
       PrintF(out, "type = %s\n", StubType2String(type()));
     }
@@ -13299,6 +13323,7 @@
   Smi* flags_;
 };
 
+
 // Utf8StringKey carries a vector of chars as key.
 class Utf8StringKey : public HashTableKey {
  public:
@@ -13665,6 +13690,7 @@
   return entry;
 }
 
+
 // Force instantiation of template instances class.
 // Please note this list is compiler dependent.
 
@@ -14027,6 +14053,7 @@
   return result_double;
 }
 
+
 ExternalArrayType JSTypedArray::type() {
   switch (elements()->map()->instance_type()) {
     case EXTERNAL_BYTE_ARRAY_TYPE:
@@ -14241,39 +14268,36 @@
 }
 
 
-Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
-    Handle<GlobalObject> global,
-    Handle<Name> name) {
-  Isolate* isolate = global->GetIsolate();
-  CALL_HEAP_FUNCTION(isolate,
-                     global->EnsurePropertyCell(*name),
-                     PropertyCell);
+// TODO(mstarzinger): Temporary wrapper until handlified.
+static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict,
+                                                Handle<Name> name,
+                                                Handle<Object> value,
+                                                PropertyDetails details) {
+  CALL_HEAP_FUNCTION(dict->GetIsolate(),
+                     dict->Add(*name, *value, details),
+                     NameDictionary);
 }
 
 
-MaybeObject* GlobalObject::EnsurePropertyCell(Name* name) {
-  ASSERT(!HasFastProperties());
-  int entry = property_dictionary()->FindEntry(name);
+Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
+    Handle<GlobalObject> global,
+    Handle<Name> name) {
+  ASSERT(!global->HasFastProperties());
+  int entry = global->property_dictionary()->FindEntry(*name);
   if (entry == NameDictionary::kNotFound) {
-    Heap* heap = GetHeap();
-    Object* cell;
-    { MaybeObject* maybe_cell =
-          heap->AllocatePropertyCell(heap->the_hole_value());
-      if (!maybe_cell->ToObject(&cell)) return maybe_cell;
-    }
+    Isolate* isolate = global->GetIsolate();
+    Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(
+        isolate->factory()->the_hole_value());
     PropertyDetails details(NONE, NORMAL, 0);
     details = details.AsDeleted();
-    Object* dictionary;
-    { MaybeObject* maybe_dictionary =
-          property_dictionary()->Add(name, cell, details);
-      if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
-    }
-    set_properties(NameDictionary::cast(dictionary));
+    Handle<NameDictionary> dictionary = NameDictionaryAdd(
+        handle(global->property_dictionary()), name, cell, details);
+    global->set_properties(*dictionary);
     return cell;
   } else {
-    Object* value = property_dictionary()->ValueAt(entry);
+    Object* value = global->property_dictionary()->ValueAt(entry);
     ASSERT(value->IsPropertyCell());
-    return value;
+    return handle(PropertyCell::cast(value));
   }
 }
 
@@ -14406,6 +14430,7 @@
   return LookupKey(&key, s);
 }
 
+
 MaybeObject* StringTable::LookupKey(HashTableKey* key, Object** s) {
   int entry = FindEntry(key);
 
@@ -15802,10 +15827,51 @@
 
 
 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) {
+  ASSERT(IsPropertyCell());
   set_type_raw(type, ignored);
 }
 
 
+Type* PropertyCell::UpdateType(Handle<PropertyCell> cell,
+                               Handle<Object> value) {
+  Isolate* isolate = cell->GetIsolate();
+  Handle<Type> old_type(cell->type(), isolate);
+  Handle<Type> new_type((value->IsSmi() || value->IsUndefined())
+                        ? Type::Constant(value, isolate)
+                        : Type::Any(), isolate);
+
+  if (new_type->Is(old_type)) {
+    return *old_type;
+  }
+
+  cell->dependent_code()->DeoptimizeDependentCodeGroup(
+      isolate, DependentCode::kPropertyCellChangedGroup);
+
+  if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) {
+    return *new_type;
+  }
+
+  return Type::Any();
+}
+
+
+MaybeObject* PropertyCell::SetValueInferType(Object* value,
+                                             WriteBarrierMode ignored) {
+  set_value(value, ignored);
+  if (!Type::Any()->Is(type())) {
+    IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate());
+    MaybeObject* maybe_type = trampoline.CallWithReturnValue(
+        &PropertyCell::UpdateType,
+        Handle<PropertyCell>(this),
+        Handle<Object>(value, GetIsolate()));
+    if (maybe_type->IsFailure()) return maybe_type;
+    Type* new_type = static_cast<Type*>(maybe_type);
+    set_type(new_type);
+  }
+  return value;
+}
+
+
 void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) {
   Handle<DependentCode> dep(dependent_code());
   Handle<DependentCode> codes =
diff --git a/src/objects.h b/src/objects.h
index 416ed7f..eb6d882 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1886,9 +1886,16 @@
   // Handles the special representation of JS global objects.
   Object* GetNormalizedProperty(LookupResult* result);
 
+  // Sets the property value in a normalized object given (key, value).
+  // Handles the special representation of JS global objects.
+  static Handle<Object> SetNormalizedProperty(Handle<JSObject> object,
+                                              LookupResult* result,
+                                              Handle<Object> value);
+
   // Sets the property value in a normalized object given a lookup result.
   // Handles the special representation of JS global objects.
-  Object* SetNormalizedProperty(LookupResult* result, Object* value);
+  MUST_USE_RESULT MaybeObject* SetNormalizedProperty(LookupResult* result,
+                                                     Object* value);
 
   // Sets the property value in a normalized object given (key, value, details).
   // Handles the special representation of JS global objects.
@@ -4567,7 +4574,8 @@
     // 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;
+    return kind == COMPARE_NIL_IC || kind == TO_BOOLEAN_IC ||
+           kind == UNARY_OP_IC;
   }
 
   inline StubType type();  // Only valid for monomorphic IC stubs.
@@ -6819,12 +6827,8 @@
   }
 
   // Ensure that the global object has a cell for the given property name.
-  static Handle<PropertyCell> EnsurePropertyCell(
-      Handle<GlobalObject> global,
-      Handle<Name> name);
-  // TODO(kmillikin): This function can be eliminated once the stub cache is
-  // fully handlified (and the static helper can be written directly).
-  MUST_USE_RESULT MaybeObject* EnsurePropertyCell(Name* name);
+  static Handle<PropertyCell> EnsurePropertyCell(Handle<GlobalObject> global,
+                                                 Handle<Name> name);
 
   // Casting.
   static inline GlobalObject* cast(Object* obj);
@@ -8586,6 +8590,14 @@
   // property.
   DECL_ACCESSORS(dependent_code, DependentCode)
 
+  // Sets the value of the cell and updates the type field to be the union
+  // of the cell's current type and the value's type. If the change causes
+  // a change of the type of the cell's contents, code dependent on the cell
+  // will be deoptimized.
+  MUST_USE_RESULT MaybeObject* SetValueInferType(
+      Object* value,
+      WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
+
   // Casting.
   static inline PropertyCell* cast(Object* obj);
 
@@ -8613,6 +8625,9 @@
 
   void AddDependentCode(Handle<Code> code);
 
+  static Type* UpdateType(Handle<PropertyCell> cell,
+                          Handle<Object> value);
+
  private:
   DECL_ACCESSORS(type_raw, Object)
   DISALLOW_IMPLICIT_CONSTRUCTORS(PropertyCell);
@@ -8921,6 +8936,9 @@
   static const int kLengthOffset = kViewSize + kPointerSize;
   static const int kSize = kLengthOffset + kPointerSize;
 
+  static const int kSizeWithInternalFields =
+      kSize + v8::ArrayBufferView::kInternalFieldCount * kPointerSize;
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSTypedArray);
 };
@@ -8940,6 +8958,9 @@
 
   static const int kSize = kViewSize;
 
+  static const int kSizeWithInternalFields =
+      kSize + v8::ArrayBufferView::kInternalFieldCount * kPointerSize;
+
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSDataView);
 };
diff --git a/src/parser.cc b/src/parser.cc
index b320299..ca2d022 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -371,6 +371,7 @@
   return result;
 }
 
+
 Scanner::Location ScriptDataImpl::MessageLocation() {
   int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
   int end_pos = Read(PreparseDataConstants::kMessageEndPos);
@@ -3769,6 +3770,7 @@
   return isolate()->factory()->uninitialized_value();
 }
 
+
 // Validation per 11.1.5 Object Initialiser
 class ObjectLiteralPropertyChecker {
  public:
@@ -4962,6 +4964,7 @@
   return factory()->NewThrow(call_constructor, scanner().location().beg_pos);
 }
 
+
 // ----------------------------------------------------------------------------
 // Regular expressions
 
@@ -5032,6 +5035,7 @@
   return simple_;
 }
 
+
 RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
   failed_ = true;
   *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc
index bda9f92..7c3da1b 100644
--- a/src/platform-cygwin.cc
+++ b/src/platform-cygwin.cc
@@ -67,6 +67,7 @@
   POSIXPostSetUp();
 }
 
+
 uint64_t OS::CpuFeaturesImpliedByPlatform() {
   return 0;  // Nothing special about Cygwin.
 }
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index 21e9c7f..f4d8b33 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -596,6 +596,7 @@
   Release_Store(&tls_base_offset_initialized, 1);
 }
 
+
 static void CheckFastTls(Thread::LocalStorageKey key) {
   void* expected = reinterpret_cast<void*>(0x1234CAFE);
   Thread::SetThreadLocal(key, expected);
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index b722e31..f849d58 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -720,6 +720,7 @@
   }
 }
 
+
 Semaphore* OS::CreateSemaphore(int count) {
   return new OpenBSDSemaphore(count);
 }
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index e72a5d9..6e83b04 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -326,6 +326,7 @@
   memmove(dest, src, size);
 }
 
+
 // Initialize to library version so we can call this at any time during startup.
 static OS::MemMoveFunction memmove_function = &MemMoveWrapper;
 
@@ -358,6 +359,7 @@
   init_fast_sqrt_function();
 }
 
+
 // ----------------------------------------------------------------------------
 // POSIX string support.
 //
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 1913760..80bcaf9 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -152,6 +152,7 @@
   memmove(dest, src, size);
 }
 
+
 // Initialize to library version so we can call this at any time during startup.
 static OS::MemMoveFunction memmove_function = &MemMoveWrapper;
 
@@ -178,6 +179,7 @@
   modulo_function = CreateModuloFunction();
 }
 
+
 double modulo(double x, double y) {
   // Note: here we rely on dependent reads being ordered. This is true
   // on all architectures we currently support.
@@ -321,6 +323,7 @@
   TimeStamp time_;
 };
 
+
 // Static variables.
 bool Time::tz_initialized_ = false;
 TIME_ZONE_INFORMATION Time::tzinfo_;
@@ -616,6 +619,7 @@
   return t.ToJSTime();
 }
 
+
 // Returns the tickcounter based on timeGetTime.
 int64_t OS::Ticks() {
   return timeGetTime() * 1000;  // Convert to microseconds.
@@ -1449,6 +1453,7 @@
   return frames_count;
 }
 
+
 // Restore warnings to previous settings.
 #pragma warning(pop)
 
@@ -1479,6 +1484,10 @@
 int OS::ActivationFrameAlignment() {
 #ifdef _WIN64
   return 16;  // Windows 64-bit ABI requires the stack to be 16-byte aligned.
+#elif defined(__MINGW32__)
+  // With gcc 4.4 the tree vectorization optimizer can generate code
+  // that requires 16 byte alignment such as movdqa on x86.
+  return 16;
 #else
   return 8;  // Floating-point math runs faster with 8-byte alignment.
 #endif
diff --git a/src/preparse-data.cc b/src/preparse-data.cc
index 287ad66..8e08848 100644
--- a/src/preparse-data.cc
+++ b/src/preparse-data.cc
@@ -86,6 +86,7 @@
   }
 }
 
+
 // ----------------------------------------------------------------------------
 // PartialParserRecorder -  Record both function entries and symbols.
 
diff --git a/src/preparser.cc b/src/preparser.cc
index 3268e3c..fe37cfa 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -1685,6 +1685,7 @@
   return result;
 }
 
+
 bool PreParser::peek_any_identifier() {
   i::Token::Value next = peek();
   return next == i::Token::IDENTIFIER ||
@@ -1698,6 +1699,7 @@
   return AddSymbol(i::Vector<const byte>::cast(key), true, value);
 }
 
+
 int DuplicateFinder::AddUtf16Symbol(i::Vector<const uint16_t> key, int value) {
   return AddSymbol(i::Vector<const byte>::cast(key), false, value);
 }
diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h
index 20c1aec..d92085a 100644
--- a/src/profile-generator-inl.h
+++ b/src/profile-generator-inl.h
@@ -45,7 +45,6 @@
 
 CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
                      const char* name,
-                     int security_token_id,
                      const char* name_prefix,
                      const char* resource_name,
                      int line_number)
@@ -57,7 +56,6 @@
       line_number_(line_number),
       shared_id_(0),
       script_id_(v8::Script::kNoScriptId),
-      security_token_id_(security_token_id),
       no_frame_ranges_(NULL) {
 }
 
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 78b05c5..cc86724 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -41,60 +41,6 @@
 namespace internal {
 
 
-TokenEnumerator::TokenEnumerator()
-    : token_locations_(4),
-      token_removed_(4) {
-}
-
-
-TokenEnumerator::~TokenEnumerator() {
-  Isolate* isolate = Isolate::Current();
-  for (int i = 0; i < token_locations_.length(); ++i) {
-    if (!token_removed_[i]) {
-      isolate->global_handles()->ClearWeakness(token_locations_[i]);
-      isolate->global_handles()->Destroy(token_locations_[i]);
-    }
-  }
-}
-
-
-int TokenEnumerator::GetTokenId(Object* token) {
-  Isolate* isolate = Isolate::Current();
-  if (token == NULL) return TokenEnumerator::kNoSecurityToken;
-  for (int i = 0; i < token_locations_.length(); ++i) {
-    if (*token_locations_[i] == token && !token_removed_[i]) return i;
-  }
-  Handle<Object> handle = isolate->global_handles()->Create(token);
-  // handle.location() points to a memory cell holding a pointer
-  // to a token object in the V8's heap.
-  isolate->global_handles()->MakeWeak(handle.location(),
-                                      this,
-                                      TokenRemovedCallback);
-  token_locations_.Add(handle.location());
-  token_removed_.Add(false);
-  return token_locations_.length() - 1;
-}
-
-
-void TokenEnumerator::TokenRemovedCallback(v8::Isolate* isolate,
-                                           v8::Persistent<v8::Value>* handle,
-                                           void* parameter) {
-  reinterpret_cast<TokenEnumerator*>(parameter)->TokenRemoved(
-      Utils::OpenPersistent(handle).location());
-  handle->Dispose(isolate);
-}
-
-
-void TokenEnumerator::TokenRemoved(Object** token_location) {
-  for (int i = 0; i < token_locations_.length(); ++i) {
-    if (token_locations_[i] == token_location && !token_removed_[i]) {
-      token_removed_[i] = true;
-      return;
-    }
-  }
-}
-
-
 StringsStorage::StringsStorage()
     : names_(StringsMatch) {
 }
@@ -274,12 +220,11 @@
 
 
 void ProfileNode::Print(int indent) {
-  OS::Print("%5u %5u %*c %s%s [%d] #%d %d",
+  OS::Print("%5u %5u %*c %s%s #%d %d",
             total_ticks_, self_ticks_,
             indent, ' ',
             entry_->name_prefix(),
             entry_->name(),
-            entry_->security_token_id(),
             entry_->script_id(),
             id());
   if (entry_->resource_name()[0] != '\0')
@@ -353,58 +298,6 @@
 };
 
 
-class FilteredCloneCallback {
- public:
-  FilteredCloneCallback(ProfileNode* dst_root, int security_token_id)
-      : stack_(10),
-        security_token_id_(security_token_id) {
-    stack_.Add(NodesPair(NULL, dst_root));
-  }
-
-  void BeforeTraversingChild(ProfileNode* parent, ProfileNode* child) {
-    if (IsTokenAcceptable(child->entry()->security_token_id(),
-                          parent->entry()->security_token_id())) {
-      ProfileNode* clone = stack_.last().dst->FindOrAddChild(child->entry());
-      clone->IncreaseSelfTicks(child->self_ticks());
-      stack_.Add(NodesPair(child, clone));
-    } else {
-      // Attribute ticks to parent node.
-      stack_.last().dst->IncreaseSelfTicks(child->self_ticks());
-    }
-  }
-
-  void AfterAllChildrenTraversed(ProfileNode* parent) { }
-
-  void AfterChildTraversed(ProfileNode*, ProfileNode* child) {
-    if (stack_.last().src == child) {
-      stack_.RemoveLast();
-    }
-  }
-
- private:
-  bool IsTokenAcceptable(int token, int parent_token) {
-    if (token == TokenEnumerator::kNoSecurityToken
-        || token == security_token_id_) return true;
-    if (token == TokenEnumerator::kInheritsSecurityToken) {
-      ASSERT(parent_token != TokenEnumerator::kInheritsSecurityToken);
-      return parent_token == TokenEnumerator::kNoSecurityToken
-          || parent_token == security_token_id_;
-    }
-    return false;
-  }
-
-  List<NodesPair> stack_;
-  int security_token_id_;
-};
-
-void ProfileTree::FilteredClone(ProfileTree* src, int security_token_id) {
-  ms_to_ticks_scale_ = src->ms_to_ticks_scale_;
-  FilteredCloneCallback cb(root_, security_token_id);
-  src->TraverseDepthFirst(&cb);
-  CalculateTotalTicks();
-}
-
-
 void ProfileTree::SetTickRatePerMs(double ticks_per_ms) {
   ms_to_ticks_scale_ = ticks_per_ms > 0 ? 1.0 / ticks_per_ms : 1.0;
 }
@@ -495,14 +388,6 @@
 }
 
 
-CpuProfile* CpuProfile::FilteredClone(int security_token_id) {
-  ASSERT(security_token_id != TokenEnumerator::kNoSecurityToken);
-  CpuProfile* clone = new CpuProfile(title_, uid_, false);
-  clone->top_down_.FilteredClone(&top_down_, security_token_id);
-  return clone;
-}
-
-
 void CpuProfile::ShortPrint() {
   OS::Print("top down ");
   top_down_.ShortPrint();
@@ -601,10 +486,7 @@
 
 
 CpuProfilesCollection::CpuProfilesCollection()
-    : profiles_uids_(UidsMatch),
-      current_profiles_semaphore_(OS::CreateSemaphore(1)) {
-  // Create list of unabridged profiles.
-  profiles_by_token_.Add(new List<CpuProfile*>());
+    : current_profiles_semaphore_(OS::CreateSemaphore(1)) {
 }
 
 
@@ -612,22 +494,16 @@
   delete *entry_ptr;
 }
 
+
 static void DeleteCpuProfile(CpuProfile** profile_ptr) {
   delete *profile_ptr;
 }
 
-static void DeleteProfilesList(List<CpuProfile*>** list_ptr) {
-  if (*list_ptr != NULL) {
-    (*list_ptr)->Iterate(DeleteCpuProfile);
-    delete *list_ptr;
-  }
-}
 
 CpuProfilesCollection::~CpuProfilesCollection() {
   delete current_profiles_semaphore_;
+  finished_profiles_.Iterate(DeleteCpuProfile);
   current_profiles_.Iterate(DeleteCpuProfile);
-  detached_profiles_.Iterate(DeleteCpuProfile);
-  profiles_by_token_.Iterate(DeleteProfilesList);
   code_entries_.Iterate(DeleteCodeEntry);
 }
 
@@ -653,8 +529,7 @@
 }
 
 
-CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id,
-                                                 const char* title,
+CpuProfile* CpuProfilesCollection::StopProfiling(const char* title,
                                                  double actual_sampling_rate) {
   const int title_len = StrLength(title);
   CpuProfile* profile = NULL;
@@ -667,48 +542,11 @@
   }
   current_profiles_semaphore_->Signal();
 
-  if (profile != NULL) {
-    profile->CalculateTotalTicks();
-    profile->SetActualSamplingRate(actual_sampling_rate);
-    List<CpuProfile*>* unabridged_list =
-        profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
-    unabridged_list->Add(profile);
-    HashMap::Entry* entry =
-        profiles_uids_.Lookup(reinterpret_cast<void*>(profile->uid()),
-                              static_cast<uint32_t>(profile->uid()),
-                              true);
-    ASSERT(entry->value == NULL);
-    entry->value = reinterpret_cast<void*>(unabridged_list->length() - 1);
-    return GetProfile(security_token_id, profile->uid());
-  }
-  return NULL;
-}
-
-
-CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id,
-                                              unsigned uid) {
-  int index = GetProfileIndex(uid);
-  if (index < 0) return NULL;
-  List<CpuProfile*>* unabridged_list =
-      profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
-  if (security_token_id == TokenEnumerator::kNoSecurityToken) {
-    return unabridged_list->at(index);
-  }
-  List<CpuProfile*>* list = GetProfilesList(security_token_id);
-  if (list->at(index) == NULL) {
-    (*list)[index] =
-        unabridged_list->at(index)->FilteredClone(security_token_id);
-  }
-  return list->at(index);
-}
-
-
-int CpuProfilesCollection::GetProfileIndex(unsigned uid) {
-  HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
-                                                static_cast<uint32_t>(uid),
-                                                false);
-  return entry != NULL ?
-      static_cast<int>(reinterpret_cast<intptr_t>(entry->value)) : -1;
+  if (profile == NULL) return NULL;
+  profile->CalculateTotalTicks();
+  profile->SetActualSamplingRate(actual_sampling_rate);
+  finished_profiles_.Add(profile);
+  return profile;
 }
 
 
@@ -724,74 +562,13 @@
 void CpuProfilesCollection::RemoveProfile(CpuProfile* profile) {
   // Called from VM thread for a completed profile.
   unsigned uid = profile->uid();
-  int index = GetProfileIndex(uid);
-  if (index < 0) {
-    detached_profiles_.RemoveElement(profile);
-    return;
-  }
-  profiles_uids_.Remove(reinterpret_cast<void*>(uid),
-                        static_cast<uint32_t>(uid));
-  // Decrement all indexes above the deleted one.
-  for (HashMap::Entry* p = profiles_uids_.Start();
-       p != NULL;
-       p = profiles_uids_.Next(p)) {
-    intptr_t p_index = reinterpret_cast<intptr_t>(p->value);
-    if (p_index > index) {
-      p->value = reinterpret_cast<void*>(p_index - 1);
+  for (int i = 0; i < finished_profiles_.length(); i++) {
+    if (uid == finished_profiles_[i]->uid()) {
+      finished_profiles_.Remove(i);
+      return;
     }
   }
-  for (int i = 0; i < profiles_by_token_.length(); ++i) {
-    List<CpuProfile*>* list = profiles_by_token_[i];
-    if (list != NULL && index < list->length()) {
-      // Move all filtered clones into detached_profiles_,
-      // so we can know that they are still in use.
-      CpuProfile* cloned_profile = list->Remove(index);
-      if (cloned_profile != NULL && cloned_profile != profile) {
-        detached_profiles_.Add(cloned_profile);
-      }
-    }
-  }
-}
-
-
-int CpuProfilesCollection::TokenToIndex(int security_token_id) {
-  ASSERT(TokenEnumerator::kNoSecurityToken == -1);
-  return security_token_id + 1;  // kNoSecurityToken -> 0, 0 -> 1, ...
-}
-
-
-List<CpuProfile*>* CpuProfilesCollection::GetProfilesList(
-    int security_token_id) {
-  const int index = TokenToIndex(security_token_id);
-  const int lists_to_add = index - profiles_by_token_.length() + 1;
-  if (lists_to_add > 0) profiles_by_token_.AddBlock(NULL, lists_to_add);
-  List<CpuProfile*>* unabridged_list =
-      profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
-  const int current_count = unabridged_list->length();
-  if (profiles_by_token_[index] == NULL) {
-    profiles_by_token_[index] = new List<CpuProfile*>(current_count);
-  }
-  List<CpuProfile*>* list = profiles_by_token_[index];
-  const int profiles_to_add = current_count - list->length();
-  if (profiles_to_add > 0) list->AddBlock(NULL, profiles_to_add);
-  return list;
-}
-
-
-List<CpuProfile*>* CpuProfilesCollection::Profiles(int security_token_id) {
-  List<CpuProfile*>* unabridged_list =
-      profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
-  if (security_token_id == TokenEnumerator::kNoSecurityToken) {
-    return unabridged_list;
-  }
-  List<CpuProfile*>* list = GetProfilesList(security_token_id);
-  const int current_count = unabridged_list->length();
-  for (int i = 0; i < current_count; ++i) {
-    if (list->at(i) == NULL) {
-      (*list)[i] = unabridged_list->at(i)->FilteredClone(security_token_id);
-    }
-  }
-  return list;
+  UNREACHABLE();
 }
 
 
@@ -811,13 +588,11 @@
 CodeEntry* CpuProfilesCollection::NewCodeEntry(
       Logger::LogEventsAndTags tag,
       const char* name,
-      int security_token_id,
       const char* name_prefix,
       const char* resource_name,
       int line_number) {
   CodeEntry* code_entry = new CodeEntry(tag,
                                         name,
-                                        security_token_id,
                                         name_prefix,
                                         resource_name,
                                         line_number);
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 411cbdb..6b02368 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -37,30 +37,6 @@
 
 struct OffsetRange;
 
-class TokenEnumerator {
- public:
-  TokenEnumerator();
-  ~TokenEnumerator();
-  int GetTokenId(Object* token);
-
-  static const int kNoSecurityToken = -1;
-  static const int kInheritsSecurityToken = -2;
-
- private:
-  static void TokenRemovedCallback(v8::Isolate* isolate,
-                                   v8::Persistent<v8::Value>* handle,
-                                   void* parameter);
-  void TokenRemoved(Object** token_location);
-
-  List<Object**> token_locations_;
-  List<bool> token_removed_;
-
-  friend class TokenEnumeratorTester;
-
-  DISALLOW_COPY_AND_ASSIGN(TokenEnumerator);
-};
-
-
 // Provides a storage of strings allocated in C++ heap, to hold them
 // forever, even if they disappear from JS heap or external storage.
 class StringsStorage {
@@ -98,7 +74,6 @@
   // CodeEntry doesn't own name strings, just references them.
   INLINE(CodeEntry(Logger::LogEventsAndTags tag,
                    const char* name,
-                   int security_token_id = TokenEnumerator::kNoSecurityToken,
                    const char* name_prefix = CodeEntry::kEmptyNamePrefix,
                    const char* resource_name = CodeEntry::kEmptyResourceName,
                    int line_number = v8::CpuProfileNode::kNoLineNumberInfo));
@@ -113,7 +88,6 @@
   INLINE(void set_shared_id(int shared_id)) { shared_id_ = shared_id; }
   INLINE(int script_id() const) { return script_id_; }
   INLINE(void set_script_id(int script_id)) { script_id_ = script_id; }
-  INLINE(int security_token_id() const) { return security_token_id_; }
 
   INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag));
 
@@ -141,7 +115,6 @@
   int line_number_;
   int shared_id_;
   int script_id_;
-  int security_token_id_;
   List<OffsetRange>* no_frame_ranges_;
 
   DISALLOW_COPY_AND_ASSIGN(CodeEntry);
@@ -201,7 +174,6 @@
   ProfileNode* AddPathFromEnd(const Vector<CodeEntry*>& path);
   void AddPathFromStart(const Vector<CodeEntry*>& path);
   void CalculateTotalTicks();
-  void FilteredClone(ProfileTree* src, int security_token_id);
 
   double TicksToMillis(unsigned ticks) const {
     return ticks * ms_to_ticks_scale_;
@@ -238,7 +210,6 @@
   void AddPath(const Vector<CodeEntry*>& path);
   void CalculateTotalTicks();
   void SetActualSamplingRate(double actual_sampling_rate);
-  CpuProfile* FilteredClone(int security_token_id);
 
   INLINE(const char* title() const) { return title_; }
   INLINE(unsigned uid() const) { return uid_; }
@@ -315,10 +286,8 @@
   ~CpuProfilesCollection();
 
   bool StartProfiling(const char* title, unsigned uid, bool record_samples);
-  CpuProfile* StopProfiling(int security_token_id,
-                            const char* title,
-                            double actual_sampling_rate);
-  List<CpuProfile*>* Profiles(int security_token_id);
+  CpuProfile* StopProfiling(const char* title, double actual_sampling_rate);
+  List<CpuProfile*>* profiles() { return &finished_profiles_; }
   const char* GetName(Name* name) {
     return function_and_resource_names_.GetName(name);
   }
@@ -331,15 +300,12 @@
   const char* GetFunctionName(const char* name) {
     return function_and_resource_names_.GetFunctionName(name);
   }
-  CpuProfile* GetProfile(int security_token_id, unsigned uid);
   bool IsLastProfile(const char* title);
   void RemoveProfile(CpuProfile* profile);
-  bool HasDetachedProfiles() { return detached_profiles_.length() > 0; }
 
   CodeEntry* NewCodeEntry(
       Logger::LogEventsAndTags tag,
       const char* name,
-      int security_token_id = TokenEnumerator::kNoSecurityToken,
       const char* name_prefix = CodeEntry::kEmptyNamePrefix,
       const char* resource_name = CodeEntry::kEmptyResourceName,
       int line_number = v8::CpuProfileNode::kNoLineNumberInfo);
@@ -351,21 +317,9 @@
   static const int kMaxSimultaneousProfiles = 100;
 
  private:
-  int GetProfileIndex(unsigned uid);
-  List<CpuProfile*>* GetProfilesList(int security_token_id);
-  int TokenToIndex(int security_token_id);
-
-  INLINE(static bool UidsMatch(void* key1, void* key2)) {
-    return key1 == key2;
-  }
-
   StringsStorage function_and_resource_names_;
   List<CodeEntry*> code_entries_;
-  List<List<CpuProfile*>* > profiles_by_token_;
-  // Mapping from profiles' uids to indexes in the second nested list
-  // of profiles_by_token_.
-  HashMap profiles_uids_;
-  List<CpuProfile*> detached_profiles_;
+  List<CpuProfile*> finished_profiles_;
 
   // Accessed by VM thread and profile generator thread.
   List<CpuProfile*> current_profiles_;
diff --git a/src/property-details.h b/src/property-details.h
index b0d10e1..ac36563 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -55,6 +55,8 @@
 namespace internal {
 
 class Smi;
+class Type;
+class TypeInfo;
 
 // Type of properties.
 // Order of properties is significant.
@@ -101,6 +103,10 @@
 
   static Representation FromKind(Kind kind) { return Representation(kind); }
 
+  // TODO(rossberg): this should die eventually.
+  static Representation FromType(TypeInfo info);
+  static Representation FromType(Handle<Type> type);
+
   bool Equals(const Representation& other) const {
     return kind_ == other.kind_;
   }
diff --git a/src/runtime.cc b/src/runtime.cc
index e3ee6d5..81018fe 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -467,7 +467,7 @@
                                                  constant_properties,
                                                  should_have_fast_elements,
                                                  has_function_literal);
-    if (boilerplate.is_null()) return Failure::Exception();
+    RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
     // Update the functions literal and return the boilerplate.
     literals->set(literals_index, *boilerplate);
   }
@@ -493,7 +493,7 @@
                                                  constant_properties,
                                                  should_have_fast_elements,
                                                  has_function_literal);
-    if (boilerplate.is_null()) return Failure::Exception();
+    RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
     // Update the functions literal and return the boilerplate.
     literals->set(literals_index, *boilerplate);
   }
@@ -514,7 +514,7 @@
     ASSERT(*elements != isolate->heap()->empty_fixed_array());
     boilerplate =
         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
-    if (boilerplate.is_null()) return Failure::Exception();
+    RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
     // Update the functions literal and return the boilerplate.
     literals->set(literals_index, *boilerplate);
   }
@@ -535,7 +535,7 @@
     ASSERT(*elements != isolate->heap()->empty_fixed_array());
     boilerplate =
         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
-    if (boilerplate.is_null()) return Failure::Exception();
+    RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
     // Update the functions literal and return the boilerplate.
     literals->set(literals_index, *boilerplate);
   }
@@ -796,6 +796,12 @@
   CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
   CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
 
+  ASSERT(holder->GetInternalFieldCount() ==
+      v8::ArrayBufferView::kInternalFieldCount);
+  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
+    holder->SetInternalField(i, Smi::FromInt(0));
+  }
+
   ExternalArrayType arrayType;
   size_t elementSize;
   switch (arrayId) {
@@ -1012,6 +1018,12 @@
   CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
   CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
 
+  ASSERT(holder->GetInternalFieldCount() ==
+      v8::ArrayBufferView::kInternalFieldCount);
+  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
+    holder->SetInternalField(i, Smi::FromInt(0));
+  }
+
   holder->set_buffer(*buffer);
   ASSERT(byte_offset->IsNumber());
   ASSERT(
@@ -1460,7 +1472,7 @@
         GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
 
     Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
-    if (result.is_null()) return Failure::Exception();
+    RETURN_IF_EMPTY_HANDLE(isolate, result);
 
     Handle<Object> new_value(
         GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
@@ -1472,7 +1484,7 @@
     return *result;
   }
   Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
-  if (result.is_null()) return Failure::Exception();
+  RETURN_IF_EMPTY_HANDLE(isolate, result);
   return *result;
 }
 
@@ -1635,7 +1647,7 @@
     elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
     // GetProperty does access check.
     Handle<Object> value = GetProperty(isolate, obj, name);
-    if (value.is_null()) return Failure::Exception();
+    RETURN_IF_EMPTY_HANDLE(isolate, value);
     elms->set(VALUE_INDEX, *value);
   } else {
     // Access checks are performed for both accessors separately.
@@ -1700,7 +1712,7 @@
   CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
   Handle<Object> result =
       RegExpImpl::Compile(re, pattern, flags);
-  if (result.is_null()) return Failure::Exception();
+  RETURN_IF_EMPTY_HANDLE(isolate, result);
   return *result;
 }
 
@@ -2109,7 +2121,8 @@
   } else if (lookup.IsNormal()) {
     if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
         !lookup.IsReadOnly()) {
-      global->SetNormalizedProperty(&lookup, *value);
+      HandleScope scope(isolate);
+      JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
     }
   } else {
     // Ignore re-initialization of constants that have already been
@@ -2198,7 +2211,7 @@
       }
     } else if (lookup.IsNormal()) {
       if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
-        object->SetNormalizedProperty(&lookup, *value);
+        JSObject::SetNormalizedProperty(object, &lookup, value);
       }
     } else {
       // We should not reach here. Any real, named property should be
@@ -2250,7 +2263,7 @@
                                            subject,
                                            index,
                                            last_match_info);
-  if (result.is_null()) return Failure::Exception();
+  RETURN_IF_EMPTY_HANDLE(isolate, result);
   return *result;
 }
 
@@ -4068,6 +4081,7 @@
   return -1;
 }
 
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
   HandleScope scope(isolate);
   ASSERT(args.length() == 3);
@@ -4789,6 +4803,7 @@
   return isolate->heap()->undefined_value();
 }
 
+
 // Implements part of 8.12.9 DefineOwnProperty.
 // There are 3 cases that lead here:
 // Step 4a - define a new data property.
@@ -7463,6 +7478,7 @@
   return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
 }
 
+
 // Slow version of Math.pow.  We check for fast paths for special cases.
 // Used if SSE2/VFP3 is not available.
 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
@@ -7485,6 +7501,7 @@
   return isolate->heap()->AllocateHeapNumber(result);
 }
 
+
 // Fast version of Math.pow if we know that y is not an integer and y is not
 // -0.5 or 0.5.  Used as slow case from full codegen.
 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
@@ -8852,6 +8869,7 @@
   MaybeObject* y;
 };
 
+
 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
   ObjectPair result = {x, y};
   // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
@@ -9377,7 +9395,7 @@
       ? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
       source, context, true, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
-  if (shared.is_null()) return Failure::Exception();
+  RETURN_IF_EMPTY_HANDLE(isolate, shared);
   Handle<JSFunction> fun =
       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
                                                             context,
@@ -9414,7 +9432,8 @@
       language_mode,
       NO_PARSE_RESTRICTION,
       scope_position);
-  if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
+  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, shared,
+                               MakePair(Failure::Exception(), NULL));
   Handle<JSFunction> compiled =
       isolate->factory()->NewFunctionFromSharedFunctionInfo(
           shared, context, NOT_TENURED);
@@ -10233,6 +10252,7 @@
   return string;
 }
 
+
 // Moves all own elements of an object, that are below a limit, to positions
 // starting at zero. All undefined values are placed after non-undefined values,
 // and are followed by non-existing element. Does not change the length
@@ -11850,6 +11870,7 @@
   return *isolate->factory()->NewJSArrayWithElements(details);
 }
 
+
 // Return an array with scope details
 // args[0]: number: break id
 // args[1]: number: frame index
@@ -12414,7 +12435,7 @@
       CLASSIC_MODE,
       NO_PARSE_RESTRICTION,
       RelocInfo::kNoPosition);
-  if (shared.is_null()) return Failure::Exception();
+  RETURN_IF_EMPTY_HANDLE(isolate, shared);
 
   Handle<JSFunction> eval_fun =
       isolate->factory()->NewFunctionFromSharedFunctionInfo(
@@ -12956,6 +12977,7 @@
   return counter;
 }
 
+
 // For a script finds all SharedFunctionInfo's in the heap that points
 // to this script. Returns JSArray of SharedFunctionInfo wrapped
 // in OpaqueReferences.
@@ -13001,6 +13023,7 @@
   return *result;
 }
 
+
 // For a script calculates compilation information about all its functions.
 // The script source is explicitly specified by the second argument.
 // The source of the actual script is not used, however it is important that
@@ -13027,6 +13050,7 @@
   return result;
 }
 
+
 // Changes the source of the script to a new_source.
 // If old_script_name is provided (i.e. is a String), also creates a copy of
 // the script with its original source and sends notification to debugger.
@@ -13074,6 +13098,7 @@
   return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
 }
 
+
 // Connects SharedFunctionInfo to another script.
 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
   HandleScope scope(isolate);
@@ -13148,6 +13173,7 @@
   return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
 }
 
+
 // Compares 2 strings line-by-line, then token-wise and returns diff in form
 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
 // of diff chunks.
diff --git a/src/runtime.js b/src/runtime.js
index 348fd74..90fb36b 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -587,7 +587,7 @@
   if (IS_NUMBER(x)) return new $Number(x);
   if (IS_BOOLEAN(x)) return new $Boolean(x);
   if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
-    throw %MakeTypeError('null_to_object', []);
+    throw %MakeTypeError('undefined_or_null_to_object', []);
   }
   return x;
 }
diff --git a/src/sampler.cc b/src/sampler.cc
index 982f252..e86cb68 100644
--- a/src/sampler.cc
+++ b/src/sampler.cc
@@ -668,6 +668,7 @@
   delete data_;
 }
 
+
 void Sampler::Start() {
   ASSERT(!IsActive());
   SetActive(true);
@@ -681,6 +682,7 @@
   SetActive(false);
 }
 
+
 void Sampler::SampleStack(const RegisterState& state) {
   TickSample* sample = isolate_->cpu_profiler()->TickSampleEvent();
   TickSample sample_obj;
diff --git a/src/scanner-character-streams.cc b/src/scanner-character-streams.cc
index 56b9f03..fb50345 100644
--- a/src/scanner-character-streams.cc
+++ b/src/scanner-character-streams.cc
@@ -46,6 +46,7 @@
   buffer_end_ = buffer_;
 }
 
+
 BufferedUtf16CharacterStream::~BufferedUtf16CharacterStream() { }
 
 void BufferedUtf16CharacterStream::PushBack(uc32 character) {
@@ -113,6 +114,7 @@
   return BufferSeekForward(delta);
 }
 
+
 // ----------------------------------------------------------------------------
 // GenericStringUtf16CharacterStream
 
diff --git a/src/spaces.cc b/src/spaces.cc
index 15381ea..5935c4a 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -914,6 +914,7 @@
   chunk->IncrementLiveBytes(by);
 }
 
+
 // -----------------------------------------------------------------------------
 // PagedSpace implementation
 
@@ -994,6 +995,7 @@
   return Failure::Exception();
 }
 
+
 bool PagedSpace::CanExpand() {
   ASSERT(max_capacity_ % AreaSize() == 0);
 
@@ -1868,6 +1870,7 @@
   }
 }
 
+
 // Because the copying collector does not touch garbage objects, we iterate
 // the new space before a collection to get a histogram of allocated objects.
 // This only happens when --log-gc flag is set.
@@ -1961,6 +1964,7 @@
   return size;
 }
 
+
 // -----------------------------------------------------------------------------
 // Free lists for old object spaces implementation
 
diff --git a/src/string.js b/src/string.js
index 7e18687..cb82c16 100644
--- a/src/string.js
+++ b/src/string.js
@@ -185,7 +185,8 @@
   if (IS_REGEXP(regexp)) {
     // Emulate RegExp.prototype.exec's side effect in step 5, even though
     // value is discarded.
-    ToInteger(regexp.lastIndex);
+    var lastIndex = regexp.lastIndex;
+    TO_INTEGER_FOR_SIDE_EFFECT(lastIndex);
     if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0);
     %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
     // lastMatchInfo is defined in regexp.js.
@@ -236,7 +237,8 @@
   if (IS_REGEXP(search)) {
     // Emulate RegExp.prototype.exec's side effect in step 5, even if
     // value is discarded.
-    ToInteger(search.lastIndex);
+    var lastIndex = search.lastIndex;
+    TO_INTEGER_FOR_SIDE_EFFECT(lastIndex);
     %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
 
     if (!IS_SPEC_FUNCTION(replace)) {
diff --git a/src/strtod.cc b/src/strtod.cc
index a1774b6..d332fd2 100644
--- a/src/strtod.cc
+++ b/src/strtod.cc
@@ -128,6 +128,7 @@
       exponent + (buffer.length() - kMaxSignificantDecimalDigits);
 }
 
+
 // Reads digits from the buffer and converts them to a uint64.
 // Reads in as many digits as fit into a uint64.
 // When the string starts with "1844674407370955161" no further digit is read.
@@ -175,8 +176,7 @@
 static bool DoubleStrtod(Vector<const char> trimmed,
                          int exponent,
                          double* result) {
-#if (V8_TARGET_ARCH_IA32 || defined(USE_SIMULATOR)) \
-    && !defined(_MSC_VER)
+#if (V8_TARGET_ARCH_IA32 || defined(USE_SIMULATOR)) && !defined(_MSC_VER)
   // On x86 the floating-point stack can be 64 or 80 bits wide. If it is
   // 80 bits wide (as is the case on Linux) then double-rounding occurs and the
   // result is not accurate.
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 62ac2c8..0ccd5e6 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -499,15 +499,30 @@
 Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
                                            Handle<GlobalObject> receiver,
                                            Handle<PropertyCell> cell,
+                                           Handle<Object> value,
                                            StrictModeFlag strict_mode) {
-  Handle<Code> stub = FindIC(
-      name, Handle<JSObject>::cast(receiver),
-      Code::STORE_IC, Code::NORMAL, strict_mode);
-  if (!stub.is_null()) return stub;
+  Isolate* isolate = cell->GetIsolate();
+  Handle<Type> union_type(PropertyCell::UpdateType(cell, value), isolate);
+  bool is_constant = union_type->IsConstant();
+  StoreGlobalStub stub(strict_mode, is_constant);
 
-  StoreStubCompiler compiler(isolate_, strict_mode);
-  Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name);
+  Handle<Code> code = FindIC(
+      name, Handle<JSObject>::cast(receiver),
+      Code::STORE_IC, Code::NORMAL, stub.GetExtraICState());
+  if (!code.is_null()) return code;
+
+  if (is_constant) return stub.GetCode(isolate_);
+
+  // Replace the placeholder cell and global object map with the actual global
+  // cell and receiver map.
+  Handle<Map> cell_map(isolate_->heap()->global_property_cell_map());
+  Handle<Map> meta_map(isolate_->heap()->meta_map());
+  Handle<Object> receiver_map(receiver->map(), isolate_);
+  code = stub.GetCodeCopyFromTemplate(isolate_);
+  code->ReplaceNthObject(1, *meta_map, *receiver_map);
+  code->ReplaceNthObject(1, *cell_map, *cell);
   JSObject::UpdateMapCodeCache(receiver, name, code);
+
   return code;
 }
 
@@ -922,12 +937,8 @@
     if (!cached_ic.is_null()) return cached_ic;
   }
 
-  Handle<Code> ic = stub.GetCode(isolate_);
-
-  // For monomorphic maps, use the code as a template, copying and replacing
-  // the monomorphic map that checks the object's type.
-  ic = isolate_->factory()->CopyCode(ic);
-  ic->ReplaceFirstMap(*receiver_map);
+  Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_);
+  ic->ReplaceNthObject(1, isolate_->heap()->meta_map(), *receiver_map);
 
   if (!receiver_map->is_shared()) {
     Map::UpdateCodeCache(receiver_map, name, ic);
@@ -2045,6 +2056,7 @@
   }
 }
 
+
 CallOptimization::CallOptimization(Handle<JSFunction> function) {
   Initialize(function);
 }
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 6d70d34..5317ce8 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -184,6 +184,7 @@
   Handle<Code> ComputeStoreGlobal(Handle<Name> name,
                                   Handle<GlobalObject> object,
                                   Handle<PropertyCell> cell,
+                                  Handle<Object> value,
                                   StrictModeFlag strict_mode);
 
   Handle<Code> ComputeStoreCallback(Handle<Name> name,
diff --git a/src/type-info.cc b/src/type-info.cc
index 83eb9c4..e2be3aa 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -395,8 +395,7 @@
   }
   Handle<Code> code = Handle<Code>::cast(object);
   ASSERT(code->is_unary_op_stub());
-  return UnaryOpIC::TypeInfoToType(
-      static_cast<UnaryOpIC::TypeInfo>(code->unary_op_type()), isolate());
+  return UnaryOpStub(code->extra_ic_state()).GetType(isolate());
 }
 
 
@@ -698,4 +697,16 @@
 #endif
 }
 
+
+Representation Representation::FromType(TypeInfo info) {
+  if (info.IsUninitialized()) return Representation::None();
+  // TODO(verwaest): Return Smi rather than Integer32.
+  if (info.IsSmi()) return Representation::Integer32();
+  if (info.IsInteger32()) return Representation::Integer32();
+  if (info.IsDouble()) return Representation::Double();
+  if (info.IsNumber()) return Representation::Double();
+  return Representation::Tagged();
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/type-info.h b/src/type-info.h
index a1c1f54..aa1f509 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -303,9 +303,9 @@
                   Maybe<int>* fixed_right_arg);
 
   void CompareType(TypeFeedbackId id,
-                   Handle<Type>* left_type,
-                   Handle<Type>* right_type,
-                   Handle<Type>* combined_type);
+                   Handle<Type>* left,
+                   Handle<Type>* right,
+                   Handle<Type>* combined);
 
   Handle<Type> ClauseType(TypeFeedbackId id);
 
diff --git a/src/types.cc b/src/types.cc
index 1275dea..ed98480 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -318,6 +318,7 @@
   return false;
 }
 
+
 // Get non-bitsets from this which are not subsumed by union, store at unioned,
 // starting at index. Returns updated index.
 int Type::ExtendUnion(Handle<Unioned> result, int current_size) {
@@ -476,4 +477,13 @@
       : Union(type, Undefined()->handle_via_isolate_of(*type));
 }
 
+
+Representation Representation::FromType(Handle<Type> type) {
+  if (type->Is(Type::None())) return Representation::None();
+  if (type->Is(Type::Signed32())) return Representation::Integer32();
+  if (type->Is(Type::Number())) return Representation::Double();
+  return Representation::Tagged();
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/typing.cc b/src/typing.cc
index 7c11612..3f3ff60 100644
--- a/src/typing.cc
+++ b/src/typing.cc
@@ -432,13 +432,13 @@
   CHECK_ALIVE(Visit(expr->right()));
 
   // Collect type feedback.
-  Handle<Type> left_type, right_type, result_type;
+  Handle<Type> type, left_type, right_type;
   Maybe<int> fixed_right_arg;
   oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
-      &left_type, &right_type, &result_type, &fixed_right_arg);
+      &left_type, &right_type, &type, &fixed_right_arg);
+  MergeLowerType(expr, type);
   MergeLowerType(expr->left(), left_type);
   MergeLowerType(expr->right(), right_type);
-  expr->set_result_type(result_type);
   expr->set_fixed_right_arg(fixed_right_arg);
   if (expr->op() == Token::OR || expr->op() == Token::AND) {
     expr->left()->RecordToBooleanTypeFeedback(oracle());
diff --git a/src/unicode.cc b/src/unicode.cc
index 04065b0..bd32467 100644
--- a/src/unicode.cc
+++ b/src/unicode.cc
@@ -52,14 +52,17 @@
   return table[D * index];
 }
 
+
 static inline uchar GetEntry(int32_t entry) {
   return entry & (kStartBit - 1);
 }
 
+
 static inline bool IsStart(int32_t entry) {
   return (entry & kStartBit) != 0;
 }
 
+
 /**
  * Look up a character in the unicode table using a mix of binary and
  * interpolation search.  For a uniformly distributed array
@@ -106,6 +109,7 @@
   uchar chars[kW];
 };
 
+
 // Look up the mapping for the given character in the specified table,
 // which is of the specified length and uses the specified special case
 // mapping for multi-char mappings.  The next parameter is the character
@@ -456,6 +460,7 @@
   }
 }
 
+
 // Lowercase:            point.category == 'Ll'
 
 static const uint16_t kLowercaseTable0Size = 463;
@@ -567,6 +572,7 @@
   }
 }
 
+
 // Letter:               point.category in ['Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl' ]
 
 static const uint16_t kLetterTable0Size = 435;
@@ -703,6 +709,7 @@
   }
 }
 
+
 // Space:                point.category == 'Zs'
 
 static const uint16_t kSpaceTable0Size = 4;
@@ -724,6 +731,7 @@
   }
 }
 
+
 // Number:               point.category == 'Nd'
 
 static const uint16_t kNumberTable0Size = 56;
@@ -758,6 +766,7 @@
   }
 }
 
+
 // WhiteSpace:           'Ws' in point.properties
 
 static const uint16_t kWhiteSpaceTable0Size = 7;
@@ -779,6 +788,7 @@
   }
 }
 
+
 // LineTerminator:       'Lt' in point.properties
 
 static const uint16_t kLineTerminatorTable0Size = 2;
@@ -800,6 +810,7 @@
   }
 }
 
+
 // CombiningMark:        point.category in ['Mn', 'Mc']
 
 static const uint16_t kCombiningMarkTable0Size = 258;
@@ -871,6 +882,7 @@
   }
 }
 
+
 // ConnectorPunctuation: point.category == 'Pc'
 
 static const uint16_t kConnectorPunctuationTable0Size = 1;
diff --git a/src/v8-counters.cc b/src/v8-counters.cc
index ca83e38..b3e15bb 100644
--- a/src/v8-counters.cc
+++ b/src/v8-counters.cc
@@ -78,6 +78,7 @@
 #undef SC
 }
 
+
 void Counters::ResetHistograms() {
 #define HT(name, caption) name##_.Reset();
     HISTOGRAM_TIMER_LIST(HT)
diff --git a/src/v8.cc b/src/v8.cc
index cb67105..cfec0c0 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -263,6 +263,7 @@
   return heap_number;
 }
 
+
 void V8::InitializeOncePerProcessImpl() {
   FlagList::EnforceFlagImplications();
   if (FLAG_stress_compaction) {
@@ -323,6 +324,7 @@
   Bootstrapper::InitializeOncePerProcess();
 }
 
+
 void V8::InitializeOncePerProcess() {
   CallOnce(&init_once, &InitializeOncePerProcessImpl);
 }
diff --git a/src/v8threads.cc b/src/v8threads.cc
index 925e198..2df187a 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -388,6 +388,7 @@
   return data != NULL && data->thread_state() != NULL;
 }
 
+
 void ThreadManager::Iterate(ObjectVisitor* v) {
   // Expecting no threads during serialization/deserialization
   for (ThreadState* state = FirstThreadStateInUse();
diff --git a/src/version.cc b/src/version.cc
index 0041c67..4ded5d2 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     20
-#define BUILD_NUMBER      2
+#define BUILD_NUMBER      3
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 3a3ee9c..aaab839 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -902,11 +902,13 @@
   emit(0xF8);
 }
 
+
 void Assembler::cld() {
   EnsureSpace ensure_space(this);
   emit(0xFC);
 }
 
+
 void Assembler::cdq() {
   EnsureSpace ensure_space(this);
   emit(0x99);
@@ -2522,6 +2524,7 @@
   emit(b2 + i);
 }
 
+
 // SSE 2 operations.
 
 void Assembler::movd(XMMRegister dst, Register src) {
@@ -2582,6 +2585,7 @@
   }
 }
 
+
 void Assembler::movdqa(const Operand& dst, XMMRegister src) {
   EnsureSpace ensure_space(this);
   emit(0x66);
@@ -3035,10 +3039,12 @@
   emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
 }
 
+
 void Assembler::emit_sse_operand(XMMRegister dst, Register src) {
   emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
 }
 
+
 void Assembler::emit_sse_operand(Register dst, XMMRegister src) {
   emit(0xC0 | (dst.low_bits() << 3) | src.low_bits());
 }
@@ -3075,6 +3081,7 @@
   reloc_info_writer.Write(&rinfo);
 }
 
+
 void Assembler::RecordJSReturn() {
   positions_recorder()->WriteRecordedPositions();
   EnsureSpace ensure_space(this);
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 2b44a77..c1a2ed7 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -726,6 +726,7 @@
   __ Abort("no cases left");
 }
 
+
 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
   Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
 }
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 9233848..e4136ba 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -1,4 +1,4 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
+// Copyright 2013 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -222,7 +222,29 @@
   descriptor->deoptimization_handler_ =
      FUNCTION_ADDR(ToBooleanIC_Miss);
   descriptor->SetMissHandler(
-      ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
+     ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
+}
+
+
+void UnaryOpStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { rax };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+     FUNCTION_ADDR(UnaryOpIC_Miss);
+}
+
+
+void StoreGlobalStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { rdx, rcx, rax };
+  descriptor->register_param_count_ = 3;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(StoreIC_MissFromStubFailure);
 }
 
 
@@ -643,259 +665,6 @@
 }
 
 
-void UnaryOpStub::Generate(MacroAssembler* masm) {
-  switch (operand_type_) {
-    case UnaryOpIC::UNINITIALIZED:
-      GenerateTypeTransition(masm);
-      break;
-    case UnaryOpIC::SMI:
-      GenerateSmiStub(masm);
-      break;
-    case UnaryOpIC::NUMBER:
-      GenerateNumberStub(masm);
-      break;
-    case UnaryOpIC::GENERIC:
-      GenerateGenericStub(masm);
-      break;
-  }
-}
-
-
-void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
-  __ pop(rcx);  // Save return address.
-
-  __ push(rax);  // the operand
-  __ Push(Smi::FromInt(op_));
-  __ Push(Smi::FromInt(mode_));
-  __ Push(Smi::FromInt(operand_type_));
-
-  __ 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::kUnaryOp_Patch), masm->isolate()), 4, 1);
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateSmiStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateSmiStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
-  Label slow;
-  GenerateSmiCodeSub(masm, &slow, &slow, Label::kNear, Label::kNear);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
-  Label non_smi;
-  GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
-  __ bind(&non_smi);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
-                                     Label* non_smi,
-                                     Label* slow,
-                                     Label::Distance non_smi_near,
-                                     Label::Distance slow_near) {
-  Label done;
-  __ JumpIfNotSmi(rax, non_smi, non_smi_near);
-  __ SmiNeg(rax, rax, &done, Label::kNear);
-  __ jmp(slow, slow_near);
-  __ bind(&done);
-  __ ret(0);
-}
-
-
-void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
-                                        Label* non_smi,
-                                        Label::Distance non_smi_near) {
-  __ JumpIfNotSmi(rax, non_smi, non_smi_near);
-  __ SmiNot(rax, rax);
-  __ ret(0);
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateNumberStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateNumberStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
-  Label non_smi, slow, call_builtin;
-  GenerateSmiCodeSub(masm, &non_smi, &call_builtin, Label::kNear);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeSub(masm, &slow);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-  __ bind(&call_builtin);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateNumberStubBitNot(
-    MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeBitNot(masm, &slow);
-  __ bind(&slow);
-  GenerateTypeTransition(masm);
-}
-
-
-void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
-                                            Label* slow) {
-  // Check if the operand is a heap number.
-  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
-                 Heap::kHeapNumberMapRootIndex);
-  __ j(not_equal, slow);
-
-  // Operand is a float, negate its value by flipping the sign bit.
-  if (mode_ == UNARY_OVERWRITE) {
-    __ Set(kScratchRegister, 0x01);
-    __ shl(kScratchRegister, Immediate(63));
-    __ xor_(FieldOperand(rax, HeapNumber::kValueOffset), kScratchRegister);
-  } else {
-    // Allocate a heap number before calculating the answer,
-    // so we don't have an untagged double around during GC.
-    Label slow_allocate_heapnumber, heapnumber_allocated;
-    __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber);
-    __ jmp(&heapnumber_allocated);
-
-    __ bind(&slow_allocate_heapnumber);
-    {
-      FrameScope scope(masm, StackFrame::INTERNAL);
-      __ push(rax);
-      __ CallRuntime(Runtime::kNumberAlloc, 0);
-      __ movq(rcx, rax);
-      __ pop(rax);
-    }
-    __ bind(&heapnumber_allocated);
-    // rcx: allocated 'empty' number
-
-    // Copy the double value to the new heap number, flipping the sign.
-    __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset));
-    __ Set(kScratchRegister, 0x01);
-    __ shl(kScratchRegister, Immediate(63));
-    __ xor_(rdx, kScratchRegister);  // Flip sign.
-    __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx);
-    __ movq(rax, rcx);
-  }
-  __ ret(0);
-}
-
-
-void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
-                                               Label* slow) {
-  // Check if the operand is a heap number.
-  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
-                 Heap::kHeapNumberMapRootIndex);
-  __ j(not_equal, slow);
-
-  // Convert the heap number in rax to an untagged integer in rcx.
-  IntegerConvert(masm, rax, rax);
-
-  // Do the bitwise operation and smi tag the result.
-  __ notl(rax);
-  __ Integer32ToSmi(rax, rax);
-  __ ret(0);
-}
-
-
-// TODO(svenpanne): Use virtual functions instead of switch.
-void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
-  switch (op_) {
-    case Token::SUB:
-      GenerateGenericStubSub(masm);
-      break;
-    case Token::BIT_NOT:
-      GenerateGenericStubBitNot(masm);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeSub(masm, &non_smi, &slow, Label::kNear);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeSub(masm, &slow);
-  __ bind(&slow);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
-  Label non_smi, slow;
-  GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
-  __ bind(&non_smi);
-  GenerateHeapNumberCodeBitNot(masm, &slow);
-  __ bind(&slow);
-  GenerateGenericCodeFallback(masm);
-}
-
-
-void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
-  // Handle the slow case by jumping to the JavaScript builtin.
-  __ pop(rcx);  // pop return address
-  __ push(rax);
-  __ push(rcx);  // push return address
-  switch (op_) {
-    case Token::SUB:
-      __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
-      break;
-    case Token::BIT_NOT:
-      __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-
-void UnaryOpStub::PrintName(StringStream* stream) {
-  const char* op_name = Token::Name(op_);
-  const char* overwrite_name = NULL;  // Make g++ happy.
-  switch (mode_) {
-    case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
-    case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
-  }
-  stream->Add("UnaryOpStub_%s_%s_%s",
-              op_name,
-              overwrite_name,
-              UnaryOpIC::GetName(operand_type_));
-}
-
-
 void BinaryOpStub::Initialize() {}
 
 
@@ -5328,6 +5097,7 @@
   __ bind(&hash_not_zero);
 }
 
+
 void SubStringStub::Generate(MacroAssembler* masm) {
   Label runtime;
 
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index f6cfad0..228a82a 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -81,77 +81,6 @@
 };
 
 
-class UnaryOpStub: public PlatformCodeStub {
- public:
-  UnaryOpStub(Token::Value op,
-              UnaryOverwriteMode mode,
-              UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
-      : op_(op),
-        mode_(mode),
-        operand_type_(operand_type) {
-  }
-
- private:
-  Token::Value op_;
-  UnaryOverwriteMode mode_;
-
-  // Operand type information determined at runtime.
-  UnaryOpIC::TypeInfo operand_type_;
-
-  virtual void PrintName(StringStream* stream);
-
-  class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
-  class OpBits: public BitField<Token::Value, 1, 7> {};
-  class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
-
-  Major MajorKey() { return UnaryOp; }
-  int MinorKey() {
-    return ModeBits::encode(mode_)
-           | OpBits::encode(op_)
-           | OperandTypeInfoBits::encode(operand_type_);
-  }
-
-  // Note: A lot of the helper functions below will vanish when we use virtual
-  // function instead of switch more often.
-  void Generate(MacroAssembler* masm);
-
-  void GenerateTypeTransition(MacroAssembler* masm);
-
-  void GenerateSmiStub(MacroAssembler* masm);
-  void GenerateSmiStubSub(MacroAssembler* masm);
-  void GenerateSmiStubBitNot(MacroAssembler* masm);
-  void GenerateSmiCodeSub(MacroAssembler* masm,
-                          Label* non_smi,
-                          Label* slow,
-                          Label::Distance non_smi_near = Label::kFar,
-                          Label::Distance slow_near = Label::kFar);
-  void GenerateSmiCodeBitNot(MacroAssembler* masm,
-                             Label* non_smi,
-                             Label::Distance non_smi_near);
-
-  void GenerateNumberStub(MacroAssembler* masm);
-  void GenerateNumberStubSub(MacroAssembler* masm);
-  void GenerateNumberStubBitNot(MacroAssembler* masm);
-  void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
-  void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
-
-  void GenerateGenericStub(MacroAssembler* masm);
-  void GenerateGenericStubSub(MacroAssembler* masm);
-  void GenerateGenericStubBitNot(MacroAssembler* masm);
-  void GenerateGenericCodeFallback(MacroAssembler* masm);
-
-  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
-
-  virtual InlineCacheState GetICState() {
-    return UnaryOpIC::ToState(operand_type_);
-  }
-
-  virtual void FinishCode(Handle<Code> code) {
-    code->set_unary_op_type(operand_type_);
-  }
-};
-
-
 class StringHelper : public AllStatic {
  public:
   // Generate code for copying characters using a simple loop. This should only
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index d787775..eefa703 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -49,6 +49,7 @@
   BYTE_OPER_REG_OP_ORDER = OPER_REG_OP_ORDER | BYTE_SIZE_OPERAND_FLAG
 };
 
+
 //------------------------------------------------------------------
 // Tables
 //------------------------------------------------------------------
@@ -293,6 +294,7 @@
   {"cmovg", TWO_OPERANDS_INSTR, REG_OPER_OP_ORDER, false}
 };
 
+
 //------------------------------------------------------------------------------
 // DisassemblerX64 implementation.
 
@@ -301,6 +303,7 @@
   ABORT_ON_UNIMPLEMENTED_OPCODE
 };
 
+
 // A new DisassemblerX64 object is created to disassemble each instruction.
 // The object can only disassemble a single instruction.
 class DisassemblerX64 {
@@ -1763,6 +1766,7 @@
   return instr_len;
 }
 
+
 //------------------------------------------------------------------------------
 
 
@@ -1822,6 +1826,7 @@
   return "";
 }
 
+
 //------------------------------------------------------------------------------
 
 Disassembler::Disassembler(const NameConverter& converter)
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 9ad7f58..66bc38b 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -4353,10 +4353,7 @@
                                            const char* comment) {
   // TODO(svenpanne): Allowing format strings in Comment would be nice here...
   Comment cmt(masm_, comment);
-  bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
-  UnaryOverwriteMode overwrite =
-      can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
-  UnaryOpStub stub(expr->op(), overwrite);
+  UnaryOpStub stub(expr->op());
   // UnaryOpStub expects the argument to be in the
   // accumulator register rax.
   VisitForAccumulatorValue(expr->expression());
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index de43f86..8a2a086 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -1834,12 +1834,12 @@
 
 template<class InstrType>
 void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
-  int right_block = instr->FalseDestination(chunk_);
   int left_block = instr->TrueDestination(chunk_);
+  int right_block = instr->FalseDestination(chunk_);
 
   int next_block = GetNextEmittedBlock();
 
-  if (right_block == left_block) {
+  if (right_block == left_block || cc == no_condition) {
     EmitGoto(left_block);
   } else if (left_block == next_block) {
     __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
@@ -1859,6 +1859,25 @@
 }
 
 
+void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
+  Representation r = instr->hydrogen()->value()->representation();
+  if (r.IsSmiOrInteger32() || r.IsDouble()) {
+    EmitBranch(instr, no_condition);
+  } else {
+    ASSERT(r.IsTagged());
+    Register reg = ToRegister(instr->value());
+    HType type = instr->hydrogen()->value()->type();
+    if (type.IsTaggedNumber()) {
+      EmitBranch(instr, no_condition);
+    }
+    __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
+    __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset),
+                   Heap::kHeapNumberMapRootIndex);
+    EmitBranch(instr, equal);
+  }
+}
+
+
 void LCodeGen::DoBranch(LBranch* instr) {
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsInteger32()) {
@@ -2027,7 +2046,7 @@
 }
 
 
-void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
+void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
   LOperand* left = instr->left();
   LOperand* right = instr->right();
   Condition cc = TokenToCondition(instr->op(), instr->is_double());
diff --git a/src/x64/lithium-gap-resolver-x64.cc b/src/x64/lithium-gap-resolver-x64.cc
index aed4f36..adb1afa 100644
--- a/src/x64/lithium-gap-resolver-x64.cc
+++ b/src/x64/lithium-gap-resolver-x64.cc
@@ -202,6 +202,20 @@
       } else {
         __ LoadObject(dst, cgen_->ToHandle(constant_source));
       }
+    } else if (destination->IsDoubleRegister()) {
+      double v = cgen_->ToDouble(constant_source);
+      uint64_t int_val = BitCast<uint64_t, double>(v);
+      int32_t lower = static_cast<int32_t>(int_val);
+      int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
+      XMMRegister dst = cgen_->ToDoubleRegister(destination);
+      if (int_val == 0) {
+        __ xorps(dst, dst);
+      } else {
+        __ push(Immediate(upper));
+        __ push(Immediate(lower));
+        __ movsd(dst, Operand(rsp, 0));
+        __ addq(rsp, Immediate(kDoubleSize));
+      }
     } else {
       ASSERT(destination->IsStackSlot());
       Operand dst = cgen_->ToOperand(destination);
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 95a44f0..950bf4d 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -185,7 +185,7 @@
 }
 
 
-void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
+void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if ");
   left()->PrintTo(stream);
   stream->Add(" %s ", Token::String(op()));
@@ -1168,6 +1168,7 @@
   return AssignEnvironment(DefineAsRegister(result));
 }
 
+
 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
   LOperand* input = UseRegisterAtStart(instr->value());
   LMathAbs* result = new(zone()) LMathAbs(input);
@@ -1598,8 +1599,8 @@
 }
 
 
-LInstruction* LChunkBuilder::DoCompareIDAndBranch(
-    HCompareIDAndBranch* instr) {
+LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
+    HCompareNumericAndBranch* instr) {
   Representation r = instr->representation();
   if (r.IsSmiOrInteger32()) {
     ASSERT(instr->left()->representation().IsSmiOrInteger32());
@@ -1607,7 +1608,7 @@
         instr->right()->representation()));
     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
     LOperand* right = UseOrConstantAtStart(instr->right());
-    return new(zone()) LCmpIDAndBranch(left, right);
+    return new(zone()) LCompareNumericAndBranch(left, right);
   } else {
     ASSERT(r.IsDouble());
     ASSERT(instr->left()->representation().IsDouble());
@@ -1621,7 +1622,7 @@
       left = UseRegisterAtStart(instr->left());
       right = UseRegisterAtStart(instr->right());
     }
-    return new(zone()) LCmpIDAndBranch(left, right);
+    return new(zone()) LCompareNumericAndBranch(left, right);
   }
 }
 
@@ -1911,6 +1912,18 @@
 }
 
 
+LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
+  LOperand* value = UseRegisterAtStart(instr->value());
+  return AssignEnvironment(new(zone()) LCheckSmi(value));
+}
+
+
+LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) {
+  return new(zone()) LIsNumberAndBranch(
+      UseRegisterOrConstantAtStart(instr->value()));
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LCheckInstanceType* result = new(zone()) LCheckInstanceType(value);
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index a7530be..6efa9d3 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -81,7 +81,7 @@
   V(ClampTToUint8)                              \
   V(ClassOfTestAndBranch)                       \
   V(CmpConstantEqAndBranch)                     \
-  V(CmpIDAndBranch)                             \
+  V(CompareNumericAndBranch)                    \
   V(CmpObjectEqAndBranch)                       \
   V(CmpMapAndBranch)                            \
   V(CmpT)                                       \
@@ -120,6 +120,7 @@
   V(IsObjectAndBranch)                          \
   V(IsStringAndBranch)                          \
   V(IsSmiAndBranch)                             \
+  V(IsNumberAndBranch)                          \
   V(IsUndetectableAndBranch)                    \
   V(Label)                                      \
   V(LazyBailout)                                \
@@ -672,9 +673,9 @@
 };
 
 
-class LCmpIDAndBranch: public LControlInstruction<2, 0> {
+class LCompareNumericAndBranch: public LControlInstruction<2, 0> {
  public:
-  LCmpIDAndBranch(LOperand* left, LOperand* right) {
+  LCompareNumericAndBranch(LOperand* left, LOperand* right) {
     inputs_[0] = left;
     inputs_[1] = right;
   }
@@ -682,8 +683,9 @@
   LOperand* left() { return inputs_[0]; }
   LOperand* right() { return inputs_[1]; }
 
-  DECLARE_CONCRETE_INSTRUCTION(CmpIDAndBranch, "cmp-id-and-branch")
-  DECLARE_HYDROGEN_ACCESSOR(CompareIDAndBranch)
+  DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch,
+                               "compare-numeric-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(CompareNumericAndBranch)
 
   Token::Value op() const { return hydrogen()->token(); }
   bool is_double() const {
@@ -866,6 +868,19 @@
 };
 
 
+class LIsNumberAndBranch: public LControlInstruction<1, 0> {
+ public:
+  explicit LIsNumberAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(IsNumberAndBranch, "is-number-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(IsNumberAndBranch)
+};
+
+
 class LIsStringAndBranch: public LControlInstruction<1, 1> {
  public:
   explicit LIsStringAndBranch(LOperand* value, LOperand* temp) {
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index e5bee67..d2db523 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -972,6 +972,7 @@
   }
 }
 
+
 void MacroAssembler::Set(const Operand& dst, int64_t x) {
   if (is_int32(x)) {
     movq(dst, Immediate(static_cast<int32_t>(x)));
@@ -1029,6 +1030,7 @@
   return kScratchRegister;
 }
 
+
 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
   if (emit_debug_code()) {
     movq(dst,
@@ -3897,52 +3899,8 @@
                               Label* gc_required,
                               AllocationFlags flags) {
   ASSERT((flags & SIZE_IN_WORDS) == 0);
-  if (!FLAG_inline_new) {
-    if (emit_debug_code()) {
-      // Trash the registers to simulate an allocation failure.
-      movl(result, Immediate(0x7091));
-      movl(result_end, Immediate(0x7191));
-      if (scratch.is_valid()) {
-        movl(scratch, Immediate(0x7291));
-      }
-      // Register element_count is not modified by the function.
-    }
-    jmp(gc_required);
-    return;
-  }
-  ASSERT(!result.is(result_end));
-
-  // Load address of new object into result.
-  LoadAllocationTopHelper(result, scratch, flags);
-
-  // Align the next allocation. Storing the filler map without checking top is
-  // always safe because the limit of the heap is always aligned.
-  if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
-    testq(result, Immediate(kDoubleAlignmentMask));
-    Check(zero, "Allocation is not double aligned");
-  }
-
-  // Calculate new top and bail out if new space is exhausted.
-  ExternalReference allocation_limit =
-      AllocationUtils::GetAllocationLimitReference(isolate(), flags);
-
-  // We assume that element_count*element_size + header_size does not
-  // overflow.
   lea(result_end, Operand(element_count, element_size, header_size));
-  addq(result_end, result);
-  j(carry, gc_required);
-  Operand limit_operand = ExternalOperand(allocation_limit);
-  cmpq(result_end, limit_operand);
-  j(above, gc_required);
-
-  // Update allocation top.
-  UpdateAllocationTopHelper(result_end, scratch, flags);
-
-  // Tag the result if requested.
-  if ((flags & TAG_OBJECT) != 0) {
-    ASSERT(kHeapObjectTag == 1);
-    incq(result);
-  }
+  Allocate(result_end, result, result_end, scratch, gc_required, flags);
 }
 
 
@@ -3952,7 +3910,7 @@
                               Register scratch,
                               Label* gc_required,
                               AllocationFlags flags) {
-  ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
+  ASSERT((flags & SIZE_IN_WORDS) == 0);
   if (!FLAG_inline_new) {
     if (emit_debug_code()) {
       // Trash the registers to simulate an allocation failure.
@@ -3971,6 +3929,13 @@
   // Load address of new object into result.
   LoadAllocationTopHelper(result, scratch, flags);
 
+  // Align the next allocation. Storing the filler map without checking top is
+  // always safe because the limit of the heap is always aligned.
+  if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
+    testq(result, Immediate(kDoubleAlignmentMask));
+    Check(zero, "Allocation is not double aligned");
+  }
+
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference allocation_limit =
       AllocationUtils::GetAllocationLimitReference(isolate(), flags);
@@ -3986,13 +3951,6 @@
   // Update allocation top.
   UpdateAllocationTopHelper(result_end, scratch, flags);
 
-  // Align the next allocation. Storing the filler map without checking top is
-  // always safe because the limit of the heap is always aligned.
-  if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
-    testq(result, Immediate(kDoubleAlignmentMask));
-    Check(zero, "Allocation is not double aligned");
-  }
-
   // Tag the result if requested.
   if ((flags & TAG_OBJECT) != 0) {
     addq(result, Immediate(kHeapObjectTag));
diff --git a/src/zone.cc b/src/zone.cc
index 2a0a0e2..9ee00ed 100644
--- a/src/zone.cc
+++ b/src/zone.cc
@@ -92,18 +92,15 @@
 #endif
 
   // Find a segment with a suitable size to keep around.
-  Segment* keep = segment_head_;
-  while (keep != NULL && keep->size() > kMaximumKeptSegmentSize) {
-    keep = keep->next();
-  }
-
+  Segment* keep = NULL;
   // Traverse the chained list of segments, zapping (in debug mode)
   // and freeing every segment except the one we wish to keep.
   for (Segment* current = segment_head_; current != NULL; ) {
     Segment* next = current->next();
-    if (current == keep) {
+    if (keep == NULL && current->size() <= kMaximumKeptSegmentSize) {
       // Unlink the segment we wish to keep from the list.
-      current->clear_next();
+      keep = current;
+      keep->clear_next();
     } else {
       int size = current->size();
 #ifdef DEBUG