Version 3.23.15

Fix context register allocation in LTransitionElementsKind (Chromium issue 324306).

Fix bug in inlining Function.apply (Chromium issue 323942).

Ensure that length is Smi in TypedArrayFromArrayLike constructor (Chromium issue 324028).

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@18158 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 81c7476..36d1d4d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2013-11-29: Version 3.23.15
+
+        Fix context register allocation in LTransitionElementsKind
+        (Chromium issue 324306).
+
+        Fix bug in inlining Function.apply (Chromium issue 323942).
+
+        Ensure that length is Smi in TypedArrayFromArrayLike constructor
+        (Chromium issue 324028).
+
+        Performance and stability improvements on all platforms.
+
+
 2013-11-28: Version 3.23.14
 
         Shorten autogenerated error message (issue 3019).
diff --git a/Makefile b/Makefile
index 2ff2cdb..9000d39 100644
--- a/Makefile
+++ b/Makefile
@@ -355,8 +355,8 @@
 FASTTESTMODES = ia32.release,x64.release,ia32.debug,x64.debug,arm.debug
 
 quickcheck:
-	@$(MAKE) all optdebug=on
-	@tools/run-tests.py $(TESTJOBS) --outdir=$(OUTDIR) \
+	@$(MAKE) all optdebug=on; \
+	tools/run-tests.py $(TESTJOBS) --outdir=$(OUTDIR) \
 	    --arch-and-mode=$(FASTTESTMODES) $(FASTTESTFLAGS) $(TESTFLAGS)
 qc: quickcheck
 
diff --git a/include/v8.h b/include/v8.h
index 28b6567..815f43d 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -734,8 +734,8 @@
           P* parameter,
           typename WeakReferenceCallbacks<T, P>::Revivable callback));
 
-  V8_DEPRECATED("This will be removed",
-                V8_INLINE T* ClearAndLeak());
+  // This will be removed.
+  V8_INLINE T* ClearAndLeak();
 
   V8_DEPRECATED("This will be removed",
                 V8_INLINE void Clear()) { this->val_ = 0; }
diff --git a/src/allocation-tracker.cc b/src/allocation-tracker.cc
index 28883ae..8044cef 100644
--- a/src/allocation-tracker.cc
+++ b/src/allocation-tracker.cc
@@ -169,7 +169,7 @@
 }
 
 
-void AllocationTracker::NewObjectEvent(Address addr, int size) {
+void AllocationTracker::AllocationEvent(Address addr, int size) {
   DisallowHeapAllocation no_allocation;
   Heap* heap = ids_->heap();
 
@@ -185,7 +185,8 @@
   while (!it.done() && length < kMaxAllocationTraceLength) {
     JavaScriptFrame* frame = it.frame();
     SharedFunctionInfo* shared = frame->function()->shared();
-    SnapshotObjectId id = ids_->FindEntry(shared->address());
+    SnapshotObjectId id = ids_->FindOrAddEntry(
+        shared->address(), shared->Size(), false);
     allocation_trace_buffer_[length++] = id;
     AddFunctionInfo(shared, id);
     it.Advance();
diff --git a/src/allocation-tracker.h b/src/allocation-tracker.h
index 8791b51..6844716 100644
--- a/src/allocation-tracker.h
+++ b/src/allocation-tracker.h
@@ -96,7 +96,7 @@
   ~AllocationTracker();
 
   void PrepareForSerialization();
-  void NewObjectEvent(Address addr, int size);
+  void AllocationEvent(Address addr, int size);
 
   AllocationTraceTree* trace_tree() { return &trace_tree_; }
   HashMap* id_to_function_info() { return &id_to_function_info_; }
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index afb0c62..84bc879 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -164,18 +164,12 @@
   inline static int NumAllocatableRegisters();
 
   static int ToAllocationIndex(Register reg) {
-    if (FLAG_enable_ool_constant_pool && (reg.code() >= kRegister_r8_Code)) {
-      return reg.code() - 1;
-    }
     ASSERT(reg.code() < kMaxNumAllocatableRegisters);
     return reg.code();
   }
 
   static Register FromAllocationIndex(int index) {
     ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
-    if (FLAG_enable_ool_constant_pool && (index >= 7)) {
-      return from_code(index + 1);
-    }
     return from_code(index);
   }
 
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 7ae2924..bef4bc3 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -693,7 +693,7 @@
   // r2: receiver
   // r3: argc
   // r4: argv
-  // r5-r6, r7 (if not FLAG_enable_ool_constant_pool) and cp may be clobbered
+  // r5-r6, r8 (if not FLAG_enable_ool_constant_pool) and cp may be clobbered
   ProfileEntryHookStub::MaybeCallEntryHook(masm);
 
   // Clear the context before we push it when entering the internal frame.
@@ -734,7 +734,7 @@
     __ mov(r5, Operand(r4));
     __ mov(r6, Operand(r4));
     if (!FLAG_enable_ool_constant_pool) {
-      __ mov(r7, Operand(r4));
+      __ mov(r8, Operand(r4));
     }
     if (kR9Available == 1) {
       __ mov(r9, Operand(r4));
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index f62ac85..09eca72 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -2584,7 +2584,7 @@
   const int kAliasedOffset =
       Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX);
 
-  __ ldr(r4, MemOperand(r8, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  __ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
   __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
   __ cmp(r1, Operand::Zero());
   __ ldr(r4, MemOperand(r4, kNormalOffset), eq);
@@ -2635,7 +2635,7 @@
   __ str(r6, FieldMemOperand(r4, FixedArray::kMapOffset));
   __ add(r6, r1, Operand(Smi::FromInt(2)));
   __ str(r6, FieldMemOperand(r4, FixedArray::kLengthOffset));
-  __ str(r8, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize));
+  __ str(cp, FieldMemOperand(r4, FixedArray::kHeaderSize + 0 * kPointerSize));
   __ add(r6, r4, Operand(r1, LSL, 1));
   __ add(r6, r6, Operand(kParameterMapHeaderSize));
   __ str(r6, FieldMemOperand(r4, FixedArray::kHeaderSize + 1 * kPointerSize));
@@ -3029,7 +3029,7 @@
 
   // For arguments 4 and 3 get string length, calculate start of string data and
   // calculate the shift of the index (0 for ASCII and 1 for two byte).
-  __ add(r8, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
+  __ add(r7, subject, Operand(SeqString::kHeaderSize - kHeapObjectTag));
   __ eor(r3, r3, Operand(1));
   // Load the length from the original subject string from the previous stack
   // frame. Therefore we have to use fp, which points exactly to two pointer
@@ -3040,12 +3040,12 @@
   // Argument 4, r3: End of string data
   // Argument 3, r2: Start of string data
   // Prepare start and end index of the input.
-  __ add(r9, r8, Operand(r9, LSL, r3));
+  __ add(r9, r7, Operand(r9, LSL, r3));
   __ add(r2, r9, Operand(r1, LSL, r3));
 
-  __ ldr(r8, FieldMemOperand(subject, String::kLengthOffset));
-  __ SmiUntag(r8);
-  __ add(r3, r9, Operand(r8, LSL, r3));
+  __ ldr(r7, FieldMemOperand(subject, String::kLengthOffset));
+  __ SmiUntag(r7);
+  __ add(r3, r9, Operand(r7, LSL, r3));
 
   // Argument 2 (r1): Previous index.
   // Already there
diff --git a/src/arm/frames-arm.h b/src/arm/frames-arm.h
index 6c9ec4a..e6ecda1 100644
--- a/src/arm/frames-arm.h
+++ b/src/arm/frames-arm.h
@@ -64,8 +64,8 @@
   1 <<  4 |  //  r4 v1
   1 <<  5 |  //  r5 v2
   1 <<  6 |  //  r6 v3
-  1 <<  7 |  //  r7 v4 (pp in JavaScript code)
-  1 <<  8 |  //  r8 v5 (cp in JavaScript code)
+  1 <<  7 |  //  r7 v4 (cp in JavaScript code)
+  1 <<  8 |  //  r8 v5 (pp in JavaScript code)
   kR9Available <<  9 |  //  r9 v6
   1 << 10 |  // r10 v7
   1 << 11;   // r11 v8 (fp in JavaScript code)
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 11a6145..dd3840a 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -341,7 +341,7 @@
 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
                                                int argc,
                                                Code::Kind kind,
-                                               Code::ExtraICState extra_state) {
+                                               ExtraICState extra_state) {
   // ----------- S t a t e -------------
   //  -- r1    : receiver
   //  -- r2    : name
@@ -445,7 +445,7 @@
 void CallICBase::GenerateMiss(MacroAssembler* masm,
                               int argc,
                               IC::UtilityId id,
-                              Code::ExtraICState extra_state) {
+                              ExtraICState extra_state) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
@@ -511,7 +511,7 @@
 
 void CallIC::GenerateMegamorphic(MacroAssembler* masm,
                                  int argc,
-                                 Code::ExtraICState extra_ic_state) {
+                                 ExtraICState extra_ic_state) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
@@ -610,7 +610,7 @@
   GenerateMonomorphicCacheProbe(masm,
                                 argc,
                                 Code::KEYED_CALL_IC,
-                                Code::kNoExtraICState);
+                                kNoExtraICState);
   // Fall through on miss.
 
   __ bind(&slow_call);
@@ -656,7 +656,7 @@
 
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeFlags(
-      Code::HANDLER, MONOMORPHIC, Code::kNoExtraICState,
+      Code::HANDLER, MONOMORPHIC, kNoExtraICState,
       Code::NORMAL, Code::LOAD_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, r0, r2, r3, r4, r5, r6);
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 467a1ac..d223b57 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -45,8 +45,8 @@
 
 
 // Give alias names to registers
-const Register pp = { kRegister_r7_Code };  // Constant pool pointer.
-const Register cp = { kRegister_r8_Code };  // JavaScript context pointer.
+const Register cp = { kRegister_r7_Code };  // JavaScript context pointer.
+const Register pp = { kRegister_r8_Code };  // Constant pool pointer.
 const Register kRootRegister = { kRegister_r10_Code };  // Roots array pointer.
 
 // Flags used for AllocateHeapNumber
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 00ea079..b93d67b 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -746,7 +746,7 @@
                                  Handle<Object> object,
                                  const ParameterCount& arguments,
                                  Label* miss,
-                                 Code::ExtraICState extra_ic_state) {
+                                 ExtraICState extra_ic_state) {
   // ----------- S t a t e -------------
   //  -- r0: receiver
   //  -- r1: function to call
@@ -757,11 +757,11 @@
   __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
   __ b(ne, miss);
 
-  // Patch the receiver on the stack with the global proxy if
-  // necessary.
   if (object->IsGlobalObject()) {
+    const int argc = arguments.immediate();
+    const int receiver_offset = argc * kPointerSize;
     __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
-    __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize));
+    __ str(r3, MemOperand(sp, receiver_offset));
   }
 
   // Invoke the function.
@@ -958,7 +958,7 @@
   CallInterceptorCompiler(StubCompiler* stub_compiler,
                           const ParameterCount& arguments,
                           Register name,
-                          Code::ExtraICState extra_ic_state)
+                          ExtraICState extra_ic_state)
       : stub_compiler_(stub_compiler),
         arguments_(arguments),
         name_(name),
@@ -1142,7 +1142,7 @@
   StubCompiler* stub_compiler_;
   const ParameterCount& arguments_;
   Register name_;
-  Code::ExtraICState extra_ic_state_;
+  ExtraICState extra_ic_state_;
 };
 
 
@@ -1541,25 +1541,6 @@
 }
 
 
-void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
-                                                   Handle<JSObject> holder,
-                                                   Handle<Name> name,
-                                                   Label* miss) {
-  ASSERT(holder->IsGlobalObject());
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-
-  // Get the receiver from the stack.
-  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
-
-  // Check that the maps haven't changed.
-  __ JumpIfSmi(r0, miss);
-  CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()), r0, holder, r3, r1, r4, name, miss);
-}
-
-
 void CallStubCompiler::GenerateLoadFunctionFromCell(
     Handle<Cell> cell,
     Handle<JSFunction> function,
@@ -1603,33 +1584,16 @@
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
                                                 Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
   Label miss;
 
-  GenerateNameCheck(name, &miss);
-
-  const int argc = arguments().immediate();
-
-  // Get the receiver of the function from the stack into r0.
-  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(r0, &miss);
-
-  // Do the right check and compute the holder register.
-  Register reg = CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()),
-      r0, holder, r1, r3, r4, name, &miss);
+  Register reg = HandlerFrontendHeader(
+      object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateFastPropertyLoad(masm(), r1, reg, index.is_inobject(holder),
                            index.translate(holder), Representation::Tagged());
 
   GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -1645,31 +1609,16 @@
     Code::StubType type) {
   Label miss;
 
-  // Check that function is still array
-  const int argc = arguments().immediate();
-  GenerateNameCheck(name, &miss);
-  Register receiver = r1;
-
-  if (cell.is_null()) {
-    __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
-
-    // Check that the receiver isn't a smi.
-    __ JumpIfSmi(receiver, &miss);
-
-    // Check that the maps haven't changed.
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()), receiver, holder,
-        r3, r0, r4, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
   Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
   site->SetElementsKind(GetInitialFastElementsKind());
   Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
+  const int argc = arguments().immediate();
   __ mov(r0, Operand(argc));
   __ mov(r2, Operand(site_feedback_cell));
   __ mov(r1, Operand(function));
@@ -1677,8 +1626,7 @@
   ArrayConstructorStub stub(isolate());
   __ TailCallStub(&stub);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1692,14 +1640,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1708,21 +1648,12 @@
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  Register receiver = r1;
-  // Get the receiver from the stack
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  Register receiver = r0;
+  Register scratch = r1;
+
   const int argc = arguments().immediate();
-  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(receiver, &miss);
-
-  // Check that the maps haven't changed.
-  CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()), receiver, holder,
-      r3, r0, r4, name, &miss);
-
   if (argc == 0) {
     // Nothing to do, just return the length.
     __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
@@ -1741,20 +1672,20 @@
 
       // Check that the elements are in fast mode and writable.
       __ CheckMap(elements,
-                  r0,
+                  scratch,
                   Heap::kFixedArrayMapRootIndex,
                   &check_double,
                   DONT_DO_SMI_CHECK);
 
-      // Get the array's length into r0 and calculate new length.
-      __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
-      __ add(r0, r0, Operand(Smi::FromInt(argc)));
+      // Get the array's length into scratch and calculate new length.
+      __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ add(scratch, scratch, Operand(Smi::FromInt(argc)));
 
       // Get the elements' length.
       __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
       // Check if we could survive without allocation.
-      __ cmp(r0, r4);
+      __ cmp(scratch, r4);
       __ b(gt, &attempt_to_grow_elements);
 
       // Check if value is a smi.
@@ -1762,49 +1693,50 @@
       __ JumpIfNotSmi(r4, &with_write_barrier);
 
       // Save new length.
-      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
       // Store the value.
       // We may need a register containing the address end_elements below,
       // so write back the value in end_elements.
-      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
+      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
       const int kEndElementsOffset =
           FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
       __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
 
       // Check for a smi.
       __ Drop(argc + 1);
+      __ mov(r0, scratch);
       __ Ret();
 
       __ bind(&check_double);
 
       // Check that the elements are in fast mode and writable.
       __ CheckMap(elements,
-                  r0,
+                  scratch,
                   Heap::kFixedDoubleArrayMapRootIndex,
                   &call_builtin,
                   DONT_DO_SMI_CHECK);
 
-      // Get the array's length into r0 and calculate new length.
-      __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
-      __ add(r0, r0, Operand(Smi::FromInt(argc)));
+      // Get the array's length into scratch and calculate new length.
+      __ ldr(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ add(scratch, scratch, Operand(Smi::FromInt(argc)));
 
       // Get the elements' length.
       __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
       // Check if we could survive without allocation.
-      __ cmp(r0, r4);
+      __ cmp(scratch, r4);
       __ b(gt, &call_builtin);
 
       __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
-      __ StoreNumberToDoubleElements(r4, r0, elements, r5, d0,
+      __ StoreNumberToDoubleElements(r4, scratch, elements, r5, d0,
                                      &call_builtin, argc * kDoubleSize);
 
       // Save new length.
-      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
-      // Check for a smi.
       __ Drop(argc + 1);
+      __ mov(r0, scratch);
       __ Ret();
 
       __ bind(&with_write_barrier);
@@ -1855,12 +1787,12 @@
       }
 
       // Save new length.
-      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
       // Store the value.
       // We may need a register containing the address end_elements below,
       // so write back the value in end_elements.
-      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
+      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
       __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
 
       __ RecordWrite(elements,
@@ -1871,10 +1803,11 @@
                      EMIT_REMEMBERED_SET,
                      OMIT_SMI_CHECK);
       __ Drop(argc + 1);
+      __ mov(r0, scratch);
       __ Ret();
 
       __ bind(&attempt_to_grow_elements);
-      // r0: array's length + 1.
+      // scratch: array's length + 1.
 
       if (!FLAG_inline_new) {
         __ b(&call_builtin);
@@ -1896,7 +1829,7 @@
 
       const int kAllocationDelta = 4;
       // Load top and check if it is the end of elements.
-      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
+      __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(scratch));
       __ add(end_elements, end_elements, Operand(kEndElementsOffset));
       __ mov(r4, Operand(new_space_allocation_top));
       __ ldr(r3, MemOperand(r4));
@@ -1921,13 +1854,14 @@
       }
 
       // Update elements' and array's sizes.
-      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
       __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
       __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
       __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
       // Elements are in new space, so write barrier is not required.
       __ Drop(argc + 1);
+      __ mov(r0, scratch);
       __ Ret();
     }
     __ bind(&call_builtin);
@@ -1935,9 +1869,7 @@
         ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1);
   }
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1951,14 +1883,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1967,26 +1891,18 @@
   }
 
   Label miss, return_undefined, call_builtin;
-  Register receiver = r1;
+  Register receiver = r0;
+  Register scratch = r1;
   Register elements = r3;
-  GenerateNameCheck(name, &miss);
 
-  // Get the receiver from the stack
-  const int argc = arguments().immediate();
-  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(receiver, &miss);
-
-  // Check that the maps haven't changed.
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), receiver, holder,
-                  elements, r4, r0, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   // Get the elements array of the object.
   __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
 
   // Check that the elements are in fast mode and writable.
   __ CheckMap(elements,
-              r0,
+              scratch,
               Heap::kFixedArrayMapRootIndex,
               &call_builtin,
               DONT_DO_SMI_CHECK);
@@ -2001,8 +1917,8 @@
   // We can't address the last element in one operation. Compute the more
   // expensive shift first, and use an offset later on.
   __ add(elements, elements, Operand::PointerOffsetFromSmiKey(r4));
-  __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
-  __ cmp(r0, r6);
+  __ ldr(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize));
+  __ cmp(scratch, r6);
   __ b(eq, &call_builtin);
 
   // Set the array's length.
@@ -2010,7 +1926,9 @@
 
   // Fill with the hole.
   __ str(r6, FieldMemOperand(elements, FixedArray::kHeaderSize));
+  const int argc = arguments().immediate();
   __ Drop(argc + 1);
+  __ mov(r0, scratch);
   __ Ret();
 
   __ bind(&return_undefined);
@@ -2022,9 +1940,7 @@
   __ TailCallExternalReference(
       ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2038,18 +1954,9 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
-  const int argc = arguments().immediate();
   Label miss;
   Label name_miss;
   Label index_out_of_range;
@@ -2060,22 +1967,13 @@
        DEFAULT_STRING_STUB)) {
     index_out_of_range_label = &miss;
   }
-  GenerateNameCheck(name, &name_miss);
 
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            r0,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate())));
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      r0, holder, r1, r3, r4, name, &miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
-  Register receiver = r1;
+  Register receiver = r0;
   Register index = r4;
-  Register result = r0;
+  Register result = r1;
+  const int argc = arguments().immediate();
   __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
   if (argc > 0) {
     __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
@@ -2092,6 +1990,7 @@
                                       STRING_INDEX_IS_NUMBER);
   generator.GenerateFast(masm());
   __ Drop(argc + 1);
+  __ mov(r0, result);
   __ Ret();
 
   StubRuntimeCallHelper call_helper;
@@ -2122,14 +2021,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
@@ -2143,24 +2034,13 @@
        DEFAULT_STRING_STUB)) {
     index_out_of_range_label = &miss;
   }
-  GenerateNameCheck(name, &name_miss);
 
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            r0,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate())));
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      r0, holder, r1, r3, r4, name, &miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = r0;
   Register index = r4;
   Register scratch = r3;
-  Register result = r0;
-  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
+  Register result = r1;
   if (argc > 0) {
     __ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
   } else {
@@ -2177,6 +2057,7 @@
                                   STRING_INDEX_IS_NUMBER);
   generator.GenerateFast(masm());
   __ Drop(argc + 1);
+  __ mov(r0, result);
   __ Ret();
 
   StubRuntimeCallHelper call_helper;
@@ -2207,14 +2088,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
 
   // If the object is not a JSObject or we got an unexpected number of
@@ -2222,20 +2095,10 @@
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
-
-    __ JumpIfSmi(r1, &miss);
-
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()),
-        r1, holder, r0, r3, r4, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2265,9 +2128,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // r2: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2281,32 +2142,16 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss, slow;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
-    __ JumpIfSmi(r1, &miss);
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()),
-        r1, holder, r0, r3, r4, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2375,9 +2220,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // r2: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2391,31 +2234,16 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- r2                     : function name
-  //  -- lr                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-  if (cell.is_null()) {
-    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
-    __ JumpIfSmi(r1, &miss);
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()),
-        r1, holder, r0, r3, r4, name, &miss);
-  } else {
+
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2475,9 +2303,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // r2: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2549,24 +2375,37 @@
 }
 
 
-void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
-                                              Handle<JSObject> holder,
-                                              Handle<Name> name,
-                                              CheckType check) {
+void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
+  if (object->IsGlobalObject()) {
+    const int argc = arguments().immediate();
+    const int receiver_offset = argc * kPointerSize;
+    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
+    __ str(r3, MemOperand(sp, receiver_offset));
+  }
+}
+
+
+Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
+                                                 Handle<JSObject> holder,
+                                                 Handle<Name> name,
+                                                 CheckType check,
+                                                 Label* miss) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
   // -----------------------------------
-  Label miss;
-  GenerateNameCheck(name, &miss);
+  GenerateNameCheck(name, miss);
+
+  Register reg = r0;
 
   // Get the receiver from the stack
   const int argc = arguments().immediate();
-  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+  const int receiver_offset = argc * kPointerSize;
+  __ ldr(r0, MemOperand(sp, receiver_offset));
 
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
-    __ JumpIfSmi(r1, &miss);
+    __ JumpIfSmi(r0, miss);
   }
 
   // Make sure that it's okay not to patch the on stack receiver
@@ -2574,85 +2413,62 @@
   ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
   switch (check) {
     case RECEIVER_MAP_CHECK:
-      __ IncrementCounter(isolate()->counters()->call_const(), 1, r0, r3);
+      __ IncrementCounter(isolate()->counters()->call_const(), 1, r1, r3);
 
       // Check that the maps haven't changed.
-      CheckPrototypes(
+      reg = CheckPrototypes(
           IC::CurrentTypeOf(object, isolate()),
-          r1, holder, r0, r3, r4, name, &miss);
-
-      // Patch the receiver on the stack with the global proxy if
-      // necessary.
-      if (object->IsGlobalObject()) {
-        __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
-        __ str(r3, MemOperand(sp, argc * kPointerSize));
-      }
+          reg, holder, r1, r3, r4, name, miss);
       break;
 
     case STRING_CHECK: {
       // Check that the object is a string.
-      __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
-      __ b(ge, &miss);
+      __ CompareObjectType(reg, r3, r3, FIRST_NONSTRING_TYPE);
+      __ b(ge, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::STRING_FUNCTION_INDEX, r0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          r0, holder, r3, r1, r4, name, &miss);
+          masm(), Context::STRING_FUNCTION_INDEX, r1, miss);
       break;
     }
     case SYMBOL_CHECK: {
       // Check that the object is a symbol.
-      __ CompareObjectType(r1, r1, r3, SYMBOL_TYPE);
-      __ b(ne, &miss);
+      __ CompareObjectType(reg, r3, r3, SYMBOL_TYPE);
+      __ b(ne, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::SYMBOL_FUNCTION_INDEX, r0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          r0, holder, r3, r1, r4, name, &miss);
+          masm(), Context::SYMBOL_FUNCTION_INDEX, r1, miss);
       break;
     }
     case NUMBER_CHECK: {
       Label fast;
       // Check that the object is a smi or a heap number.
-      __ JumpIfSmi(r1, &fast);
-      __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
-      __ b(ne, &miss);
+      __ JumpIfSmi(reg, &fast);
+      __ CompareObjectType(reg, r3, r3, HEAP_NUMBER_TYPE);
+      __ b(ne, miss);
       __ bind(&fast);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          r0, holder, r3, r1, r4, name, &miss);
+          masm(), Context::NUMBER_FUNCTION_INDEX, r1, miss);
       break;
     }
     case BOOLEAN_CHECK: {
-      GenerateBooleanCheck(r1, &miss);
+      GenerateBooleanCheck(reg, miss);
 
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          r0, holder, r3, r1, r4, name, &miss);
+          masm(), Context::BOOLEAN_FUNCTION_INDEX, r1, miss);
       break;
     }
   }
 
-  Label success;
-  __ b(&success);
+  if (check != RECEIVER_MAP_CHECK) {
+    Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
+    reg = CheckPrototypes(
+        IC::CurrentTypeOf(prototype, isolate()),
+        r1, holder, r1, r3, r4, name, miss);
+  }
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
-
-  __ bind(&success);
+  return reg;
 }
 
 
@@ -2681,8 +2497,11 @@
     if (!code.is_null()) return code;
   }
 
-  CompileHandlerFrontend(object, holder, name, check);
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
+  PatchGlobalProxy(object);
   CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(function);
@@ -2692,10 +2511,6 @@
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
                                                       Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
   Label miss;
   GenerateNameCheck(name, &miss);
 
@@ -2733,10 +2548,6 @@
     Handle<PropertyCell> cell,
     Handle<JSFunction> function,
     Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
         object, holder, cell, function, Handle<String>::cast(name),
@@ -2746,19 +2557,9 @@
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-  GenerateGlobalReceiverCheck(object, holder, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateLoadFunctionFromCell(cell, function, &miss);
-
-  // Patch the receiver on the stack with the global proxy if
-  // necessary.
-  if (object->IsGlobalObject()) {
-    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
-    __ str(r3, MemOperand(sp, argc * kPointerSize));
-  }
+  PatchGlobalProxy(object);
 
   // Set up the context (function already in r1).
   __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
@@ -2777,10 +2578,7 @@
   __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
                 NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::NORMAL, name);
@@ -2897,13 +2695,10 @@
 
   __ Push(receiver(), this->name(), value());
 
-  __ mov(scratch1(), Operand(Smi::FromInt(strict_mode())));
-  __ push(scratch1());  // strict mode
-
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
-  __ TailCallExternalReference(store_ic_property, 4, 1);
+  __ TailCallExternalReference(store_ic_property, 3, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
diff --git a/src/ast.cc b/src/ast.cc
index 20881bd..85482fa 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -580,37 +580,6 @@
 }
 
 
-void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
-                                  Zone* zone) {
-  // Record type feedback from the oracle in the AST.
-  is_uninitialized_ = oracle->LoadIsUninitialized(this);
-  if (is_uninitialized_) return;
-
-  is_pre_monomorphic_ = oracle->LoadIsPreMonomorphic(this);
-  is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
-  ASSERT(!is_pre_monomorphic_ || !is_monomorphic_);
-  receiver_types_.Clear();
-  if (key()->IsPropertyName()) {
-    FunctionPrototypeStub proto_stub(Code::LOAD_IC);
-    if (oracle->LoadIsStub(this, &proto_stub)) {
-      is_function_prototype_ = true;
-    } else {
-      Literal* lit_key = key()->AsLiteral();
-      ASSERT(lit_key != NULL && lit_key->value()->IsString());
-      Handle<String> name = Handle<String>::cast(lit_key->value());
-      oracle->LoadReceiverTypes(this, name, &receiver_types_);
-    }
-  } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
-    is_string_access_ = true;
-  } else if (is_monomorphic_) {
-    receiver_types_.Add(oracle->LoadMonomorphicReceiverType(this), zone);
-  } else if (oracle->LoadIsPolymorphic(this)) {
-    receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
-    oracle->CollectKeyedReceiverTypes(PropertyFeedbackId(), &receiver_types_);
-  }
-}
-
-
 void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle,
                                     Zone* zone) {
   Property* prop = target()->AsProperty();
diff --git a/src/ast.h b/src/ast.h
index 33ede16..3febc16 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1691,7 +1691,6 @@
   bool IsFunctionPrototype() const { return is_function_prototype_; }
 
   // Type feedback information.
-  void RecordTypeFeedback(TypeFeedbackOracle* oracle, Zone* zone);
   virtual bool IsMonomorphic() V8_OVERRIDE { return is_monomorphic_; }
   virtual SmallMapList* GetReceiverTypes() V8_OVERRIDE {
     return &receiver_types_;
@@ -1704,6 +1703,12 @@
   bool HasNoTypeInformation() {
     return is_uninitialized_ || is_pre_monomorphic_;
   }
+  void set_is_uninitialized(bool b) { is_uninitialized_ = b; }
+  void set_is_monomorphic(bool b) { is_monomorphic_ = b; }
+  void set_is_pre_monomorphic(bool b) { is_pre_monomorphic_ = b; }
+  void set_is_string_access(bool b) { is_string_access_ = b; }
+  void set_is_function_prototype(bool b) { is_function_prototype_ = b; }
+
   TypeFeedbackId PropertyFeedbackId() { return reuse(id()); }
 
  protected:
diff --git a/src/builtins.cc b/src/builtins.cc
index 999969d..1b62223 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -276,15 +276,10 @@
   FixedArrayBase* new_elms = FixedArrayBase::cast(HeapObject::FromAddress(
       elms->address() + size_delta));
   HeapProfiler* profiler = heap->isolate()->heap_profiler();
-  if (profiler->is_profiling()) {
+  if (profiler->is_tracking_object_moves()) {
     profiler->ObjectMoveEvent(elms->address(),
                               new_elms->address(),
                               new_elms->Size());
-    if (profiler->is_tracking_allocations()) {
-      // Report filler object as a new allocation.
-      // Otherwise it will become an untracked object.
-      profiler->NewObjectEvent(elms->address(), elms->Size());
-    }
   }
   return new_elms;
 }
@@ -1658,7 +1653,7 @@
     functions->s_name = #aname;                                             \
     functions->name = k##aname;                                             \
     functions->flags = Code::ComputeFlags(                                  \
-        Code::HANDLER, MONOMORPHIC, Code::kNoExtraICState,                  \
+        Code::HANDLER, MONOMORPHIC, kNoExtraICState,                        \
         Code::NORMAL, Code::kind);                                          \
     functions->extra_args = NO_EXTRA_ARGUMENTS;                             \
     ++functions;
diff --git a/src/builtins.h b/src/builtins.h
index e569e8f..f76ed02 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -58,9 +58,9 @@
 
 #define DECLARE_CODE_AGE_BUILTIN(C, V)             \
   V(Make##C##CodeYoungAgainOddMarking, BUILTIN,    \
-    UNINITIALIZED, Code::kNoExtraICState)          \
+    UNINITIALIZED, kNoExtraICState)                \
   V(Make##C##CodeYoungAgainEvenMarking, BUILTIN,   \
-    UNINITIALIZED, Code::kNoExtraICState)
+    UNINITIALIZED, kNoExtraICState)
 
 
 // Define list of builtins implemented in C++.
@@ -87,132 +87,132 @@
 // Define list of builtins implemented in assembly.
 #define BUILTIN_LIST_A(V)                                               \
   V(ArgumentsAdaptorTrampoline,     BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(InRecompileQueue,               BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(JSConstructStubCountdown,       BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(JSConstructStubGeneric,         BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(JSConstructStubApi,             BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(JSEntryTrampoline,              BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(JSConstructEntryTrampoline,     BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(LazyCompile,                    BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(LazyRecompile,                  BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(ConcurrentRecompile,            BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(NotifyDeoptimized,              BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(NotifySoftDeoptimized,          BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(NotifyLazyDeoptimized,          BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(NotifyStubFailure,              BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(NotifyStubFailureSaveDoubles,   BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
                                                                         \
   V(LoadIC_Miss,                    BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(KeyedLoadIC_Miss,               BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(StoreIC_Miss,                   BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(KeyedStoreIC_Miss,              BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(LoadIC_Initialize,              LOAD_IC, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(LoadIC_PreMonomorphic,          LOAD_IC, PREMONOMORPHIC,            \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(LoadIC_Megamorphic,             LOAD_IC, MEGAMORPHIC,               \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(LoadIC_Getter_ForDeopt,         LOAD_IC, MONOMORPHIC,               \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
                                                                         \
   V(KeyedLoadIC_Initialize,         KEYED_LOAD_IC, UNINITIALIZED,       \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(KeyedLoadIC_PreMonomorphic,     KEYED_LOAD_IC, PREMONOMORPHIC,      \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(KeyedLoadIC_Generic,            KEYED_LOAD_IC, GENERIC,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(KeyedLoadIC_String,             KEYED_LOAD_IC, MEGAMORPHIC,         \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(KeyedLoadIC_IndexedInterceptor, KEYED_LOAD_IC, MONOMORPHIC,         \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(KeyedLoadIC_NonStrictArguments, KEYED_LOAD_IC, MONOMORPHIC,         \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
                                                                         \
   V(StoreIC_Initialize,             STORE_IC, UNINITIALIZED,            \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(StoreIC_PreMonomorphic,         STORE_IC, PREMONOMORPHIC,           \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(StoreIC_Megamorphic,            STORE_IC, MEGAMORPHIC,              \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(StoreIC_Generic,                STORE_IC, GENERIC,                  \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(StoreIC_Generic_Strict,         STORE_IC, GENERIC,                  \
-                                    kStrictMode)                        \
+                                    StoreIC::kStrictModeState)          \
   V(StoreIC_GlobalProxy,            STORE_IC, GENERIC,                  \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(StoreIC_Initialize_Strict,      STORE_IC, UNINITIALIZED,            \
-                                    kStrictMode)                        \
+                                    StoreIC::kStrictModeState)          \
   V(StoreIC_PreMonomorphic_Strict,  STORE_IC, PREMONOMORPHIC,           \
-                                    kStrictMode)                        \
+                                    StoreIC::kStrictModeState)          \
   V(StoreIC_Megamorphic_Strict,     STORE_IC, MEGAMORPHIC,              \
-                                    kStrictMode)                        \
+                                    StoreIC::kStrictModeState)          \
   V(StoreIC_GlobalProxy_Strict,     STORE_IC, GENERIC,                  \
-                                    kStrictMode)                        \
+                                    StoreIC::kStrictModeState)          \
   V(StoreIC_Setter_ForDeopt,        STORE_IC, MONOMORPHIC,              \
-                                    kStrictMode)                        \
+                                    StoreIC::kStrictModeState)          \
                                                                         \
   V(KeyedStoreIC_Initialize,        KEYED_STORE_IC, UNINITIALIZED,      \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(KeyedStoreIC_PreMonomorphic,    KEYED_STORE_IC, PREMONOMORPHIC,     \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(KeyedStoreIC_Generic,           KEYED_STORE_IC, GENERIC,            \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
                                                                         \
   V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC, UNINITIALIZED,      \
-                                    kStrictMode)                        \
+                                    StoreIC::kStrictModeState)          \
   V(KeyedStoreIC_PreMonomorphic_Strict, KEYED_STORE_IC, PREMONOMORPHIC, \
-                                    kStrictMode)                        \
+                                    StoreIC::kStrictModeState)          \
   V(KeyedStoreIC_Generic_Strict,    KEYED_STORE_IC, GENERIC,            \
-                                    kStrictMode)                        \
+                                    StoreIC::kStrictModeState)          \
   V(KeyedStoreIC_NonStrictArguments, KEYED_STORE_IC, MONOMORPHIC,       \
-                                     Code::kNoExtraICState)             \
+                                     kNoExtraICState)                   \
                                                                         \
   /* Uses KeyedLoadIC_Initialize; must be after in list. */             \
   V(FunctionCall,                   BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(FunctionApply,                  BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
                                                                         \
   V(InternalArrayCode,              BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(ArrayCode,                      BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
                                                                         \
   V(StringConstructCode,            BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
                                                                         \
   V(OnStackReplacement,             BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(InterruptCheck,                 BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(OsrAfterStackCheck,             BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(StackCheck,                     BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
                                                                         \
   V(MarkCodeAsExecutedOnce,         BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   V(MarkCodeAsExecutedTwice,        BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
+                                    kNoExtraICState)                    \
   CODE_AGE_LIST_WITH_ARG(DECLARE_CODE_AGE_BUILTIN, V)
 
 // Define list of builtin handlers implemented in assembly.
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 52b5942..e20060f 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -193,8 +193,8 @@
   virtual InlineCacheState GetICState() {
     return UNINITIALIZED;
   }
-  virtual Code::ExtraICState GetExtraICState() {
-    return Code::kNoExtraICState;
+  virtual ExtraICState GetExtraICState() {
+    return kNoExtraICState;
   }
   virtual Code::StubType GetStubType() {
     return Code::NORMAL;
@@ -846,8 +846,8 @@
       : ICStub(kind), strict_mode_(strict_mode) { }
 
  protected:
-  virtual Code::ExtraICState GetExtraICState() {
-    return strict_mode_;
+  virtual ExtraICState GetExtraICState() {
+    return StoreIC::ComputeExtraICState(strict_mode_);
   }
 
  private:
@@ -982,7 +982,7 @@
       Isolate* isolate,
       CodeStubInterfaceDescriptor* descriptor);
 
-  virtual Code::ExtraICState GetExtraICState() { return bit_field_; }
+  virtual ExtraICState GetExtraICState() { return bit_field_; }
 
   bool is_constant() {
     return IsConstantBits::decode(bit_field_);
@@ -1036,7 +1036,7 @@
   }
 
   virtual Code::Kind kind() const { return Code::KEYED_CALL_IC; }
-  virtual Code::ExtraICState GetExtraICState() { return bit_field_; }
+  virtual ExtraICState GetExtraICState() { return bit_field_; }
 
   ElementsKind elements_kind() {
     return HoleyBits::decode(bit_field_) ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
@@ -1046,7 +1046,7 @@
   virtual int GetStubFlags() { return argc(); }
 
   static bool IsHoley(Handle<Code> code) {
-    Code::ExtraICState state = code->extra_ic_state();
+    ExtraICState state = code->extra_ic_state();
     return HoleyBits::decode(state);
   }
 
@@ -1081,7 +1081,7 @@
     Initialize();
   }
 
-  explicit BinaryOpStub(Code::ExtraICState state)
+  explicit BinaryOpStub(ExtraICState state)
       : op_(decode_token(OpBits::decode(state))),
         mode_(OverwriteModeField::decode(state)),
         fixed_right_arg_(
@@ -1124,7 +1124,7 @@
     ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
   }
 
-  virtual Code::ExtraICState GetExtraICState() {
+  virtual ExtraICState GetExtraICState() {
     bool sse_field = Max(result_state_, Max(left_state_, right_state_)) > SMI &&
                      CpuFeatures::IsSafeForSnapshot(SSE2);
 
@@ -1364,7 +1364,7 @@
 
   explicit CompareNilICStub(NilValue nil) : nil_value_(nil) { }
 
-  CompareNilICStub(Code::ExtraICState ic_state,
+  CompareNilICStub(ExtraICState ic_state,
                    InitializationState init_state = INITIALIZED)
       : HydrogenCodeStub(init_state),
         nil_value_(NilValueField::decode(ic_state)),
@@ -1401,7 +1401,7 @@
 
   virtual Handle<Code> GenerateCode(Isolate* isolate);
 
-  virtual Code::ExtraICState GetExtraICState() {
+  virtual ExtraICState GetExtraICState() {
     return NilValueField::encode(nil_value_) |
            TypesField::encode(state_.ToIntegral());
   }
@@ -2330,7 +2330,7 @@
 
   explicit ToBooleanStub(Types types = Types())
       : types_(types) { }
-  explicit ToBooleanStub(Code::ExtraICState state)
+  explicit ToBooleanStub(ExtraICState state)
       : types_(static_cast<byte>(state)) { }
 
   bool UpdateStatus(Handle<Object> object);
@@ -2357,7 +2357,7 @@
     return ToBooleanStub(UNINITIALIZED).GetCode(isolate);
   }
 
-  virtual Code::ExtraICState GetExtraICState() {
+  virtual ExtraICState GetExtraICState() {
     return types_.ToIntegral();
   }
 
diff --git a/src/compiler.cc b/src/compiler.cc
index 1ec2626..83f9ab2 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -324,9 +324,9 @@
 }
 
 
-class HOptimizedGraphBuilderWithPotisions: public HOptimizedGraphBuilder {
+class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
  public:
-  explicit HOptimizedGraphBuilderWithPotisions(CompilationInfo* info)
+  explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
       : HOptimizedGraphBuilder(info) {
   }
 
@@ -468,7 +468,7 @@
   AstTyper::Run(info());
 
   graph_builder_ = FLAG_emit_opt_code_positions
-      ? new(info()->zone()) HOptimizedGraphBuilderWithPotisions(info())
+      ? new(info()->zone()) HOptimizedGraphBuilderWithPositions(info())
       : new(info()->zone()) HOptimizedGraphBuilder(info());
 
   Timer t(this, &time_taken_to_create_graph_);
@@ -513,7 +513,7 @@
   ASSERT(graph_ != NULL);
   BailoutReason bailout_reason = kNoReason;
   if (!graph_->Optimize(&bailout_reason)) {
-    if (bailout_reason == kNoReason) graph_builder_->Bailout(bailout_reason);
+    if (bailout_reason != kNoReason) graph_builder_->Bailout(bailout_reason);
     return SetLastStatus(BAILED_OUT);
   } else {
     chunk_ = LChunk::NewChunk(graph_);
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 077337f..76f2fa9 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -1522,6 +1522,7 @@
   output_frame->SetRegister(context_reg.code(), value);
   output_frame_offset -= kPointerSize;
   output_frame->SetFrameSlot(output_frame_offset, value);
+  ASSERT(reinterpret_cast<Object*>(value)->IsContext());
   if (trace_scope_ != NULL) {
     PrintF(trace_scope_->file(),
            "    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 2d4b10e..525c634 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -236,7 +236,7 @@
       space = retry_space;
     } else {
       if (profiler->is_tracking_allocations() && result->To(&object)) {
-        profiler->NewObjectEvent(object->address(), size_in_bytes);
+        profiler->AllocationEvent(object->address(), size_in_bytes);
       }
       return result;
     }
@@ -260,7 +260,7 @@
   }
   if (result->IsFailure()) old_gen_exhausted_ = true;
   if (profiler->is_tracking_allocations() && result->To(&object)) {
-    profiler->NewObjectEvent(object->address(), size_in_bytes);
+    profiler->AllocationEvent(object->address(), size_in_bytes);
   }
   return result;
 }
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index a4ec5a9..6f99360 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -36,7 +36,8 @@
 HeapProfiler::HeapProfiler(Heap* heap)
     : snapshots_(new HeapSnapshotsCollection(heap)),
       next_snapshot_uid_(1),
-      is_tracking_allocations_(false) {
+      is_tracking_allocations_(false),
+      is_tracking_object_moves_(false) {
 }
 
 
@@ -84,6 +85,7 @@
     }
   }
   snapshots_->SnapshotGenerationFinished(result);
+  is_tracking_object_moves_ = true;
   return result;
 }
 
@@ -98,6 +100,7 @@
 
 void HeapProfiler::StartHeapObjectsTracking() {
   snapshots_->StartHeapObjectsTracking();
+  is_tracking_object_moves_ = true;
 }
 
 
@@ -138,8 +141,8 @@
 }
 
 
-void HeapProfiler::NewObjectEvent(Address addr, int size) {
-  snapshots_->NewObjectEvent(addr, size);
+void HeapProfiler::AllocationEvent(Address addr, int size) {
+  snapshots_->AllocationEvent(addr, size);
 }
 
 
@@ -159,7 +162,6 @@
   StartHeapObjectsTracking();
   heap()->DisableInlineAllocation();
   is_tracking_allocations_ = true;
-  snapshots_->UpdateHeapObjectsMap();
 }
 
 
diff --git a/src/heap-profiler.h b/src/heap-profiler.h
index f2e8100..866a678 100644
--- a/src/heap-profiler.h
+++ b/src/heap-profiler.h
@@ -64,7 +64,7 @@
 
   void ObjectMoveEvent(Address from, Address to, int size);
 
-  void NewObjectEvent(Address addr, int size);
+  void AllocationEvent(Address addr, int size);
 
   void UpdateObjectSizeEvent(Address addr, int size);
 
@@ -73,15 +73,10 @@
 
   v8::RetainedObjectInfo* ExecuteWrapperClassCallback(uint16_t class_id,
                                                       Object** wrapper);
-  INLINE(bool is_profiling()) {
-    return snapshots_->is_tracking_objects();
-  }
-
   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
 
-  bool is_tracking_allocations() {
-    return is_tracking_allocations_;
-  }
+  bool is_tracking_object_moves() const { return is_tracking_object_moves_; }
+  bool is_tracking_allocations() const { return is_tracking_allocations_; }
 
   void StartHeapAllocationsRecording();
   void StopHeapAllocationsRecording();
@@ -97,6 +92,7 @@
   unsigned next_snapshot_uid_;
   List<v8::HeapProfiler::WrapperInfoCallback> wrapper_callbacks_;
   bool is_tracking_allocations_;
+  bool is_tracking_object_moves_;
 };
 
 } }  // namespace v8::internal
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 7e74d86..b77414b 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -446,18 +446,6 @@
 }
 
 
-void HeapObjectsMap::NewObject(Address addr, int size) {
-  if (FLAG_heap_profiler_trace_objects) {
-    PrintF("New object         : %p %6d. Next address is %p\n",
-           addr,
-           size,
-           addr + size);
-  }
-  ASSERT(addr != NULL);
-  FindOrAddEntry(addr, size, false);
-}
-
-
 void HeapObjectsMap::UpdateObjectSize(Address addr, int size) {
   FindOrAddEntry(addr, size, false);
 }
@@ -747,8 +735,7 @@
 
 
 HeapSnapshotsCollection::HeapSnapshotsCollection(Heap* heap)
-    : is_tracking_objects_(false),
-      names_(heap),
+    : names_(heap),
       ids_(heap),
       allocation_tracker_(NULL) {
 }
@@ -770,7 +757,6 @@
   if (allocation_tracker_ == NULL) {
     allocation_tracker_ = new AllocationTracker(&ids_, names());
   }
-  is_tracking_objects_ = true;
 }
 
 
@@ -785,7 +771,6 @@
 
 HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(const char* name,
                                                    unsigned uid) {
-  is_tracking_objects_ = true;  // Start watching for heap objects moves.
   return new HeapSnapshot(this, name, uid);
 }
 
@@ -826,11 +811,10 @@
 }
 
 
-void HeapSnapshotsCollection::NewObjectEvent(Address addr, int size) {
+void HeapSnapshotsCollection::AllocationEvent(Address addr, int size) {
   DisallowHeapAllocation no_allocation;
-  ids_.NewObject(addr, size);
   if (allocation_tracker_ != NULL) {
-    allocation_tracker_->NewObjectEvent(addr, size);
+    allocation_tracker_->AllocationEvent(addr, size);
   }
 }
 
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index c69d5e5..8fa840c 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -233,7 +233,6 @@
                                   unsigned int size,
                                   bool accessed = true);
   void MoveObject(Address from, Address to, int size);
-  void NewObject(Address addr, int size);
   void UpdateObjectSize(Address addr, int size);
   SnapshotObjectId last_assigned_id() const {
     return next_id_ - kObjectIdStep;
@@ -294,7 +293,6 @@
 
   Heap* heap() const { return ids_.heap(); }
 
-  bool is_tracking_objects() { return is_tracking_objects_; }
   SnapshotObjectId PushHeapObjectsStats(OutputStream* stream) {
     return ids_.PushHeapObjectsStats(stream);
   }
@@ -319,7 +317,7 @@
   void ObjectMoveEvent(Address from, Address to, int size) {
     ids_.MoveObject(from, to, size);
   }
-  void NewObjectEvent(Address addr, int size);
+  void AllocationEvent(Address addr, int size);
   void UpdateObjectSizeEvent(Address addr, int size) {
     ids_.UpdateObjectSize(addr, size);
   }
@@ -330,10 +328,7 @@
 
   int FindUntrackedObjects() { return ids_.FindUntrackedObjects(); }
 
-  void UpdateHeapObjectsMap() { ids_.UpdateHeapObjectsMap(); }
-
  private:
-  bool is_tracking_objects_;  // Whether tracking object moves is needed.
   List<HeapSnapshot*> snapshots_;
   StringsStorage names_;
   // Mapping from HeapObject addresses to objects' uids.
diff --git a/src/heap.cc b/src/heap.cc
index 86efe4b..d5c40ad 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2196,7 +2196,7 @@
       RecordCopiedObject(heap, target);
       Isolate* isolate = heap->isolate();
       HeapProfiler* heap_profiler = isolate->heap_profiler();
-      if (heap_profiler->is_profiling()) {
+      if (heap_profiler->is_tracking_object_moves()) {
         heap_profiler->ObjectMoveEvent(source->address(), target->address(),
                                        size);
       }
@@ -2447,7 +2447,7 @@
       isolate()->logger()->is_logging() ||
       isolate()->cpu_profiler()->is_profiling() ||
       (isolate()->heap_profiler() != NULL &&
-       isolate()->heap_profiler()->is_profiling());
+       isolate()->heap_profiler()->is_tracking_object_moves());
 
   if (!incremental_marking()->IsMarking()) {
     if (!logging_and_profiling) {
@@ -4885,13 +4885,6 @@
       AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
           reinterpret_cast<Address>(clone) + object_size);
       InitializeAllocationMemento(alloc_memento, site);
-      HeapProfiler* profiler = isolate()->heap_profiler();
-      if (profiler->is_tracking_allocations()) {
-        profiler->UpdateObjectSizeEvent(HeapObject::cast(clone)->address(),
-                                        object_size);
-        profiler->NewObjectEvent(alloc_memento->address(),
-                                 AllocationMemento::kSize);
-      }
     }
   }
 
diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc
index f712a39..5333221 100644
--- a/src/hydrogen-check-elimination.cc
+++ b/src/hydrogen-check-elimination.cc
@@ -27,59 +27,160 @@
 
 #include "hydrogen-check-elimination.h"
 #include "hydrogen-alias-analysis.h"
+#include "hydrogen-flow-engine.h"
+
+#define GLOBAL 1
+
+// Only collect stats in debug mode.
+#if DEBUG
+#define INC_STAT(x) phase_->x++
+#else
+#define INC_STAT(x)
+#endif
+
+// For code de-uglification.
+#define TRACE(x) if (FLAG_trace_check_elimination) PrintF x
 
 namespace v8 {
 namespace internal {
 
-static const int kMaxTrackedObjects = 10;
 typedef UniqueSet<Map>* MapSet;
 
+struct HCheckTableEntry {
+  HValue* object_;  // The object being approximated. NULL => invalid entry.
+  HValue* check_;   // The last check instruction.
+  MapSet maps_;     // The set of known maps for the object.
+};
+
+
 // The main datastructure used during check elimination, which stores a
 // set of known maps for each object.
-class HCheckTable {
+class HCheckTable : public ZoneObject {
  public:
-  explicit HCheckTable(Zone* zone) : zone_(zone) {
-    Kill();
-    redundant_ = 0;
-    narrowed_ = 0;
-    empty_ = 0;
-    removed_ = 0;
-    compares_true_ = 0;
-    compares_false_ = 0;
-    transitions_ = 0;
-    loads_ = 0;
+  static const int kMaxTrackedObjects = 10;
+
+  explicit HCheckTable(HCheckEliminationPhase* phase)
+    : phase_(phase),
+      cursor_(0),
+      size_(0) {
+  }
+
+  // The main processing of instructions.
+  HCheckTable* Process(HInstruction* instr, Zone* zone) {
+    switch (instr->opcode()) {
+      case HValue::kCheckMaps: {
+        ReduceCheckMaps(HCheckMaps::cast(instr));
+        break;
+      }
+      case HValue::kCheckValue: {
+        ReduceCheckValue(HCheckValue::cast(instr));
+        break;
+      }
+      case HValue::kLoadNamedField: {
+        ReduceLoadNamedField(HLoadNamedField::cast(instr));
+        break;
+      }
+      case HValue::kStoreNamedField: {
+        ReduceStoreNamedField(HStoreNamedField::cast(instr));
+        break;
+      }
+      case HValue::kCompareMap: {
+        ReduceCompareMap(HCompareMap::cast(instr));
+        break;
+      }
+      case HValue::kTransitionElementsKind: {
+        ReduceTransitionElementsKind(
+            HTransitionElementsKind::cast(instr));
+        break;
+      }
+      case HValue::kCheckMapValue: {
+        ReduceCheckMapValue(HCheckMapValue::cast(instr));
+        break;
+      }
+      default: {
+        // If the instruction changes maps uncontrollably, drop everything.
+        if (instr->CheckGVNFlag(kChangesMaps) ||
+            instr->CheckGVNFlag(kChangesOsrEntries)) {
+          Kill();
+        }
+      }
+      // Improvements possible:
+      // - eliminate HCheckSmi and HCheckHeapObject
+    }
+
+    return this;
+  }
+
+  // Global analysis: Copy state to successor block.
+  HCheckTable* Copy(HBasicBlock* succ, Zone* zone) {
+    HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_);
+    for (int i = 0; i < size_; i++) {
+      HCheckTableEntry* old_entry = &entries_[i];
+      HCheckTableEntry* new_entry = &copy->entries_[i];
+      // TODO(titzer): keep the check if this block dominates the successor?
+      new_entry->object_ = old_entry->object_;
+      new_entry->check_ = NULL;
+      new_entry->maps_ = old_entry->maps_->Copy(phase_->zone());
+    }
+    return copy;
+  }
+
+  // Global analysis: Merge this state with the other incoming state.
+  HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that, Zone* zone) {
+    if (that->size_ == 0) {
+      // If the other state is empty, simply reset.
+      size_ = 0;
+      cursor_ = 0;
+      return this;
+    }
+    bool compact = false;
+    for (int i = 0; i < size_; i++) {
+      HCheckTableEntry* this_entry = &entries_[i];
+      HCheckTableEntry* that_entry = that->Find(this_entry->object_);
+      if (that_entry == NULL) {
+        this_entry->object_ = NULL;
+        compact = true;
+      } else {
+        this_entry->maps_ = this_entry->maps_->Union(
+            that_entry->maps_, phase_->zone());
+        if (this_entry->check_ != that_entry->check_) this_entry->check_ = NULL;
+        ASSERT(this_entry->maps_->size() > 0);
+      }
+    }
+    if (compact) Compact();
+    return this;
   }
 
   void ReduceCheckMaps(HCheckMaps* instr) {
     HValue* object = instr->value()->ActualValue();
-    int index = Find(object);
-    if (index >= 0) {
+    HCheckTableEntry* entry = Find(object);
+    if (entry != NULL) {
       // entry found;
-      MapSet a = known_maps_[index];
-      MapSet i = instr->map_set().Copy(zone_);
+      MapSet a = entry->maps_;
+      MapSet i = instr->map_set().Copy(phase_->zone());
       if (a->IsSubset(i)) {
         // The first check is more strict; the second is redundant.
-        if (checks_[index] != NULL) {
-          instr->DeleteAndReplaceWith(checks_[index]);
-          redundant_++;
+        if (entry->check_ != NULL) {
+          instr->DeleteAndReplaceWith(entry->check_);
+          INC_STAT(redundant_);
         } else {
           instr->DeleteAndReplaceWith(instr->value());
-          removed_++;
+          INC_STAT(removed_);
         }
         return;
       }
-      i = i->Intersect(a, zone_);
+      i = i->Intersect(a, phase_->zone());
       if (i->size() == 0) {
         // Intersection is empty; probably megamorphic, which is likely to
         // deopt anyway, so just leave things as they are.
-        empty_++;
+        INC_STAT(empty_);
       } else {
-        // TODO(titzer): replace the first check with a more strict check.
-        narrowed_++;
+        // TODO(titzer): replace the first check with a more strict check
+        INC_STAT(narrowed_);
       }
     } else {
       // No entry; insert a new one.
-      Insert(object, instr, instr->map_set().Copy(zone_));
+      Insert(object, instr, instr->map_set().Copy(phase_->zone()));
     }
   }
 
@@ -88,10 +189,10 @@
     HValue* value = instr->Canonicalize();
     if (value == NULL) {
       instr->DeleteAndReplaceWith(instr->value());
-      removed_++;
+      INC_STAT(removed_);
     } else if (value != instr) {
       instr->DeleteAndReplaceWith(value);
-      redundant_++;
+      INC_STAT(redundant_);
     }
   }
 
@@ -107,7 +208,7 @@
     HConstant* constant = HConstant::CreateAndInsertBefore(
         instr->block()->graph()->zone(), map, true, instr);
     instr->DeleteAndReplaceWith(constant);
-    loads_++;
+    INC_STAT(loads_);
   }
 
   void ReduceCheckMapValue(HCheckMapValue* instr) {
@@ -122,11 +223,11 @@
         if (maps->size() == 1) {
           // Object is known to have exactly this map.
           instr->DeleteAndReplaceWith(NULL);
-          removed_++;
+          INC_STAT(removed_);
         } else {
           // Only one map survives the check.
           maps->Clear();
-          maps->Add(map, zone_);
+          maps->Add(map, phase_->zone());
         }
       }
     } else {
@@ -146,10 +247,9 @@
       Kill(object);
       if (!instr->value()->IsConstant()) return;
       Insert(object, MapConstant(instr->value()));
-    } else if (instr->CheckGVNFlag(kChangesMaps)) {
-      // This store indirectly changes the map of the object.
-      Kill(instr->object());
-      UNREACHABLE();
+    } else {
+      // If the instruction changes maps, it should be handled above.
+      CHECK(!instr->CheckGVNFlag(kChangesMaps));
     }
   }
 
@@ -157,11 +257,13 @@
     MapSet maps = FindMaps(instr->value()->ActualValue());
     if (maps == NULL) return;
     if (maps->Contains(instr->map())) {
-      // TODO(titzer): replace with goto true branch
-      if (maps->size() == 1) compares_true_++;
+      if (maps->size() == 1) {
+        // TODO(titzer): replace with goto true branch
+        INC_STAT(compares_true_);
+      }
     } else {
       // TODO(titzer): replace with goto false branch
-      compares_false_++;
+      INC_STAT(compares_false_);
     }
   }
 
@@ -172,36 +274,76 @@
     if (maps->Contains(instr->original_map())) {
       // If the object has the original map, it will be transitioned.
       maps->Remove(instr->original_map());
-      maps->Add(instr->transitioned_map(), zone_);
+      maps->Add(instr->transitioned_map(), phase_->zone());
     } else {
       // Object does not have the given map, thus the transition is redundant.
       instr->DeleteAndReplaceWith(instr->object());
-      transitions_++;
+      INC_STAT(transitions_);
     }
   }
 
   // Kill everything in the table.
   void Kill() {
-    memset(objects_, 0, sizeof(objects_));
+    size_ = 0;
+    cursor_ = 0;
   }
 
   // Kill everything in the table that may alias {object}.
   void Kill(HValue* object) {
-    for (int i = 0; i < kMaxTrackedObjects; i++) {
-      if (objects_[i] == NULL) continue;
-      if (aliasing_.MayAlias(objects_[i], object)) objects_[i] = NULL;
+    bool compact = false;
+    for (int i = 0; i < size_; i++) {
+      HCheckTableEntry* entry = &entries_[i];
+      ASSERT(entry->object_ != NULL);
+      if (phase_->aliasing_->MayAlias(entry->object_, object)) {
+        entry->object_ = NULL;
+        compact = true;
+      }
     }
-    ASSERT(Find(object) < 0);
+    if (compact) Compact();
+    ASSERT(Find(object) == NULL);
+  }
+
+  void Compact() {
+    // First, compact the array in place.
+    int max = size_, dest = 0, old_cursor = cursor_;
+    for (int i = 0; i < max; i++) {
+      if (entries_[i].object_ != NULL) {
+        if (dest != i) entries_[dest] = entries_[i];
+        dest++;
+      } else {
+        if (i < old_cursor) cursor_--;
+        size_--;
+      }
+    }
+    ASSERT(size_ == dest);
+    ASSERT(cursor_ <= size_);
+
+    // Preserve the age of the entries by moving the older entries to the end.
+    if (cursor_ == size_) return;  // Cursor already points at end.
+    if (cursor_ != 0) {
+      // | L = oldest |   R = newest   |       |
+      //              ^ cursor         ^ size  ^ MAX
+      HCheckTableEntry tmp_entries[kMaxTrackedObjects];
+      int L = cursor_;
+      int R = size_ - cursor_;
+
+      OS::MemMove(&tmp_entries[0], &entries_[0], L * sizeof(HCheckTableEntry));
+      OS::MemMove(&entries_[0], &entries_[L], R * sizeof(HCheckTableEntry));
+      OS::MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry));
+    }
+
+    cursor_ = size_;  // Move cursor to end.
   }
 
   void Print() {
-    for (int i = 0; i < kMaxTrackedObjects; i++) {
-      if (objects_[i] == NULL) continue;
-      PrintF("  checkmaps-table @%d: object #%d ", i, objects_[i]->id());
-      if (checks_[i] != NULL) {
-        PrintF("check #%d ", checks_[i]->id());
+    for (int i = 0; i < size_; i++) {
+      HCheckTableEntry* entry = &entries_[i];
+      ASSERT(entry->object_ != NULL);
+      PrintF("  checkmaps-table @%d: object #%d ", i, entry->object_->id());
+      if (entry->check_ != NULL) {
+        PrintF("check #%d ", entry->check_->id());
       }
-      MapSet list = known_maps_[i];
+      MapSet list = entry->maps_;
       PrintF("%d maps { ", list->size());
       for (int j = 0; j < list->size(); j++) {
         if (j > 0) PrintF(", ");
@@ -211,47 +353,36 @@
     }
   }
 
-  void PrintStats() {
-    if (redundant_ > 0)      PrintF("  redundant   = %2d\n", redundant_);
-    if (removed_ > 0)        PrintF("  removed     = %2d\n", removed_);
-    if (narrowed_ > 0)       PrintF("  narrowed    = %2d\n", narrowed_);
-    if (loads_ > 0)          PrintF("  loads       = %2d\n", loads_);
-    if (empty_ > 0)          PrintF("  empty       = %2d\n", empty_);
-    if (compares_true_ > 0)  PrintF("  cmp_true    = %2d\n", compares_true_);
-    if (compares_false_ > 0) PrintF("  cmp_false   = %2d\n", compares_false_);
-    if (transitions_ > 0)    PrintF("  transitions = %2d\n", transitions_);
-  }
-
  private:
-  int Find(HValue* object) {
-    for (int i = 0; i < kMaxTrackedObjects; i++) {
-      if (objects_[i] == NULL) continue;
-      if (aliasing_.MustAlias(objects_[i], object)) return i;
+  HCheckTableEntry* Find(HValue* object) {
+    for (int i = size_ - 1; i >= 0; i--) {
+      // Search from most-recently-inserted to least-recently-inserted.
+      HCheckTableEntry* entry = &entries_[i];
+      ASSERT(entry->object_ != NULL);
+      if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry;
     }
-    return -1;
+    return NULL;
   }
 
   MapSet FindMaps(HValue* object) {
-    int index = Find(object);
-    return index < 0 ? NULL : known_maps_[index];
+    HCheckTableEntry* entry = Find(object);
+    return entry == NULL ? NULL : entry->maps_;
   }
 
   void Insert(HValue* object, Unique<Map> map) {
-    MapSet list = new(zone_) UniqueSet<Map>();
-    list->Add(map, zone_);
+    MapSet list = new(phase_->zone()) UniqueSet<Map>();
+    list->Add(map, phase_->zone());
     Insert(object, NULL, list);
   }
 
   void Insert(HValue* object, HCheckMaps* check, MapSet maps) {
-    for (int i = 0; i < kMaxTrackedObjects; i++) {
-      // TODO(titzer): drop old entries instead of disallowing new ones.
-      if (objects_[i] == NULL) {
-        objects_[i] = object;
-        checks_[i] = check;
-        known_maps_[i] = maps;
-        return;
-      }
-    }
+    HCheckTableEntry* entry = &entries_[cursor_++];
+    entry->object_ = object;
+    entry->check_ = check;
+    entry->maps_ = maps;
+    // If the table becomes full, wrap around and overwrite older entries.
+    if (cursor_ == kMaxTrackedObjects) cursor_ = 0;
+    if (size_ < kMaxTrackedObjects) size_++;
   }
 
   bool IsMapAccess(HObjectAccess access) {
@@ -262,96 +393,110 @@
     return Unique<Map>::cast(HConstant::cast(value)->GetUnique());
   }
 
-  Zone* zone_;
-  HValue* objects_[kMaxTrackedObjects];
-  HValue* checks_[kMaxTrackedObjects];
-  MapSet known_maps_[kMaxTrackedObjects];
-  HAliasAnalyzer aliasing_;
-  int redundant_;
-  int removed_;
-  int narrowed_;
-  int loads_;
-  int empty_;
-  int compares_true_;
-  int compares_false_;
-  int transitions_;
+  friend class HCheckMapsEffects;
+
+  HCheckEliminationPhase* phase_;
+  HCheckTableEntry entries_[kMaxTrackedObjects];
+  int16_t cursor_;  // Must be <= kMaxTrackedObjects
+  int16_t size_;    // Must be <= kMaxTrackedObjects
+  // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_)
 };
 
 
-void HCheckEliminationPhase::Run() {
-  for (int i = 0; i < graph()->blocks()->length(); i++) {
-    EliminateLocalChecks(graph()->blocks()->at(i));
+// Collects instructions that can cause effects that invalidate information
+// needed for check elimination.
+class HCheckMapsEffects : public ZoneObject {
+ public:
+  explicit HCheckMapsEffects(Zone* zone)
+    : maps_stored_(false),
+      stores_(5, zone) { }
+
+  inline bool Disabled() {
+    return false;  // Effects are _not_ disabled.
   }
-}
 
-
-// For code de-uglification.
-#define TRACE(x) if (FLAG_trace_check_elimination) PrintF x
-
-
-// Eliminate checks local to a block.
-void HCheckEliminationPhase::EliminateLocalChecks(HBasicBlock* block) {
-  HCheckTable table(zone());
-  TRACE(("-- check-elim B%d ------------------------------------------------\n",
-         block->block_id()));
-
-  for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
-    bool changed = false;
-    HInstruction* instr = it.Current();
-
+  // Process a possibly side-effecting instruction.
+  void Process(HInstruction* instr, Zone* zone) {
     switch (instr->opcode()) {
-      case HValue::kCheckMaps: {
-        table.ReduceCheckMaps(HCheckMaps::cast(instr));
-        changed = true;
-        break;
-      }
-      case HValue::kCheckValue: {
-        table.ReduceCheckValue(HCheckValue::cast(instr));
-        changed = true;
-        break;
-      }
-      case HValue::kLoadNamedField: {
-        table.ReduceLoadNamedField(HLoadNamedField::cast(instr));
-        changed = true;
-        break;
-      }
       case HValue::kStoreNamedField: {
-        table.ReduceStoreNamedField(HStoreNamedField::cast(instr));
-        changed = true;
+        stores_.Add(HStoreNamedField::cast(instr), zone);
         break;
       }
-      case HValue::kCompareMap: {
-        table.ReduceCompareMap(HCompareMap::cast(instr));
-        changed = true;
-        break;
-      }
-      case HValue::kTransitionElementsKind: {
-        table.ReduceTransitionElementsKind(
-            HTransitionElementsKind::cast(instr));
-        changed = true;
-        break;
-      }
-      case HValue::kCheckMapValue: {
-        table.ReduceCheckMapValue(HCheckMapValue::cast(instr));
-        changed = true;
-        break;
+      case HValue::kOsrEntry: {
+        // Kill everything. Loads must not be hoisted past the OSR entry.
+        maps_stored_ = true;
       }
       default: {
-        // If the instruction changes maps uncontrollably, kill the whole town.
-        if (instr->CheckGVNFlag(kChangesMaps)) {
-          table.Kill();
-          changed = true;
-        }
+        maps_stored_ |= (instr->CheckGVNFlag(kChangesMaps) |
+                         instr->CheckGVNFlag(kChangesElementsKind));
       }
-      // Improvements possible:
-      // - eliminate HCheckSmi and HCheckHeapObject
     }
-
-    if (changed && FLAG_trace_check_elimination) table.Print();
   }
 
-  if (FLAG_trace_check_elimination) table.PrintStats();
+  // Apply these effects to the given check elimination table.
+  void Apply(HCheckTable* table) {
+    if (maps_stored_) {
+      // Uncontrollable map modifications; kill everything.
+      table->Kill();
+      return;
+    }
+
+    // Kill maps for each store contained in these effects.
+    for (int i = 0; i < stores_.length(); i++) {
+      HStoreNamedField* s = stores_[i];
+      if (table->IsMapAccess(s->access()) || s->has_transition()) {
+        table->Kill(s->object()->ActualValue());
+      }
+    }
+  }
+
+  // Union these effects with the other effects.
+  void Union(HCheckMapsEffects* that, Zone* zone) {
+    maps_stored_ |= that->maps_stored_;
+    for (int i = 0; i < that->stores_.length(); i++) {
+      stores_.Add(that->stores_[i], zone);
+    }
+  }
+
+ private:
+  bool maps_stored_ : 1;
+  ZoneList<HStoreNamedField*> stores_;
+};
+
+
+// The main routine of the analysis phase. Use the HFlowEngine for either a
+// local or a global analysis.
+void HCheckEliminationPhase::Run() {
+  HFlowEngine<HCheckTable, HCheckMapsEffects> engine(graph(), zone());
+  HCheckTable* table = new(zone()) HCheckTable(this);
+
+  if (GLOBAL) {
+    // Perform a global analysis.
+    engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table);
+  } else {
+    // Perform only local analysis.
+    for (int i = 0; i < graph()->blocks()->length(); i++) {
+      table->Kill();
+      engine.AnalyzeOneBlock(graph()->blocks()->at(i), table);
+    }
+  }
+
+  if (FLAG_trace_check_elimination) PrintStats();
 }
 
 
+// Are we eliminated yet?
+void HCheckEliminationPhase::PrintStats() {
+#if DEBUG
+  if (redundant_ > 0)      PrintF("  redundant   = %2d\n", redundant_);
+  if (removed_ > 0)        PrintF("  removed     = %2d\n", removed_);
+  if (narrowed_ > 0)       PrintF("  narrowed    = %2d\n", narrowed_);
+  if (loads_ > 0)          PrintF("  loads       = %2d\n", loads_);
+  if (empty_ > 0)          PrintF("  empty       = %2d\n", empty_);
+  if (compares_true_ > 0)  PrintF("  cmp_true    = %2d\n", compares_true_);
+  if (compares_false_ > 0) PrintF("  cmp_false   = %2d\n", compares_false_);
+  if (transitions_ > 0)    PrintF("  transitions = %2d\n", transitions_);
+#endif
+}
+
 } }  // namespace v8::internal
diff --git a/src/hydrogen-check-elimination.h b/src/hydrogen-check-elimination.h
index fa01964..f38e615 100644
--- a/src/hydrogen-check-elimination.h
+++ b/src/hydrogen-check-elimination.h
@@ -29,6 +29,7 @@
 #define V8_HYDROGEN_CHECK_ELIMINATION_H_
 
 #include "hydrogen.h"
+#include "hydrogen-alias-analysis.h"
 
 namespace v8 {
 namespace internal {
@@ -38,12 +39,33 @@
 class HCheckEliminationPhase : public HPhase {
  public:
   explicit HCheckEliminationPhase(HGraph* graph)
-      : HPhase("H_Check Elimination", graph) { }
+    : HPhase("H_Check Elimination", graph),
+      aliasing_(),
+      redundant_(0),
+      removed_(0),
+      narrowed_(0),
+      loads_(0),
+      empty_(0),
+      compares_true_(0),
+      compares_false_(0),
+      transitions_(0) { }
 
   void Run();
 
+  friend class HCheckTable;
+
  private:
-  void EliminateLocalChecks(HBasicBlock* block);
+  void PrintStats();
+
+  HAliasAnalyzer* aliasing_;
+  int redundant_;
+  int removed_;
+  int narrowed_;
+  int loads_;
+  int empty_;
+  int compares_true_;
+  int compares_false_;
+  int transitions_;
 };
 
 
diff --git a/src/hydrogen-environment-liveness.cc b/src/hydrogen-environment-liveness.cc
index fad9755..d7501ac 100644
--- a/src/hydrogen-environment-liveness.cc
+++ b/src/hydrogen-environment-liveness.cc
@@ -201,7 +201,7 @@
       HBasicBlock* block = graph()->blocks()->at(block_id);
       UpdateLivenessAtBlockEnd(block, &live);
 
-      for (HInstruction* instr = block->last(); instr != NULL;
+      for (HInstruction* instr = block->end(); instr != NULL;
            instr = instr->previous()) {
         UpdateLivenessAtInstruction(instr, &live);
       }
diff --git a/src/hydrogen-load-elimination.cc b/src/hydrogen-load-elimination.cc
index f37de90..f3b5748 100644
--- a/src/hydrogen-load-elimination.cc
+++ b/src/hydrogen-load-elimination.cc
@@ -349,7 +349,9 @@
 
   bool Equal(HValue* a, HValue* b) {
     if (a == b) return true;
-    if (a != NULL && b != NULL) return a->Equals(b);
+    if (a != NULL && b != NULL && a->CheckFlag(HValue::kUseGVN)) {
+      return a->Equals(b);
+    }
     return false;
   }
 
diff --git a/src/hydrogen-mark-unreachable.h b/src/hydrogen-mark-unreachable.h
index e9459d5..9ecc6e9 100644
--- a/src/hydrogen-mark-unreachable.h
+++ b/src/hydrogen-mark-unreachable.h
@@ -37,7 +37,7 @@
 class HMarkUnreachableBlocksPhase : public HPhase {
  public:
   explicit HMarkUnreachableBlocksPhase(HGraph* graph)
-      : HPhase("H_Mark unrechable blocks", graph) { }
+      : HPhase("H_Mark unreachable blocks", graph) { }
 
   void Run();
 
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 5b9e42f..b6498b1 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1602,7 +1602,7 @@
   if_objectissmi.Else();
   {
     if (type->Is(Type::Smi())) {
-      if_objectissmi.Deopt("Excepted smi");
+      if_objectissmi.Deopt("Expected smi");
     } else {
       // Check if the object is a heap number.
       IfBuilder if_objectisnumber(this);
@@ -2248,9 +2248,8 @@
               AllocationSite::kMementoCreateCountOffset);
       HValue* create_info = Add<HLoadNamedField>(allocation_site_payload,
                                                  access);
-      HInstruction* new_create_info = HAdd::New(zone(), context(),
-                                                create_info,
-                                                graph()->GetConstant1());
+      HInstruction* new_create_info =
+          AddUncasted<HAdd>(create_info, graph()->GetConstant1());
       new_create_info->ClearFlag(HValue::kCanOverflow);
       HStoreNamedField* store = Add<HStoreNamedField>(allocation_site_payload,
                                                       access, new_create_info);
@@ -3571,15 +3570,8 @@
   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
     builder->Bailout(kArgumentsObjectValueInATestContext);
   }
-  HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
-  HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
   ToBooleanStub::Types expected(condition()->to_boolean_types());
-  builder->FinishCurrentBlock(builder->New<HBranch>(
-          value, expected, empty_true, empty_false));
-
-  owner()->Goto(empty_true, if_true(), builder->function_state());
-  owner()->Goto(empty_false , if_false(), builder->function_state());
-  builder->set_current_block(NULL);
+  ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
 }
 
 
@@ -3771,7 +3763,6 @@
   // where unreachable code could unnecessarily defeat LICM.
   Run<HMarkUnreachableBlocksPhase>();
 
-  if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
 
@@ -3802,6 +3793,8 @@
 
   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
 
+  if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
+
   if (FLAG_use_range) Run<HRangeAnalysisPhase>();
 
   Run<HComputeChangeUndefinedToNaN>();
@@ -7560,6 +7553,7 @@
   // Found pattern f.apply(receiver, arguments).
   CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true);
   HValue* function = Top();
+
   AddCheckConstantFunction(expr->holder(), function, function_map);
   Drop(1);
 
@@ -7590,10 +7584,10 @@
     }
 
     Handle<JSFunction> known_function;
-    if (function->IsConstant()) {
-      HConstant* constant_function = HConstant::cast(function);
+    if (function->IsConstant() &&
+        HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
       known_function = Handle<JSFunction>::cast(
-          constant_function->handle(isolate()));
+          HConstant::cast(function)->handle(isolate()));
       int args_count = arguments_count - 1;  // Excluding receiver.
       if (TryInlineApply(known_function, expr, args_count)) return true;
     }
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 53742dc..0b85829 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -952,7 +952,7 @@
 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
                                                int argc,
                                                Code::Kind kind,
-                                               Code::ExtraICState extra_state) {
+                                               ExtraICState extra_state) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- edx                 : receiver
@@ -1061,7 +1061,7 @@
 void CallICBase::GenerateMiss(MacroAssembler* masm,
                               int argc,
                               IC::UtilityId id,
-                              Code::ExtraICState extra_state) {
+                              ExtraICState extra_state) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -1132,7 +1132,7 @@
 
 void CallIC::GenerateMegamorphic(MacroAssembler* masm,
                                  int argc,
-                                 Code::ExtraICState extra_state) {
+                                 ExtraICState extra_state) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -1249,7 +1249,7 @@
   __ bind(&lookup_monomorphic_cache);
   __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1);
   CallICBase::GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC,
-                                            Code::kNoExtraICState);
+                                            kNoExtraICState);
   // Fall through on miss.
 
   __ bind(&slow_call);
@@ -1327,7 +1327,7 @@
 
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeFlags(
-      Code::HANDLER, MONOMORPHIC, Code::kNoExtraICState,
+      Code::HANDLER, MONOMORPHIC, kNoExtraICState,
       Code::NORMAL, Code::LOAD_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, edx, ecx, ebx, eax);
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index eb1f960..739f042 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -4845,13 +4845,10 @@
                          ToRegister(instr->temp()),
                          kDontSaveFPRegs);
   } else {
+    ASSERT(ToRegister(instr->context()).is(esi));
     PushSafepointRegistersScope scope(this);
     if (!object_reg.is(eax)) {
-      __ push(object_reg);
-    }
-    LoadContextFromDeferred(instr->context());
-    if (!object_reg.is(eax)) {
-      __ pop(eax);
+      __ mov(eax, object_reg);
     }
     __ mov(ebx, to_map);
     TransitionElementsKindStub stub(from_kind, to_kind);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 921b5aa..678c0ca 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -2420,7 +2420,7 @@
                                             new_map_reg, temp_reg);
     return result;
   } else {
-    LOperand* context = UseRegister(instr->context());
+    LOperand* context = UseFixed(instr->context(), esi);
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
     return AssignPointerMap(result);
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 2d0720a..b5cefdb 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -1107,10 +1107,8 @@
   push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
 
   // Save the frame pointer and the context in top.
-  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress,
-                                       isolate());
-  ExternalReference context_address(Isolate::kContextAddress,
-                                    isolate());
+  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
+  ExternalReference context_address(Isolate::kContextAddress, isolate());
   mov(Operand::StaticVariable(c_entry_fp_address), ebp);
   mov(Operand::StaticVariable(context_address), esi);
 }
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 1c98c98..d799c3b 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -648,7 +648,7 @@
   CallInterceptorCompiler(StubCompiler* stub_compiler,
                           const ParameterCount& arguments,
                           Register name,
-                          Code::ExtraICState extra_state)
+                          ExtraICState extra_state)
       : stub_compiler_(stub_compiler),
         arguments_(arguments),
         name_(name),
@@ -833,7 +833,7 @@
   StubCompiler* stub_compiler_;
   const ParameterCount& arguments_;
   Register name_;
-  Code::ExtraICState extra_state_;
+  ExtraICState extra_state_;
 };
 
 
@@ -1602,26 +1602,6 @@
 }
 
 
-void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
-                                                   Handle<JSObject> holder,
-                                                   Handle<Name> name,
-                                                   Label* miss) {
-  ASSERT(holder->IsGlobalObject());
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-
-  // Get the receiver from the stack.
-  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-
-
-  // Check that the maps haven't changed.
-  __ JumpIfSmi(edx, miss);
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                  ebx, eax, edi, name, miss);
-}
-
-
 void CallStubCompiler::GenerateLoadFunctionFromCell(
     Handle<Cell> cell,
     Handle<JSFunction> function,
@@ -1668,27 +1648,10 @@
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
                                                 Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
   Label miss;
 
-  GenerateNameCheck(name, &miss);
-
-  // Get the receiver from the stack.
-  const int argc = arguments().immediate();
-  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(edx, &miss);
-
-  // Do the right check and compute the holder register.
-  Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx,
-                                 holder, ebx, eax, edi, name, &miss);
+  Register reg = HandlerFrontendHeader(
+      object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   GenerateFastPropertyLoad(
       masm(), edi, reg, index.is_inobject(holder),
@@ -1699,12 +1662,7 @@
   __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
   __ j(not_equal, &miss);
 
-  // Patch the receiver on the stack with the global proxy if
-  // necessary.
-  if (object->IsGlobalObject()) {
-    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
-    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
-  }
+  PatchGlobalProxy(object);
 
   // Invoke the function.
   CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
@@ -1713,9 +1671,7 @@
   __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
                     NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -1731,28 +1687,16 @@
     Code::StubType type) {
   Label miss;
 
-  // Check that function is still array
-  const int argc = arguments().immediate();
-  GenerateNameCheck(name, &miss);
-
-  if (cell.is_null()) {
-    // Get the receiver from the stack.
-    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-
-    // Check that the receiver isn't a smi.
-    __ JumpIfSmi(edx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                    ebx, eax, edi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
   Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
   site->SetElementsKind(GetInitialFastElementsKind());
   Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
+  const int argc = arguments().immediate();
   __ mov(eax, Immediate(argc));
   __ mov(ebx, site_feedback_cell);
   __ mov(edi, function);
@@ -1760,8 +1704,7 @@
   ArrayConstructorStub stub(isolate());
   __ TailCallStub(&stub);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1775,14 +1718,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1792,18 +1727,9 @@
 
   Label miss;
 
-  GenerateNameCheck(name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
-  // Get the receiver from the stack.
   const int argc = arguments().immediate();
-  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(edx, &miss);
-
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                  ebx, eax, edi, name, &miss);
-
   if (argc == 0) {
     // Noop, return the length.
     __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
@@ -2021,8 +1947,7 @@
         1);
   }
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2036,14 +1961,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -2053,16 +1970,7 @@
 
   Label miss, return_undefined, call_builtin;
 
-  GenerateNameCheck(name, &miss);
-
-  // Get the receiver from the stack.
-  const int argc = arguments().immediate();
-  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(edx, &miss);
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                  ebx, eax, edi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   // Get the elements array of the object.
   __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
@@ -2094,6 +2002,7 @@
                       ecx, times_half_pointer_size,
                       FixedArray::kHeaderSize),
          Immediate(factory()->the_hole_value()));
+  const int argc = arguments().immediate();
   __ ret((argc + 1) * kPointerSize);
 
   __ bind(&return_undefined);
@@ -2106,8 +2015,7 @@
       argc + 1,
       1);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2121,14 +2029,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : function name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) {
     return Handle<Code>::null();
@@ -2147,18 +2047,7 @@
     index_out_of_range_label = &miss;
   }
 
-  GenerateNameCheck(name, &name_miss);
-
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            eax,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      eax, holder, ebx, edx, edi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = ebx;
   Register index = edi;
@@ -2207,14 +2096,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : function name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) {
     return Handle<Code>::null();
@@ -2233,18 +2114,7 @@
     index_out_of_range_label = &miss;
   }
 
-  GenerateNameCheck(name, &name_miss);
-
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            eax,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      eax, holder, ebx, edx, edi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = eax;
   Register index = edi;
@@ -2295,14 +2165,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : function name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
 
   // If the object is not a JSObject or we got an unexpected number of
@@ -2312,18 +2174,10 @@
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ mov(edx, Operand(esp, 2 * kPointerSize));
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(edx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                    ebx, eax, edi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2356,9 +2210,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), call_kind);
 
-  __ bind(&miss);
-  // ecx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2372,14 +2224,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   if (!CpuFeatures::IsSupported(SSE2)) {
     return Handle<Code>::null();
   }
@@ -2395,20 +2239,10 @@
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ mov(edx, Operand(esp, 2 * kPointerSize));
-
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(edx, &miss);
-
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                    ebx, eax, edi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2488,9 +2322,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // ecx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2504,14 +2336,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
 
   // If the object is not a JSObject or we got an unexpected number of
@@ -2521,20 +2345,10 @@
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ mov(edx, Operand(esp, 2 * kPointerSize));
-
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(edx, &miss);
-
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                    ebx, eax, edi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2597,9 +2411,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // ecx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2676,27 +2488,32 @@
 }
 
 
-void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
-                                              Handle<JSObject> holder,
-                                              Handle<Name> name,
-                                              CheckType check) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-  Label miss;
-  GenerateNameCheck(name, &miss);
+void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
+  if (object->IsGlobalObject()) {
+    const int argc = arguments().immediate();
+    const int receiver_offset = (argc + 1) * kPointerSize;
+    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+    __ mov(Operand(esp, receiver_offset), edx);
+  }
+}
 
-  // Get the receiver from the stack.
+
+Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
+                                                 Handle<JSObject> holder,
+                                                 Handle<Name> name,
+                                                 CheckType check,
+                                                 Label* miss) {
+  GenerateNameCheck(name, miss);
+
+  Register reg = edx;
+
   const int argc = arguments().immediate();
-  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+  const int receiver_offset = (argc + 1) * kPointerSize;
+  __ mov(reg, Operand(esp, receiver_offset));
 
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
-    __ JumpIfSmi(edx, &miss);
+    __ JumpIfSmi(reg, miss);
   }
 
   // Make sure that it's okay not to patch the on stack receiver
@@ -2707,80 +2524,58 @@
       __ IncrementCounter(isolate()->counters()->call_const(), 1);
 
       // Check that the maps haven't changed.
-      CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
-                      ebx, eax, edi, name, &miss);
+      reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
+                            ebx, eax, edi, name, miss);
 
-      // Patch the receiver on the stack with the global proxy if
-      // necessary.
-      if (object->IsGlobalObject()) {
-        __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
-        __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
-      }
       break;
 
     case STRING_CHECK: {
       // Check that the object is a string.
-      __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
-      __ j(above_equal, &miss);
+      __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, eax);
+      __ j(above_equal, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::STRING_FUNCTION_INDEX, eax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          eax, holder, ebx, edx, edi, name, &miss);
+          masm(), Context::STRING_FUNCTION_INDEX, eax, miss);
       break;
     }
     case SYMBOL_CHECK: {
       // Check that the object is a symbol.
-      __ CmpObjectType(edx, SYMBOL_TYPE, eax);
-      __ j(not_equal, &miss);
+      __ CmpObjectType(reg, SYMBOL_TYPE, eax);
+      __ j(not_equal, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          eax, holder, ebx, edx, edi, name, &miss);
+          masm(), Context::SYMBOL_FUNCTION_INDEX, eax, miss);
       break;
     }
     case NUMBER_CHECK: {
       Label fast;
       // Check that the object is a smi or a heap number.
-      __ JumpIfSmi(edx, &fast);
-      __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
-      __ j(not_equal, &miss);
+      __ JumpIfSmi(reg, &fast);
+      __ CmpObjectType(reg, HEAP_NUMBER_TYPE, eax);
+      __ j(not_equal, miss);
       __ bind(&fast);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          eax, holder, ebx, edx, edi, name, &miss);
+          masm(), Context::NUMBER_FUNCTION_INDEX, eax, miss);
       break;
     }
     case BOOLEAN_CHECK: {
-      GenerateBooleanCheck(edx, &miss);
+      GenerateBooleanCheck(reg, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          eax, holder, ebx, edx, edi, name, &miss);
+          masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, miss);
       break;
     }
   }
 
-  Label success;
-  __ jmp(&success);
+  if (check != RECEIVER_MAP_CHECK) {
+    Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
+    reg = CheckPrototypes(
+        IC::CurrentTypeOf(prototype, isolate()),
+        eax, holder, ebx, edx, edi, name, miss);
+  }
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
-
-  __ bind(&success);
+  return reg;
 }
 
 
@@ -2810,8 +2605,11 @@
     if (!code.is_null()) return code;
   }
 
-  CompileHandlerFrontend(object, holder, name, check);
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
+  PatchGlobalProxy(object);
   CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(function);
@@ -2821,13 +2619,6 @@
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
                                                       Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
   Label miss;
 
   GenerateNameCheck(name, &miss);
@@ -2883,14 +2674,6 @@
     Handle<PropertyCell> cell,
     Handle<JSFunction> function,
     Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
-  // -----------------------------------
-
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
         object, holder, cell, function, Handle<String>::cast(name),
@@ -2900,18 +2683,9 @@
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-  GenerateGlobalReceiverCheck(object, holder, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateLoadFunctionFromCell(cell, function, &miss);
-
-  // Patch the receiver on the stack with the global proxy.
-  if (object->IsGlobalObject()) {
-    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
-    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
-  }
+  PatchGlobalProxy(object);
 
   // Set up the context (function already in edi).
   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
@@ -2930,10 +2704,7 @@
                 expected, arguments(), JUMP_FUNCTION,
                 NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(counters->call_global_inline_miss(), 1);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::NORMAL, name);
@@ -3037,13 +2808,12 @@
   __ push(receiver());
   __ push(this->name());
   __ push(value());
-  __ push(Immediate(Smi::FromInt(strict_mode())));
   __ push(scratch1());  // restore return address
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
-  __ TailCallExternalReference(store_ic_property, 4, 1);
+  __ TailCallExternalReference(store_ic_property, 3, 1);
 
   // Return the generated code.
   return GetCode(kind(), Code::FAST, name);
diff --git a/src/ic-inl.h b/src/ic-inl.h
index 1840587..24a939d 100644
--- a/src/ic-inl.h
+++ b/src/ic-inl.h
@@ -86,8 +86,8 @@
   // ICs as strict mode. The strict-ness of the IC must be preserved.
   if (old_target->kind() == Code::STORE_IC ||
       old_target->kind() == Code::KEYED_STORE_IC) {
-    ASSERT(Code::GetStrictMode(old_target->extra_ic_state()) ==
-           Code::GetStrictMode(target->extra_ic_state()));
+    ASSERT(StoreIC::GetStrictMode(old_target->extra_ic_state()) ==
+           StoreIC::GetStrictMode(target->extra_ic_state()));
   }
 #endif
   Assembler::set_target_address_at(address, target->instruction_start());
diff --git a/src/ic.cc b/src/ic.cc
index 557a483..46820fe 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -89,9 +89,10 @@
       }
     }
     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
-    Code::ExtraICState extra_state = new_target->extra_ic_state();
+    ExtraICState extra_state = new_target->extra_ic_state();
     const char* modifier =
-        GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(extra_state));
+        GetTransitionMarkModifier(
+            KeyedStoreIC::GetKeyedAccessStoreMode(extra_state));
     PrintF(" (%c->%c%s)",
            TransitionMarkFromState(state()),
            TransitionMarkFromState(new_state),
@@ -532,7 +533,7 @@
   if (IsCleared(target)) return;
   SetTargetAtAddress(address,
       *pre_monomorphic_stub(
-          isolate, Code::GetStrictMode(target->extra_ic_state())));
+          isolate, StoreIC::GetStrictMode(target->extra_ic_state())));
 }
 
 
@@ -540,7 +541,7 @@
   if (IsCleared(target)) return;
   SetTargetAtAddress(address,
       *pre_monomorphic_stub(
-          isolate, Code::GetStrictMode(target->extra_ic_state())));
+          isolate, StoreIC::GetStrictMode(target->extra_ic_state())));
 }
 
 
@@ -822,7 +823,7 @@
 
     if (stub.is_null()) {
       stub = isolate()->stub_cache()->ComputeCallMegamorphic(
-          argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
+          argc, Code::KEYED_CALL_IC, kNoExtraICState);
       if (object->IsJSObject()) {
         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
         if (receiver->elements()->map() ==
@@ -1005,7 +1006,7 @@
   }
 
   Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
-      &types, &handlers, number_of_valid_types, name, strict_mode());
+      &types, &handlers, number_of_valid_types, name, extra_ic_state());
   set_target(*ic);
   return true;
 }
@@ -1043,7 +1044,7 @@
                              Handle<String> name) {
   if (!handler->is_handler()) return set_target(*handler);
   Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
-      name, type, handler, strict_mode());
+      name, type, handler, extra_ic_state());
   set_target(*ic);
 }
 
@@ -1178,7 +1179,7 @@
       isolate(), *object, cache_holder));
 
   Handle<Code> code = isolate()->stub_cache()->FindHandler(
-      name, handle(stub_holder->map()), kind(), cache_holder, strict_mode());
+      name, handle(stub_holder->map()), kind(), cache_holder);
   if (!code.is_null()) return code;
 
   code = CompileHandler(lookup, object, name, value, cache_holder);
@@ -1753,7 +1754,7 @@
   // superset of the original IC. Handle those here if the receiver map hasn't
   // changed or it has transitioned to a more general kind.
   KeyedAccessStoreMode old_store_mode =
-      Code::GetKeyedAccessStoreMode(target()->extra_ic_state());
+      KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state());
   Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
   if (state() == MONOMORPHIC) {
       // If the "old" and "new" maps are in the same elements map family, stay
@@ -2344,7 +2345,7 @@
 
 
 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) {
-  Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
+  ExtraICState extra_ic_state = target()->extended_extra_ic_state();
   BinaryOpStub stub(extra_ic_state);
 
   Handle<Type> left_type = stub.GetLeftType(isolate());
@@ -2637,7 +2638,7 @@
 
 void CompareNilIC::Clear(Address address, Code* target) {
   if (IsCleared(target)) return;
-  Code::ExtraICState state = target->extended_extra_ic_state();
+  ExtraICState state = target->extended_extra_ic_state();
 
   CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
   stub.ClearState();
@@ -2659,7 +2660,7 @@
 
 
 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
-  Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
+  ExtraICState extra_ic_state = target()->extended_extra_ic_state();
 
   CompareNilICStub stub(extra_ic_state);
 
diff --git a/src/ic.h b/src/ic.h
index bfb73ac..3db352a 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -250,11 +250,13 @@
     UNREACHABLE();
     return Handle<Code>::null();
   }
-  virtual StrictModeFlag strict_mode() const { return kNonStrictMode; }
+
   bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
                                               Handle<String> name);
   void TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name);
 
+  virtual ExtraICState extra_ic_state() { return kNoExtraICState; }
+
  private:
   Code* raw_target() const { return GetTargetAtAddress(address()); }
 
@@ -296,8 +298,13 @@
 
 class CallICBase: public IC {
  public:
-  class Contextual: public BitField<bool, 0, 1> {};
+  // ExtraICState bits
+  class Contextual: public BitField<ContextualMode, 0, 1> {};
   class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
+  static ExtraICState ComputeExtraICState(ContextualMode mode,
+                                          StringStubFeedback feedback) {
+    return Contextual::encode(mode) | StringStubState::encode(feedback);
+  }
 
   // Returns a JSFunction or a Failure.
   MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object,
@@ -307,8 +314,6 @@
   CallICBase(Code::Kind kind, Isolate* isolate)
       : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
 
-  virtual Code::ExtraICState extra_ic_state() { return Code::kNoExtraICState; }
-
   // Compute a monomorphic stub if possible, otherwise return a null handle.
   Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
                                       Handle<Object> object,
@@ -334,14 +339,14 @@
   static void GenerateMiss(MacroAssembler* masm,
                            int argc,
                            IC::UtilityId id,
-                           Code::ExtraICState extra_state);
+                           ExtraICState extra_state);
 
   static void GenerateNormal(MacroAssembler* masm, int argc);
 
   static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
                                             int argc,
                                             Code::Kind kind,
-                                            Code::ExtraICState extra_state);
+                                            ExtraICState extra_state);
 
   virtual Handle<Code> megamorphic_stub();
   virtual Handle<Code> pre_monomorphic_stub();
@@ -363,31 +368,31 @@
   // Code generator routines.
   static void GenerateInitialize(MacroAssembler* masm,
                                  int argc,
-                                 Code::ExtraICState extra_state) {
+                                 ExtraICState extra_state) {
     GenerateMiss(masm, argc, extra_state);
   }
 
   static void GenerateMiss(MacroAssembler* masm,
                            int argc,
-                           Code::ExtraICState extra_state) {
+                           ExtraICState extra_state) {
     CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
   }
 
   static void GenerateMegamorphic(MacroAssembler* masm,
                                   int argc,
-                                  Code::ExtraICState extra_ic_state);
+                                  ExtraICState extra_ic_state);
 
   static void GenerateNormal(MacroAssembler* masm, int argc) {
     CallICBase::GenerateNormal(masm, argc);
-    GenerateMiss(masm, argc, Code::kNoExtraICState);
+    GenerateMiss(masm, argc, kNoExtraICState);
   }
   bool TryUpdateExtraICState(LookupResult* lookup, Handle<Object> object);
 
  protected:
-  virtual Code::ExtraICState extra_ic_state() { return extra_ic_state_; }
+  virtual ExtraICState extra_ic_state() { return extra_ic_state_; }
 
  private:
-  Code::ExtraICState extra_ic_state_;
+  ExtraICState extra_ic_state_;
 };
 
 
@@ -408,7 +413,7 @@
 
   static void GenerateMiss(MacroAssembler* masm, int argc) {
     CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
-                             Code::kNoExtraICState);
+                             kNoExtraICState);
   }
 
   static void GenerateMegamorphic(MacroAssembler* masm, int argc);
@@ -559,13 +564,28 @@
 
 class StoreIC: public IC {
  public:
+  // ExtraICState bits
+  class StrictModeState: public BitField<StrictModeFlag, 0, 1> {};
+  static ExtraICState ComputeExtraICState(StrictModeFlag flag) {
+    return StrictModeState::encode(flag);
+  }
+
+  static StrictModeFlag GetStrictMode(ExtraICState state) {
+    return StrictModeState::decode(state);
+  }
+
+  // For convenience, a statically declared encoding of strict mode extra
+  // IC state.
+  static const ExtraICState kStrictModeState =
+      1 << StrictModeState::kShift;
+
   StoreIC(FrameDepth depth, Isolate* isolate)
       : IC(depth, isolate),
-        strict_mode_(Code::GetStrictMode(target()->extra_ic_state())) {
+        strict_mode_(GetStrictMode(target()->extra_ic_state())) {
     ASSERT(IsStoreStub());
   }
 
-  virtual StrictModeFlag strict_mode() const { return strict_mode_; }
+  StrictModeFlag strict_mode() const { return strict_mode_; }
 
   // Code generators for stub routines. Only called once at startup.
   static void GenerateSlow(MacroAssembler* masm);
@@ -642,11 +662,15 @@
                                       Handle<Object> value,
                                       InlineCacheHolderFlag cache_holder);
 
+  virtual ExtraICState extra_ic_state() {
+    return ComputeExtraICState(strict_mode());
+  }
+
  private:
   void set_target(Code* code) {
     // Strict mode must be preserved across IC patching.
-    ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
-           Code::GetStrictMode(target()->extra_ic_state()));
+    ASSERT(GetStrictMode(code->extra_ic_state()) ==
+           GetStrictMode(target()->extra_ic_state()));
     IC::set_target(code);
   }
 
@@ -681,6 +705,22 @@
 
 class KeyedStoreIC: public StoreIC {
  public:
+  // ExtraICState bits (building on IC)
+  // ExtraICState bits
+  class ExtraICStateKeyedAccessStoreMode:
+      public BitField<KeyedAccessStoreMode, 1, 4> {};  // NOLINT
+
+  static ExtraICState ComputeExtraICState(StrictModeFlag flag,
+                                                KeyedAccessStoreMode mode) {
+    return StrictModeState::encode(flag) |
+        ExtraICStateKeyedAccessStoreMode::encode(mode);
+  }
+
+  static KeyedAccessStoreMode GetKeyedAccessStoreMode(
+      ExtraICState extra_state) {
+    return ExtraICStateKeyedAccessStoreMode::decode(extra_state);
+  }
+
   KeyedStoreIC(FrameDepth depth, Isolate* isolate)
       : StoreIC(depth, isolate) {
     ASSERT(target()->is_keyed_store_stub());
@@ -707,6 +747,10 @@
 
   virtual void UpdateMegamorphicCache(Type* type, Name* name, Code* code) { }
 
+  virtual ExtraICState extra_ic_state() {
+    return ComputeExtraICState(strict_mode(), STANDARD_STORE);
+  }
+
   virtual Handle<Code> pre_monomorphic_stub() {
     return pre_monomorphic_stub(isolate(), strict_mode());
   }
@@ -735,7 +779,7 @@
  private:
   void set_target(Code* code) {
     // Strict mode must be preserved across IC patching.
-    ASSERT(Code::GetStrictMode(code->extra_ic_state()) == strict_mode());
+    ASSERT(GetStrictMode(code->extra_ic_state()) == strict_mode());
     IC::set_target(code);
   }
 
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index b60768b..0e6b980 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -2768,7 +2768,7 @@
                                          int size,
                                          AllocationSpace dest) {
   HeapProfiler* heap_profiler = heap()->isolate()->heap_profiler();
-  if (heap_profiler->is_profiling()) {
+  if (heap_profiler->is_tracking_object_moves()) {
     heap_profiler->ObjectMoveEvent(src, dst, size);
   }
   ASSERT(heap()->AllowedToBeMigrated(HeapObject::FromAddress(src), dest));
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index 5062080..37af8a6 100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -346,7 +346,7 @@
 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
                                                int argc,
                                                Code::Kind kind,
-                                               Code::ExtraICState extra_state) {
+                                               ExtraICState extra_state) {
   // ----------- S t a t e -------------
   //  -- a1    : receiver
   //  -- a2    : name
@@ -448,7 +448,7 @@
 void CallICBase::GenerateMiss(MacroAssembler* masm,
                               int argc,
                               IC::UtilityId id,
-                              Code::ExtraICState extra_state) {
+                              ExtraICState extra_state) {
   // ----------- S t a t e -------------
   //  -- a2    : name
   //  -- ra    : return address
@@ -512,7 +512,7 @@
 
 void CallIC::GenerateMegamorphic(MacroAssembler* masm,
                                  int argc,
-                                 Code::ExtraICState extra_ic_state) {
+                                 ExtraICState extra_ic_state) {
   // ----------- S t a t e -------------
   //  -- a2    : name
   //  -- ra    : return address
@@ -609,7 +609,7 @@
   GenerateMonomorphicCacheProbe(masm,
                                 argc,
                                 Code::KEYED_CALL_IC,
-                                Code::kNoExtraICState);
+                                kNoExtraICState);
   // Fall through on miss.
 
   __ bind(&slow_call);
@@ -655,7 +655,7 @@
 
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeFlags(
-      Code::HANDLER, MONOMORPHIC, Code::kNoExtraICState,
+      Code::HANDLER, MONOMORPHIC, kNoExtraICState,
       Code::NORMAL, Code::LOAD_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, a0, a2, a3, t0, t1, t2);
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index e743701..748a783 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -736,7 +736,7 @@
                                  Handle<Object> object,
                                  const ParameterCount& arguments,
                                  Label* miss,
-                                 Code::ExtraICState extra_ic_state) {
+                                 ExtraICState extra_ic_state) {
   // ----------- S t a t e -------------
   //  -- a0: receiver
   //  -- a1: function to call
@@ -746,11 +746,11 @@
   __ GetObjectType(a1, a3, a3);
   __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE));
 
-  // Patch the receiver on the stack with the global proxy if
-  // necessary.
   if (object->IsGlobalObject()) {
+    const int argc = arguments.immediate();
+    const int receiver_offset = argc * kPointerSize;
     __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
-    __ sw(a3, MemOperand(sp, arguments.immediate() * kPointerSize));
+    __ sw(a3, MemOperand(sp, receiver_offset));
   }
 
   // Invoke the function.
@@ -945,7 +945,7 @@
   CallInterceptorCompiler(StubCompiler* stub_compiler,
                           const ParameterCount& arguments,
                           Register name,
-                          Code::ExtraICState extra_ic_state)
+                          ExtraICState extra_ic_state)
       : stub_compiler_(stub_compiler),
         arguments_(arguments),
         name_(name),
@@ -1129,7 +1129,7 @@
   StubCompiler* stub_compiler_;
   const ParameterCount& arguments_;
   Register name_;
-  Code::ExtraICState extra_ic_state_;
+  ExtraICState extra_ic_state_;
 };
 
 
@@ -1527,25 +1527,6 @@
 }
 
 
-void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
-                                                   Handle<JSObject> holder,
-                                                   Handle<Name> name,
-                                                   Label* miss) {
-  ASSERT(holder->IsGlobalObject());
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-
-  // Get the receiver from the stack.
-  __ lw(a0, MemOperand(sp, argc * kPointerSize));
-
-  // Check that the maps haven't changed.
-  __ JumpIfSmi(a0, miss);
-  CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()), a0, holder, a3, a1, t0, name, miss);
-}
-
-
 void CallStubCompiler::GenerateLoadFunctionFromCell(
     Handle<Cell> cell,
     Handle<JSFunction> function,
@@ -1588,33 +1569,16 @@
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
                                                 Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
   Label miss;
 
-  GenerateNameCheck(name, &miss);
-
-  const int argc = arguments().immediate();
-
-  // Get the receiver of the function from the stack into a0.
-  __ lw(a0, MemOperand(sp, argc * kPointerSize));
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(a0, &miss, t0);
-
-  // Do the right check and compute the holder register.
-  Register reg = CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()),
-      a0, holder, a1, a3, t0, name, &miss);
+  Register reg = HandlerFrontendHeader(
+      object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder),
                            index.translate(holder), Representation::Tagged());
 
   GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -1630,31 +1594,16 @@
     Code::StubType type) {
   Label miss;
 
-  // Check that function is still array.
-  const int argc = arguments().immediate();
-  GenerateNameCheck(name, &miss);
-  Register receiver = a1;
-
-  if (cell.is_null()) {
-    __ lw(receiver, MemOperand(sp, argc * kPointerSize));
-
-    // Check that the receiver isn't a smi.
-    __ JumpIfSmi(receiver, &miss);
-
-    // Check that the maps haven't changed.
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()), receiver, holder,
-        a3, a0, t0, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
   Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
   site->SetElementsKind(GetInitialFastElementsKind());
   Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
+  const int argc = arguments().immediate();
   __ li(a0, Operand(argc));
   __ li(a2, Operand(site_feedback_cell));
   __ li(a1, Operand(function));
@@ -1662,8 +1611,7 @@
   ArrayConstructorStub stub(isolate());
   __ TailCallStub(&stub);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1677,14 +1625,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- a2    : name
-  //  -- ra    : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1693,22 +1633,11 @@
   }
 
   Label miss;
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  Register receiver = a0;
+  Register scratch = a1;
 
-  GenerateNameCheck(name, &miss);
-
-  Register receiver = a1;
-
-  // Get the receiver from the stack.
   const int argc = arguments().immediate();
-  __ lw(receiver, MemOperand(sp, argc * kPointerSize));
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(receiver, &miss);
-
-  // Check that the maps haven't changed.
-  CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()), receiver, holder,
-      a3, v0, t0, name, &miss);
 
   if (argc == 0) {
     // Nothing to do, just return the length.
@@ -1726,34 +1655,34 @@
 
       // Check that the elements are in fast mode and writable.
       __ CheckMap(elements,
-                  v0,
+                  scratch,
                   Heap::kFixedArrayMapRootIndex,
                   &check_double,
                   DONT_DO_SMI_CHECK);
 
-      // Get the array's length into v0 and calculate new length.
-      __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      // Get the array's length into scratch and calculate new length.
+      __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
       STATIC_ASSERT(kSmiTagSize == 1);
       STATIC_ASSERT(kSmiTag == 0);
-      __ Addu(v0, v0, Operand(Smi::FromInt(argc)));
+      __ Addu(scratch, scratch, Operand(Smi::FromInt(argc)));
 
       // Get the elements' length.
       __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
       // Check if we could survive without allocation.
-      __ Branch(&attempt_to_grow_elements, gt, v0, Operand(t0));
+      __ Branch(&attempt_to_grow_elements, gt, scratch, Operand(t0));
 
       // Check if value is a smi.
       __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
       __ JumpIfNotSmi(t0, &with_write_barrier);
 
       // Save new length.
-      __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
       // Store the value.
       // We may need a register containing the address end_elements below,
       // so write back the value in end_elements.
-      __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize);
+      __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize);
       __ Addu(end_elements, elements, end_elements);
       const int kEndElementsOffset =
           FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
@@ -1761,38 +1690,39 @@
       __ sw(t0, MemOperand(end_elements));
 
       // Check for a smi.
+      __ mov(v0, scratch);
       __ DropAndRet(argc + 1);
 
       __ bind(&check_double);
 
       // Check that the elements are in fast mode and writable.
       __ CheckMap(elements,
-                  a0,
+                  scratch,
                   Heap::kFixedDoubleArrayMapRootIndex,
                   &call_builtin,
                   DONT_DO_SMI_CHECK);
 
-      // Get the array's length into v0 and calculate new length.
-      __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      // Get the array's length into scratch and calculate new length.
+      __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
       STATIC_ASSERT(kSmiTagSize == 1);
       STATIC_ASSERT(kSmiTag == 0);
-      __ Addu(v0, v0, Operand(Smi::FromInt(argc)));
+      __ Addu(scratch, scratch, Operand(Smi::FromInt(argc)));
 
       // Get the elements' length.
       __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
       // Check if we could survive without allocation.
-      __ Branch(&call_builtin, gt, v0, Operand(t0));
+      __ Branch(&call_builtin, gt, scratch, Operand(t0));
 
       __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
       __ StoreNumberToDoubleElements(
-          t0, v0, elements, a3, t1, a2,
+          t0, scratch, elements, a3, t1, a2,
           &call_builtin, argc * kDoubleSize);
 
       // Save new length.
-      __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
-      // Check for a smi.
+      __ mov(v0, scratch);
       __ DropAndRet(argc + 1);
 
       __ bind(&with_write_barrier);
@@ -1842,12 +1772,12 @@
       }
 
       // Save new length.
-      __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
       // Store the value.
       // We may need a register containing the address end_elements below,
       // so write back the value in end_elements.
-      __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize);
+      __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize);
       __ Addu(end_elements, elements, end_elements);
       __ Addu(end_elements, end_elements, kEndElementsOffset);
       __ sw(t0, MemOperand(end_elements));
@@ -1859,10 +1789,11 @@
                      kDontSaveFPRegs,
                      EMIT_REMEMBERED_SET,
                      OMIT_SMI_CHECK);
+      __ mov(v0, scratch);
       __ DropAndRet(argc + 1);
 
       __ bind(&attempt_to_grow_elements);
-      // v0: array's length + 1.
+      // scratch: array's length + 1.
       // t0: elements' length.
 
       if (!FLAG_inline_new) {
@@ -1885,7 +1816,7 @@
 
       const int kAllocationDelta = 4;
       // Load top and check if it is the end of elements.
-      __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize);
+      __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize);
       __ Addu(end_elements, elements, end_elements);
       __ Addu(end_elements, end_elements, Operand(kEndElementsOffset));
       __ li(t3, Operand(new_space_allocation_top));
@@ -1909,11 +1840,12 @@
       }
 
       // Update elements' and array's sizes.
-      __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset));
       __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta)));
       __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
       // Elements are in new space, so write barrier is not required.
+      __ mov(v0, scratch);
       __ DropAndRet(argc + 1);
     }
     __ bind(&call_builtin);
@@ -1921,9 +1853,7 @@
         ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1);
   }
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1937,14 +1867,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- a2    : name
-  //  -- ra    : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1953,27 +1875,17 @@
   }
 
   Label miss, return_undefined, call_builtin;
-  Register receiver = a1;
+  Register receiver = a0;
+  Register scratch = a1;
   Register elements = a3;
-  GenerateNameCheck(name, &miss);
-
-  // Get the receiver from the stack.
-  const int argc = arguments().immediate();
-  __ lw(receiver, MemOperand(sp, argc * kPointerSize));
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(receiver, &miss);
-
-  // Check that the maps haven't changed.
-  CheckPrototypes(
-      IC::CurrentTypeOf(object, isolate()), receiver, holder,
-      elements, t0, v0, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   // Get the elements array of the object.
   __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
 
   // Check that the elements are in fast mode and writable.
   __ CheckMap(elements,
-              v0,
+              scratch,
               Heap::kFixedArrayMapRootIndex,
               &call_builtin,
               DONT_DO_SMI_CHECK);
@@ -1991,14 +1903,16 @@
   // expensive shift first, and use an offset later on.
   __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize);
   __ Addu(elements, elements, t1);
-  __ lw(v0, FieldMemOperand(elements, FixedArray::kHeaderSize));
-  __ Branch(&call_builtin, eq, v0, Operand(t2));
+  __ lw(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize));
+  __ Branch(&call_builtin, eq, scratch, Operand(t2));
 
   // Set the array's length.
   __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset));
 
   // Fill with the hole.
   __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize));
+  const int argc = arguments().immediate();
+  __ mov(v0, scratch);
   __ DropAndRet(argc + 1);
 
   __ bind(&return_undefined);
@@ -2009,9 +1923,7 @@
   __ TailCallExternalReference(
       ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2025,18 +1937,9 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- a2                     : function name
-  //  -- ra                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
-  const int argc = arguments().immediate();
   Label miss;
   Label name_miss;
   Label index_out_of_range;
@@ -2049,22 +1952,12 @@
     index_out_of_range_label = &miss;
   }
 
-  GenerateNameCheck(name, &name_miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            v0,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate())));
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      v0, holder, a1, a3, t0, name, &miss);
-
-  Register receiver = a1;
+  Register receiver = a0;
   Register index = t1;
-  Register result = v0;
+  Register result = a1;
+  const int argc = arguments().immediate();
   __ lw(receiver, MemOperand(sp, argc * kPointerSize));
   if (argc > 0) {
     __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize));
@@ -2080,6 +1973,7 @@
                                       index_out_of_range_label,
                                       STRING_INDEX_IS_NUMBER);
   generator.GenerateFast(masm());
+  __ mov(v0, result);
   __ DropAndRet(argc + 1);
 
   StubRuntimeCallHelper call_helper;
@@ -2109,14 +2003,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- a2                     : function name
-  //  -- ra                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
@@ -2130,24 +2016,13 @@
        DEFAULT_STRING_STUB)) {
     index_out_of_range_label = &miss;
   }
-  GenerateNameCheck(name, &name_miss);
 
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            v0,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate())));
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      v0, holder, a1, a3, t0, name, &miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
-  Register receiver = v0;
+  Register receiver = a0;
   Register index = t1;
   Register scratch = a3;
-  Register result = v0;
-  __ lw(receiver, MemOperand(sp, argc * kPointerSize));
+  Register result = a1;
   if (argc > 0) {
     __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize));
   } else {
@@ -2163,6 +2038,7 @@
                                   index_out_of_range_label,
                                   STRING_INDEX_IS_NUMBER);
   generator.GenerateFast(masm());
+  __ mov(v0, result);
   __ DropAndRet(argc + 1);
 
   StubRuntimeCallHelper call_helper;
@@ -2192,14 +2068,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- a2                     : function name
-  //  -- ra                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
 
   // If the object is not a JSObject or we got an unexpected number of
@@ -2207,21 +2075,9 @@
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  if (cell.is_null()) {
-    __ lw(a1, MemOperand(sp, 1 * kPointerSize));
-
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(a1, &miss);
-
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()),
-        a1, holder, v0, a3, t0, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2251,9 +2107,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // a2: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2267,34 +2121,15 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- a2                     : function name
-  //  -- ra                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
-
   const int argc = arguments().immediate();
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss, slow;
-  GenerateNameCheck(name, &miss);
-
-  if (cell.is_null()) {
-    __ lw(a1, MemOperand(sp, 1 * kPointerSize));
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(a1, &miss);
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()),
-        a1, holder, a0, a3, t0, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2382,9 +2217,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // a2: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2398,14 +2231,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- a2                     : function name
-  //  -- ra                     : return address
-  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- sp[argc * 4]           : receiver
-  // -----------------------------------
-
   const int argc = arguments().immediate();
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
@@ -2413,18 +2238,9 @@
 
   Label miss;
 
-  GenerateNameCheck(name, &miss);
-  if (cell.is_null()) {
-    __ lw(a1, MemOperand(sp, 1 * kPointerSize));
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(a1, &miss);
-    CheckPrototypes(
-        IC::CurrentTypeOf(object, isolate()),
-        a1, holder, v0, a3, t0, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2483,9 +2299,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // a2: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2557,24 +2371,37 @@
 }
 
 
-void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
-                                              Handle<JSObject> holder,
-                                              Handle<Name> name,
-                                              CheckType check) {
+void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
+  if (object->IsGlobalObject()) {
+    const int argc = arguments().immediate();
+    const int receiver_offset = argc * kPointerSize;
+    __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
+    __ sw(a3, MemOperand(sp, receiver_offset));
+  }
+}
+
+
+Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
+                                                 Handle<JSObject> holder,
+                                                 Handle<Name> name,
+                                                 CheckType check,
+                                                 Label* miss) {
   // ----------- S t a t e -------------
   //  -- a2    : name
   //  -- ra    : return address
   // -----------------------------------
-  Label miss;
-  GenerateNameCheck(name, &miss);
+  GenerateNameCheck(name, miss);
+
+  Register reg = a0;
 
   // Get the receiver from the stack.
   const int argc = arguments().immediate();
-  __ lw(a1, MemOperand(sp, argc * kPointerSize));
+  const int receiver_offset = argc * kPointerSize;
+  __ lw(a0, MemOperand(sp, receiver_offset));
 
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
-    __ JumpIfSmi(a1, &miss);
+    __ JumpIfSmi(a0, miss);
   }
 
   // Make sure that it's okay not to patch the on stack receiver
@@ -2582,86 +2409,62 @@
   ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
   switch (check) {
     case RECEIVER_MAP_CHECK:
-      __ IncrementCounter(isolate()->counters()->call_const(), 1, a0, a3);
+      __ IncrementCounter(isolate()->counters()->call_const(), 1, a1, a3);
 
       // Check that the maps haven't changed.
-      CheckPrototypes(
+      reg = CheckPrototypes(
           IC::CurrentTypeOf(object, isolate()),
-          a1, holder, a0, a3, t0, name, &miss);
-
-      // Patch the receiver on the stack with the global proxy if
-      // necessary.
-      if (object->IsGlobalObject()) {
-        __ lw(a3, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset));
-        __ sw(a3, MemOperand(sp, argc * kPointerSize));
-      }
+          reg, holder, a1, a3, t0, name, miss);
       break;
 
     case STRING_CHECK: {
       // Check that the object is a string.
-      __ GetObjectType(a1, a3, a3);
-      __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE));
+      __ GetObjectType(reg, a3, a3);
+      __ Branch(miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE));
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::STRING_FUNCTION_INDEX, a0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          a0, holder, a3, a1, t0, name, &miss);
+          masm(), Context::STRING_FUNCTION_INDEX, a1, miss);
       break;
     }
     case SYMBOL_CHECK: {
       // Check that the object is a symbol.
-      __ GetObjectType(a1, a1, a3);
-      __ Branch(&miss, ne, a3, Operand(SYMBOL_TYPE));
+      __ GetObjectType(reg, a1, a3);
+      __ Branch(miss, ne, a3, Operand(SYMBOL_TYPE));
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::SYMBOL_FUNCTION_INDEX, a0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          a0, holder, a3, a1, t0, name, &miss);
+          masm(), Context::SYMBOL_FUNCTION_INDEX, a1, miss);
       break;
     }
     case NUMBER_CHECK: {
       Label fast;
       // Check that the object is a smi or a heap number.
-      __ JumpIfSmi(a1, &fast);
-      __ GetObjectType(a1, a0, a0);
-      __ Branch(&miss, ne, a0, Operand(HEAP_NUMBER_TYPE));
+      __ JumpIfSmi(reg, &fast);
+      __ GetObjectType(reg, a3, a3);
+      __ Branch(miss, ne, a3, Operand(HEAP_NUMBER_TYPE));
       __ bind(&fast);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::NUMBER_FUNCTION_INDEX, a0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          a0, holder, a3, a1, t0, name, &miss);
+          masm(), Context::NUMBER_FUNCTION_INDEX, a1, miss);
       break;
     }
     case BOOLEAN_CHECK: {
-      GenerateBooleanCheck(a1, &miss);
+      GenerateBooleanCheck(reg, miss);
 
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::BOOLEAN_FUNCTION_INDEX, a0, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          a0, holder, a3, a1, t0, name, &miss);
+          masm(), Context::BOOLEAN_FUNCTION_INDEX, a1, miss);
       break;
     }
   }
 
-  Label success;
-  __ Branch(&success);
+  if (check != RECEIVER_MAP_CHECK) {
+    Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
+    reg = CheckPrototypes(
+        IC::CurrentTypeOf(prototype, isolate()),
+        a1, holder, a1, a3, t0, name, miss);
+  }
 
-  // Handle call cache miss.
-  __ bind(&miss);
-
-  GenerateMissBranch();
-
-  __ bind(&success);
+  return reg;
 }
 
 
@@ -2690,8 +2493,11 @@
     if (!code.is_null()) return code;
   }
 
-  CompileHandlerFrontend(object, holder, name, check);
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
+  PatchGlobalProxy(object);
   CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(function);
@@ -2701,11 +2507,6 @@
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
                                                       Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
-
   Label miss;
 
   GenerateNameCheck(name, &miss);
@@ -2744,11 +2545,6 @@
     Handle<PropertyCell> cell,
     Handle<JSFunction> function,
     Handle<Name> name) {
-  // ----------- S t a t e -------------
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
-
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
         object, holder, cell, function, Handle<String>::cast(name),
@@ -2758,19 +2554,9 @@
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  // Get the number of arguments.
-  const int argc = arguments().immediate();
-  GenerateGlobalReceiverCheck(object, holder, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateLoadFunctionFromCell(cell, function, &miss);
-
-  // Patch the receiver on the stack with the global proxy if
-  // necessary.
-  if (object->IsGlobalObject()) {
-    __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
-    __ sw(a3, MemOperand(sp, argc * kPointerSize));
-  }
+  PatchGlobalProxy(object);
 
   // Set up the context (function already in r1).
   __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
@@ -2789,10 +2575,7 @@
   __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION,
                 NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::NORMAL, name);
@@ -2911,13 +2694,10 @@
 
   __ Push(receiver(), this->name(), value());
 
-  __ li(scratch1(), Operand(Smi::FromInt(strict_mode())));
-  __ push(scratch1());  // strict mode
-
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
-  __ TailCallExternalReference(store_ic_property, 4, 1);
+  __ TailCallExternalReference(store_ic_property, 3, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 832a682..ee81c2f 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -3889,14 +3889,14 @@
 }
 
 
-Code::ExtraICState Code::extra_ic_state() {
+ExtraICState Code::extra_ic_state() {
   ASSERT((is_inline_cache_stub() && !needs_extended_extra_ic_state(kind()))
          || ic_state() == DEBUG_STUB);
   return ExtractExtraICStateFromFlags(flags());
 }
 
 
-Code::ExtraICState Code::extended_extra_ic_state() {
+ExtraICState Code::extended_extra_ic_state() {
   ASSERT(is_inline_cache_stub() || ic_state() == DEBUG_STUB);
   ASSERT(needs_extended_extra_ic_state(kind()));
   return ExtractExtendedExtraICStateFromFlags(flags());
@@ -4233,12 +4233,12 @@
 }
 
 
-Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
+ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
   return ExtraICStateField::decode(flags);
 }
 
 
-Code::ExtraICState Code::ExtractExtendedExtraICStateFromFlags(
+ExtraICState Code::ExtractExtendedExtraICStateFromFlags(
     Flags flags) {
   return ExtendedExtraICStateField::decode(flags);
 }
diff --git a/src/objects.h b/src/objects.h
index 6fbba3c..db92ecb 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -179,6 +179,12 @@
 };
 
 
+enum ContextualMode {
+  NOT_CONTEXTUAL,
+  CONTEXTUAL
+};
+
+
 static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
     STANDARD_STORE;
 STATIC_ASSERT(STANDARD_STORE == 0);
@@ -297,6 +303,11 @@
   EVEN_MARKING_PARITY
 };
 
+// ICs store extra state in a Code object. The default extra state is
+// kNoExtraICState.
+typedef int ExtraICState;
+static const ExtraICState kNoExtraICState = 0;
+
 // Instance size sentinel for objects of variable size.
 const int kVariableSizeSentinel = 0;
 
@@ -5036,10 +5047,6 @@
     FAST
   };
 
-  typedef int ExtraICState;
-
-  static const ExtraICState kNoExtraICState = 0;
-
   static const int kPrologueOffsetNotSet = -1;
 
 #ifdef ENABLE_DISASSEMBLER
@@ -5259,26 +5266,6 @@
   // out the to-be-overwritten header data for reproducible snapshots.
   inline void WipeOutHeader();
 
-  class ExtraICStateStrictMode: public BitField<StrictModeFlag, 0, 1> {};
-  class ExtraICStateKeyedAccessStoreMode:
-      public BitField<KeyedAccessStoreMode, 1, 4> {};  // NOLINT
-
-  static inline StrictModeFlag GetStrictMode(ExtraICState extra_ic_state) {
-    return ExtraICStateStrictMode::decode(extra_ic_state);
-  }
-
-  static inline KeyedAccessStoreMode GetKeyedAccessStoreMode(
-      ExtraICState extra_ic_state) {
-    return ExtraICStateKeyedAccessStoreMode::decode(extra_ic_state);
-  }
-
-  static inline ExtraICState ComputeExtraICState(
-      KeyedAccessStoreMode store_mode,
-      StrictModeFlag strict_mode) {
-    return ExtraICStateKeyedAccessStoreMode::encode(store_mode) |
-        ExtraICStateStrictMode::encode(strict_mode);
-  }
-
   // Flags operations.
   static inline Flags ComputeFlags(
       Kind kind,
@@ -5462,12 +5449,12 @@
   // Flags layout.  BitField<type, shift, size>.
   class ICStateField: public BitField<InlineCacheState, 0, 3> {};
   class TypeField: public BitField<StubType, 3, 1> {};
-  class CacheHolderField: public BitField<InlineCacheHolderFlag, 6, 1> {};
-  class KindField: public BitField<Kind, 7, 4> {};
-  class IsPregeneratedField: public BitField<bool, 11, 1> {};
-  class ExtraICStateField: public BitField<ExtraICState, 12, 5> {};
-  class ExtendedExtraICStateField: public BitField<ExtraICState, 12,
-      PlatformSmiTagging::kSmiValueSize - 12 + 1> {};  // NOLINT
+  class CacheHolderField: public BitField<InlineCacheHolderFlag, 5, 1> {};
+  class KindField: public BitField<Kind, 6, 4> {};
+  class IsPregeneratedField: public BitField<bool, 10, 1> {};
+  class ExtraICStateField: public BitField<ExtraICState, 11, 6> {};
+  class ExtendedExtraICStateField: public BitField<ExtraICState, 11,
+      PlatformSmiTagging::kSmiValueSize - 11 + 1> {};  // NOLINT
   STATIC_ASSERT(ExtraICStateField::kShift == ExtendedExtraICStateField::kShift);
 
   // KindSpecificFlags1 layout (STUB and OPTIMIZED_FUNCTION)
diff --git a/src/serialize.h b/src/serialize.h
index 47627ac..90f78bf 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -364,7 +364,7 @@
     high_water_[space_index] = address + size;
     HeapProfiler* profiler = isolate_->heap_profiler();
     if (profiler->is_tracking_allocations()) {
-      profiler->NewObjectEvent(address, size);
+      profiler->AllocationEvent(address, size);
     }
     return address;
   }
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 06edc0d..5121cad 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -102,7 +102,7 @@
 Handle<Code> StubCache::FindIC(Handle<Name> name,
                                Handle<Map> stub_holder,
                                Code::Kind kind,
-                               Code::ExtraICState extra_state,
+                               ExtraICState extra_state,
                                InlineCacheHolderFlag cache_holder) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(
       kind, extra_state, cache_holder);
@@ -115,15 +115,9 @@
 Handle<Code> StubCache::FindHandler(Handle<Name> name,
                                     Handle<Map> stub_holder,
                                     Code::Kind kind,
-                                    InlineCacheHolderFlag cache_holder,
-                                    StrictModeFlag strict_mode) {
-  Code::ExtraICState extra_ic_state = Code::kNoExtraICState;
-  if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) {
-    extra_ic_state = Code::ComputeExtraICState(
-        STANDARD_STORE, strict_mode);
-  }
+                                    InlineCacheHolderFlag cache_holder) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(
-      Code::HANDLER, extra_ic_state, cache_holder, Code::NORMAL, kind);
+      Code::HANDLER, kNoExtraICState, cache_holder, Code::NORMAL, kind);
 
   Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_);
   if (probe->IsCode()) return Handle<Code>::cast(probe);
@@ -131,10 +125,11 @@
 }
 
 
-Handle<Code> StubCache::ComputeMonomorphicIC(Handle<Name> name,
-                                             Handle<Type> type,
-                                             Handle<Code> handler,
-                                             StrictModeFlag strict_mode) {
+Handle<Code> StubCache::ComputeMonomorphicIC(
+    Handle<Name> name,
+    Handle<Type> type,
+    Handle<Code> handler,
+    ExtraICState extra_ic_state) {
   Code::Kind kind = handler->handler_kind();
   InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type);
 
@@ -146,7 +141,7 @@
   bool can_be_cached = !type->Is(Type::String());
   if (can_be_cached) {
     stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate());
-    ic = FindIC(name, stub_holder, kind, strict_mode, flag);
+    ic = FindIC(name, stub_holder, kind, extra_ic_state, flag);
     if (!ic.is_null()) return ic;
   }
 
@@ -157,10 +152,12 @@
     KeyedLoadStubCompiler ic_compiler(isolate(), flag);
     ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
   } else if (kind == Code::STORE_IC) {
+    StrictModeFlag strict_mode = StoreIC::GetStrictMode(extra_ic_state);
     StoreStubCompiler ic_compiler(isolate(), strict_mode);
     ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
   } else {
     ASSERT(kind == Code::KEYED_STORE_IC);
+    StrictModeFlag strict_mode = StoreIC::GetStrictMode(extra_ic_state);
     KeyedStoreStubCompiler ic_compiler(isolate(), strict_mode, STANDARD_STORE);
     ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
   }
@@ -224,8 +221,8 @@
     Handle<Map> receiver_map,
     StrictModeFlag strict_mode,
     KeyedAccessStoreMode store_mode) {
-  Code::ExtraICState extra_state =
-      Code::ComputeExtraICState(store_mode, strict_mode);
+  ExtraICState extra_state =
+      KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode);
   Code::Flags flags = Code::ComputeMonomorphicFlags(
       Code::KEYED_STORE_IC, extra_state);
 
@@ -243,7 +240,8 @@
   Handle<Code> code = compiler.CompileStoreElement(receiver_map);
 
   Map::UpdateCodeCache(receiver_map, name, code);
-  ASSERT(Code::GetKeyedAccessStoreMode(code->extra_ic_state()) == store_mode);
+  ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state())
+         == store_mode);
   return code;
 }
 
@@ -253,7 +251,7 @@
 
 Handle<Code> StubCache::ComputeCallConstant(int argc,
                                             Code::Kind kind,
-                                            Code::ExtraICState extra_state,
+                                            ExtraICState extra_state,
                                             Handle<Name> name,
                                             Handle<Object> object,
                                             Handle<JSObject> holder,
@@ -307,7 +305,7 @@
 
 Handle<Code> StubCache::ComputeCallField(int argc,
                                          Code::Kind kind,
-                                         Code::ExtraICState extra_state,
+                                         ExtraICState extra_state,
                                          Handle<Name> name,
                                          Handle<Object> object,
                                          Handle<JSObject> holder,
@@ -346,7 +344,7 @@
 
 Handle<Code> StubCache::ComputeCallInterceptor(int argc,
                                                Code::Kind kind,
-                                               Code::ExtraICState extra_state,
+                                               ExtraICState extra_state,
                                                Handle<Name> name,
                                                Handle<Object> object,
                                                Handle<JSObject> holder) {
@@ -384,7 +382,7 @@
 
 Handle<Code> StubCache::ComputeCallGlobal(int argc,
                                           Code::Kind kind,
-                                          Code::ExtraICState extra_state,
+                                          ExtraICState extra_state,
                                           Handle<Name> name,
                                           Handle<JSObject> receiver,
                                           Handle<GlobalObject> holder,
@@ -422,9 +420,10 @@
 Code* StubCache::FindCallInitialize(int argc,
                                     RelocInfo::Mode mode,
                                     Code::Kind kind) {
-  Code::ExtraICState extra_state =
+  ExtraICState extra_state =
       CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
-      CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
+      CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT
+                                         ? CONTEXTUAL : NOT_CONTEXTUAL);
   Code::Flags flags =
       Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
   UnseededNumberDictionary* dictionary =
@@ -441,9 +440,10 @@
 Handle<Code> StubCache::ComputeCallInitialize(int argc,
                                               RelocInfo::Mode mode,
                                               Code::Kind kind) {
-  Code::ExtraICState extra_state =
+  ExtraICState extra_state =
       CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
-      CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
+      CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT
+                                         ? CONTEXTUAL : NOT_CONTEXTUAL);
   Code::Flags flags =
       Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
   Handle<UnseededNumberDictionary> cache =
@@ -472,7 +472,7 @@
 Handle<Code> StubCache::ComputeCallPreMonomorphic(
     int argc,
     Code::Kind kind,
-    Code::ExtraICState extra_state) {
+    ExtraICState extra_state) {
   Code::Flags flags =
       Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc);
   Handle<UnseededNumberDictionary> cache =
@@ -489,7 +489,7 @@
 
 Handle<Code> StubCache::ComputeCallNormal(int argc,
                                           Code::Kind kind,
-                                          Code::ExtraICState extra_state) {
+                                          ExtraICState extra_state) {
   Code::Flags flags =
       Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc);
   Handle<UnseededNumberDictionary> cache =
@@ -507,7 +507,7 @@
 Handle<Code> StubCache::ComputeCallArguments(int argc) {
   Code::Flags flags =
       Code::ComputeFlags(Code::KEYED_CALL_IC, MEGAMORPHIC,
-                         Code::kNoExtraICState, Code::NORMAL, argc);
+                         kNoExtraICState, Code::NORMAL, argc);
   Handle<UnseededNumberDictionary> cache =
       isolate_->factory()->non_monomorphic_cache();
   int entry = cache->FindEntry(isolate_, flags);
@@ -523,7 +523,7 @@
 Handle<Code> StubCache::ComputeCallMegamorphic(
     int argc,
     Code::Kind kind,
-    Code::ExtraICState extra_state) {
+    ExtraICState extra_state) {
   Code::Flags flags =
       Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
                          Code::NORMAL, argc);
@@ -541,7 +541,7 @@
 
 Handle<Code> StubCache::ComputeCallMiss(int argc,
                                         Code::Kind kind,
-                                        Code::ExtraICState extra_state) {
+                                        ExtraICState extra_state) {
   // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
   // and monomorphic stubs are not mixed up together in the stub cache.
   Code::Flags flags =
@@ -605,11 +605,13 @@
 }
 
 
-Handle<Code> StubCache::ComputePolymorphicIC(TypeHandleList* types,
-                                             CodeHandleList* handlers,
-                                             int number_of_valid_types,
-                                             Handle<Name> name,
-                                             StrictModeFlag strict_mode) {
+Handle<Code> StubCache::ComputePolymorphicIC(
+    TypeHandleList* types,
+    CodeHandleList* handlers,
+    int number_of_valid_types,
+    Handle<Name> name,
+    ExtraICState extra_ic_state) {
+
   Handle<Code> handler = handlers->at(0);
   Code::Kind kind = handler->handler_kind();
   Code::StubType type = number_of_valid_types == 1 ? handler->type()
@@ -620,6 +622,7 @@
         types, handlers, name, type, PROPERTY);
   } else {
     ASSERT(kind == Code::STORE_IC);
+    StrictModeFlag strict_mode = StoreIC::GetStrictMode(extra_ic_state);
     StoreStubCompiler ic_compiler(isolate_, strict_mode);
     return ic_compiler.CompilePolymorphicIC(
         types, handlers, name, type, PROPERTY);
@@ -637,8 +640,8 @@
          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
   Handle<PolymorphicCodeCache> cache =
       isolate_->factory()->polymorphic_code_cache();
-  Code::ExtraICState extra_state = Code::ComputeExtraICState(store_mode,
-                                                             strict_mode);
+  ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState(
+      strict_mode, store_mode);
   Code::Flags flags =
       Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state);
   Handle<Object> probe = cache->Lookup(receiver_maps, flags);
@@ -921,16 +924,15 @@
 
 RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
   HandleScope scope(isolate);
-  ASSERT(args.length() == 4);
-  Handle<JSObject> recv(JSObject::cast(args[0]));
-  Handle<Name> name(Name::cast(args[1]));
-  Handle<Object> value(args[2], isolate);
-  ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
-  StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
-  ASSERT(recv->HasNamedInterceptor());
+  ASSERT(args.length() == 3);
+  StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
+  Handle<JSObject> receiver = args.at<JSObject>(0);
+  Handle<Name> name = args.at<Name>(1);
+  Handle<Object> value = args.at<Object>(2);
+  ASSERT(receiver->HasNamedInterceptor());
   PropertyAttributes attr = NONE;
   Handle<Object> result = JSObject::SetPropertyWithInterceptor(
-      recv, name, value, attr, strict_mode);
+      receiver, name, value, attr, ic.strict_mode());
   RETURN_IF_EMPTY_HANDLE(isolate, result);
   return *result;
 }
@@ -947,7 +949,7 @@
 Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
-  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
+  ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
   if (kind == Code::CALL_IC) {
     CallIC::GenerateInitialize(masm(), argc, extra_state);
   } else {
@@ -968,7 +970,7 @@
   // The code of the PreMonomorphic stub is the same as the code
   // of the Initialized stub.  They just differ on the code object flags.
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
-  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
+  ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
   if (kind == Code::CALL_IC) {
     CallIC::GenerateInitialize(masm(), argc, extra_state);
   } else {
@@ -1008,7 +1010,7 @@
 Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
-  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
+  ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
   if (kind == Code::CALL_IC) {
     CallIC::GenerateMegamorphic(masm(), argc, extra_state);
   } else {
@@ -1040,7 +1042,7 @@
 Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
   int argc = Code::ExtractArgumentsCountFromFlags(flags);
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
-  Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
+  ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
   if (kind == Code::CALL_IC) {
     CallIC::GenerateMiss(masm(), argc, extra_state);
   } else {
@@ -1075,7 +1077,7 @@
   Code::Kind kind = Code::ExtractKindFromFlags(flags);
   if (kind == Code::CALL_IC) {
     // For the debugger extra ic state is irrelevant.
-    CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
+    CallIC::GenerateMiss(masm(), argc, kNoExtraICState);
   } else {
     KeyedCallIC::GenerateMiss(masm(), argc);
   }
@@ -1126,6 +1128,12 @@
 #define __ ACCESS_MASM(masm())
 
 
+void CallStubCompiler::HandlerFrontendFooter(Label* miss) {
+  __ bind(miss);
+  GenerateMissBranch();
+}
+
+
 Register LoadStubCompiler::HandlerFrontendHeader(
     Handle<Type> type,
     Register object_reg,
@@ -1679,7 +1687,7 @@
 CallStubCompiler::CallStubCompiler(Isolate* isolate,
                                    int argc,
                                    Code::Kind kind,
-                                   Code::ExtraICState extra_state,
+                                   ExtraICState extra_state,
                                    InlineCacheHolderFlag cache_holder)
     : StubCompiler(isolate),
       arguments_(argc),
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 199fca5..c9510a8 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -83,19 +83,18 @@
   Handle<Code> FindIC(Handle<Name> name,
                       Handle<Map> stub_holder_map,
                       Code::Kind kind,
-                      Code::ExtraICState extra_state = Code::kNoExtraICState,
+                      ExtraICState extra_state = kNoExtraICState,
                       InlineCacheHolderFlag cache_holder = OWN_MAP);
 
   Handle<Code> FindHandler(Handle<Name> name,
                            Handle<Map> map,
                            Code::Kind kind,
-                           InlineCacheHolderFlag cache_holder = OWN_MAP,
-                           StrictModeFlag strict_mode = kNonStrictMode);
+                           InlineCacheHolderFlag cache_holder = OWN_MAP);
 
   Handle<Code> ComputeMonomorphicIC(Handle<Name> name,
                                     Handle<Type> type,
                                     Handle<Code> handler,
-                                    StrictModeFlag strict_mode);
+                                    ExtraICState extra_ic_state);
 
   Handle<Code> ComputeLoadNonexistent(Handle<Name> name, Handle<Type> type);
 
@@ -107,7 +106,7 @@
 
   Handle<Code> ComputeCallField(int argc,
                                 Code::Kind,
-                                Code::ExtraICState extra_state,
+                                ExtraICState extra_state,
                                 Handle<Name> name,
                                 Handle<Object> object,
                                 Handle<JSObject> holder,
@@ -115,7 +114,7 @@
 
   Handle<Code> ComputeCallConstant(int argc,
                                    Code::Kind,
-                                   Code::ExtraICState extra_state,
+                                   ExtraICState extra_state,
                                    Handle<Name> name,
                                    Handle<Object> object,
                                    Handle<JSObject> holder,
@@ -123,14 +122,14 @@
 
   Handle<Code> ComputeCallInterceptor(int argc,
                                       Code::Kind,
-                                      Code::ExtraICState extra_state,
+                                      ExtraICState extra_state,
                                       Handle<Name> name,
                                       Handle<Object> object,
                                       Handle<JSObject> holder);
 
   Handle<Code> ComputeCallGlobal(int argc,
                                  Code::Kind,
-                                 Code::ExtraICState extra_state,
+                                 ExtraICState extra_state,
                                  Handle<Name> name,
                                  Handle<JSObject> object,
                                  Handle<GlobalObject> holder,
@@ -145,21 +144,21 @@
 
   Handle<Code> ComputeCallPreMonomorphic(int argc,
                                          Code::Kind kind,
-                                         Code::ExtraICState extra_state);
+                                         ExtraICState extra_state);
 
   Handle<Code> ComputeCallNormal(int argc,
                                  Code::Kind kind,
-                                 Code::ExtraICState state);
+                                 ExtraICState state);
 
   Handle<Code> ComputeCallArguments(int argc);
 
   Handle<Code> ComputeCallMegamorphic(int argc,
                                       Code::Kind kind,
-                                      Code::ExtraICState state);
+                                      ExtraICState state);
 
   Handle<Code> ComputeCallMiss(int argc,
                                Code::Kind kind,
-                               Code::ExtraICState state);
+                               ExtraICState state);
 
   // ---
 
@@ -177,7 +176,7 @@
                                     CodeHandleList* handlers,
                                     int number_of_valid_maps,
                                     Handle<Name> name,
-                                    StrictModeFlag strict_mode);
+                                    ExtraICState extra_ic_state);
 
   // Finds the Code object stored in the Heap::non_monomorphic_cache().
   Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
@@ -590,7 +589,7 @@
   }
   void JitEvent(Handle<Name> name, Handle<Code> code);
 
-  virtual Code::ExtraICState extra_state() { return Code::kNoExtraICState; }
+  virtual ExtraICState extra_state() { return kNoExtraICState; }
   virtual Register receiver() = 0;
   virtual Register name() = 0;
   virtual Register scratch1() = 0;
@@ -828,7 +827,9 @@
   virtual Register scratch2() { return registers_[4]; }
   virtual Register scratch3() { return registers_[5]; }
   StrictModeFlag strict_mode() { return strict_mode_; }
-  virtual Code::ExtraICState extra_state() { return strict_mode_; }
+  virtual ExtraICState extra_state() {
+    return StoreIC::ComputeExtraICState(strict_mode_);
+  }
 
  protected:
   static Register* registers();
@@ -858,8 +859,8 @@
   static void GenerateStoreDictionaryElement(MacroAssembler* masm);
 
  protected:
-  virtual Code::ExtraICState extra_state() {
-    return Code::ComputeExtraICState(store_mode_, strict_mode());
+  virtual ExtraICState extra_state() {
+    return KeyedStoreIC::ComputeExtraICState(strict_mode(), store_mode_);
   }
   static Register* registers();
 
@@ -898,7 +899,7 @@
   CallStubCompiler(Isolate* isolate,
                    int argc,
                    Code::Kind kind,
-                   Code::ExtraICState extra_state,
+                   ExtraICState extra_state,
                    InlineCacheHolderFlag cache_holder = OWN_MAP);
 
   Handle<Code> CompileCallField(Handle<JSObject> object,
@@ -906,10 +907,17 @@
                                 PropertyIndex index,
                                 Handle<Name> name);
 
-  void CompileHandlerFrontend(Handle<Object> object,
-                              Handle<JSObject> holder,
-                              Handle<Name> name,
-                              CheckType check);
+  // Patch the global proxy over the global object if the global object is the
+  // receiver.
+  void PatchGlobalProxy(Handle<Object> object);
+
+  // Returns the register containing the holder of |name|.
+  Register HandlerFrontendHeader(Handle<Object> object,
+                                 Handle<JSObject> holder,
+                                 Handle<Name> name,
+                                 CheckType check,
+                                 Label* miss);
+  void HandlerFrontendFooter(Label* miss);
 
   void CompileHandlerBackend(Handle<JSFunction> function);
 
@@ -967,11 +975,6 @@
 
   void GenerateNameCheck(Handle<Name> name, Label* miss);
 
-  void GenerateGlobalReceiverCheck(Handle<JSObject> object,
-                                   Handle<JSObject> holder,
-                                   Handle<Name> name,
-                                   Label* miss);
-
   // Generates code to load the function from the cell checking that
   // it still contains the same function.
   void GenerateLoadFunctionFromCell(Handle<Cell> cell,
@@ -983,7 +986,7 @@
 
   const ParameterCount arguments_;
   const Code::Kind kind_;
-  const Code::ExtraICState extra_state_;
+  const ExtraICState extra_state_;
   const InlineCacheHolderFlag cache_holder_;
 };
 
diff --git a/src/type-info.cc b/src/type-info.cc
index 59850c7..79134ca 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -99,8 +99,8 @@
 }
 
 
-bool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) {
-  Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId());
+bool TypeFeedbackOracle::LoadIsUninitialized(TypeFeedbackId id) {
+  Handle<Object> map_or_code = GetInfo(id);
   if (map_or_code->IsMap()) return false;
   if (map_or_code->IsCode()) {
     Handle<Code> code = Handle<Code>::cast(map_or_code);
@@ -110,8 +110,8 @@
 }
 
 
-bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) {
-  Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId());
+bool TypeFeedbackOracle::LoadIsMonomorphicNormal(TypeFeedbackId id) {
+  Handle<Object> map_or_code = GetInfo(id);
   if (map_or_code->IsMap()) return true;
   if (map_or_code->IsCode()) {
     Handle<Code> code = Handle<Code>::cast(map_or_code);
@@ -128,8 +128,8 @@
 }
 
 
-bool TypeFeedbackOracle::LoadIsPreMonomorphic(Property* expr) {
-  Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId());
+bool TypeFeedbackOracle::LoadIsPreMonomorphic(TypeFeedbackId id) {
+  Handle<Object> map_or_code = GetInfo(id);
   if (map_or_code->IsCode()) {
     Handle<Code> code = Handle<Code>::cast(map_or_code);
     return code->is_inline_cache_stub() && code->ic_state() == PREMONOMORPHIC;
@@ -138,8 +138,8 @@
 }
 
 
-bool TypeFeedbackOracle::LoadIsPolymorphic(Property* expr) {
-  Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId());
+bool TypeFeedbackOracle::LoadIsPolymorphic(TypeFeedbackId id) {
+  Handle<Object> map_or_code = GetInfo(id);
   if (map_or_code->IsCode()) {
     Handle<Code> code = Handle<Code>::cast(map_or_code);
     return code->is_keyed_load_stub() && code->ic_state() == POLYMORPHIC;
@@ -233,9 +233,9 @@
 }
 
 
-Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(Property* expr) {
-  ASSERT(LoadIsMonomorphicNormal(expr));
-  Handle<Object> map_or_code = GetInfo(expr->PropertyFeedbackId());
+Handle<Map> TypeFeedbackOracle::LoadMonomorphicReceiverType(TypeFeedbackId id) {
+  ASSERT(LoadIsMonomorphicNormal(id));
+  Handle<Object> map_or_code = GetInfo(id);
   if (map_or_code->IsCode()) {
     Handle<Code> code = Handle<Code>::cast(map_or_code);
     Map* map = code->FindFirstMap()->CurrentMapForDeprecated();
@@ -268,20 +268,20 @@
   if (map_or_code->IsCode()) {
     Handle<Code> code = Handle<Code>::cast(map_or_code);
     if (code->kind() == Code::KEYED_STORE_IC) {
-      return Code::GetKeyedAccessStoreMode(code->extra_ic_state());
+      return KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state());
     }
   }
   return STANDARD_STORE;
 }
 
 
-void TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
+void TypeFeedbackOracle::LoadReceiverTypes(TypeFeedbackId id,
                                            Handle<String> name,
                                            SmallMapList* types) {
   Code::Flags flags = Code::ComputeFlags(
-      Code::HANDLER, MONOMORPHIC, Code::kNoExtraICState,
+      Code::HANDLER, MONOMORPHIC, kNoExtraICState,
       Code::NORMAL, Code::LOAD_IC);
-  CollectReceiverTypes(expr->PropertyFeedbackId(), name, flags, types);
+  CollectReceiverTypes(id, name, flags, types);
 }
 
 
@@ -289,7 +289,7 @@
                                             Handle<String> name,
                                             SmallMapList* types) {
   Code::Flags flags = Code::ComputeFlags(
-      Code::HANDLER, MONOMORPHIC, Code::kNoExtraICState,
+      Code::HANDLER, MONOMORPHIC, kNoExtraICState,
       Code::NORMAL, Code::STORE_IC);
   CollectReceiverTypes(expr->AssignmentFeedbackId(), name, flags, types);
 }
@@ -303,8 +303,11 @@
 
   // Note: Currently we do not take string extra ic data into account
   // here.
-  Code::ExtraICState extra_ic_state =
-      CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION);
+  ContextualMode contextual_mode = call_kind == CALL_AS_FUNCTION
+      ? CONTEXTUAL
+      : NOT_CONTEXTUAL;
+  ExtraICState extra_ic_state =
+      CallIC::Contextual::encode(contextual_mode);
 
   Code::Flags flags = Code::ComputeMonomorphicFlags(
       Code::CALL_IC, extra_ic_state, OWN_MAP, Code::NORMAL, arity);
@@ -353,14 +356,14 @@
 }
 
 
-bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
-  return *GetInfo(expr->PropertyFeedbackId()) ==
-      isolate_->builtins()->builtin(id);
+bool TypeFeedbackOracle::LoadIsBuiltin(
+    TypeFeedbackId id, Builtins::Name builtin) {
+  return *GetInfo(id) == isolate_->builtins()->builtin(builtin);
 }
 
 
-bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) {
-  Handle<Object> object = GetInfo(expr->PropertyFeedbackId());
+bool TypeFeedbackOracle::LoadIsStub(TypeFeedbackId id, ICStub* stub) {
+  Handle<Object> object = GetInfo(id);
   if (!object->IsCode()) return false;
   Handle<Code> code = Handle<Code>::cast(object);
   if (!code->is_load_stub()) return false;
@@ -456,6 +459,33 @@
 }
 
 
+void TypeFeedbackOracle::PropertyReceiverTypes(
+    TypeFeedbackId id, Handle<String> name,
+    SmallMapList* receiver_types, bool* is_prototype) {
+  receiver_types->Clear();
+  FunctionPrototypeStub proto_stub(Code::LOAD_IC);
+  *is_prototype = LoadIsStub(id, &proto_stub);
+  if (!*is_prototype) {
+    LoadReceiverTypes(id, name, receiver_types);
+  }
+}
+
+
+void TypeFeedbackOracle::KeyedPropertyReceiverTypes(
+    TypeFeedbackId id, SmallMapList* receiver_types, bool* is_string) {
+  receiver_types->Clear();
+  *is_string = false;
+  if (LoadIsBuiltin(id, Builtins::kKeyedLoadIC_String)) {
+    *is_string = true;
+  } else if (LoadIsMonomorphicNormal(id)) {
+    receiver_types->Add(LoadMonomorphicReceiverType(id), zone());
+  } else if (LoadIsPolymorphic(id)) {
+    receiver_types->Reserve(kMaxKeyedPolymorphism, zone());
+    CollectKeyedReceiverTypes(id, receiver_types);
+  }
+}
+
+
 void TypeFeedbackOracle::CountReceiverTypes(
     TypeFeedbackId id, SmallMapList* receiver_types) {
   receiver_types->Clear();
diff --git a/src/type-info.h b/src/type-info.h
index d6b9207..05c76f2 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -241,10 +241,10 @@
                      Isolate* isolate,
                      Zone* zone);
 
-  bool LoadIsMonomorphicNormal(Property* expr);
-  bool LoadIsUninitialized(Property* expr);
-  bool LoadIsPreMonomorphic(Property* expr);
-  bool LoadIsPolymorphic(Property* expr);
+  bool LoadIsMonomorphicNormal(TypeFeedbackId id);
+  bool LoadIsUninitialized(TypeFeedbackId id);
+  bool LoadIsPreMonomorphic(TypeFeedbackId id);
+  bool LoadIsPolymorphic(TypeFeedbackId id);
   bool StoreIsUninitialized(TypeFeedbackId ast_id);
   bool StoreIsMonomorphicNormal(TypeFeedbackId ast_id);
   bool StoreIsPreMonomorphic(TypeFeedbackId ast_id);
@@ -260,12 +260,12 @@
   // be possible.
   byte ForInType(TypeFeedbackId id);
 
-  Handle<Map> LoadMonomorphicReceiverType(Property* expr);
+  Handle<Map> LoadMonomorphicReceiverType(TypeFeedbackId id);
   Handle<Map> StoreMonomorphicReceiverType(TypeFeedbackId id);
 
   KeyedAccessStoreMode GetStoreMode(TypeFeedbackId ast_id);
 
-  void LoadReceiverTypes(Property* expr,
+  void LoadReceiverTypes(TypeFeedbackId id,
                          Handle<String> name,
                          SmallMapList* types);
   void StoreReceiverTypes(Assignment* expr,
@@ -280,6 +280,16 @@
   void CollectPolymorphicStoreReceiverTypes(TypeFeedbackId ast_id,
                                             SmallMapList* types);
 
+  void PropertyReceiverTypes(TypeFeedbackId id,
+                             Handle<String> name,
+                             SmallMapList* receiver_types,
+                             bool* is_prototype);
+  void KeyedPropertyReceiverTypes(TypeFeedbackId id,
+                                  SmallMapList* receiver_types,
+                                  bool* is_string);
+  void CountReceiverTypes(TypeFeedbackId id,
+                          SmallMapList* receiver_types);
+
   static bool CanRetainOtherContext(Map* map, Context* native_context);
   static bool CanRetainOtherContext(JSFunction* function,
                                     Context* native_context);
@@ -293,8 +303,8 @@
 
   Handle<Map> GetObjectLiteralStoreMap(ObjectLiteralProperty* prop);
 
-  bool LoadIsBuiltin(Property* expr, Builtins::Name id);
-  bool LoadIsStub(Property* expr, ICStub* stub);
+  bool LoadIsBuiltin(TypeFeedbackId id, Builtins::Name builtin_id);
+  bool LoadIsStub(TypeFeedbackId id, ICStub* stub);
 
   // TODO(1571) We can't use ToBooleanStub::Types as the return value because
   // of various cycles in our headers. Death to tons of implementations in
@@ -315,7 +325,6 @@
                    Handle<Type>* combined);
 
   Handle<Type> CountType(TypeFeedbackId id);
-  void CountReceiverTypes(TypeFeedbackId id, SmallMapList* receiver_types);
 
   Handle<Type> ClauseType(TypeFeedbackId id);
 
diff --git a/src/typedarray.js b/src/typedarray.js
index ed9de23..21dd9c8 100644
--- a/src/typedarray.js
+++ b/src/typedarray.js
@@ -99,6 +99,9 @@
   function NAMEConstructByArrayLike(obj, arrayLike) {
     var length = arrayLike.length;
     var l = ToPositiveInteger(length, "invalid_typed_array_length");
+    if (l > %MaxSmi()) {
+      throw MakeRangeError("invalid_typed_array_length");
+    }
     if(!%TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l)) {
       for (var i = 0; i < l; i++) {
         // It is crucial that we let any execptions from arrayLike[i]
diff --git a/src/typing.cc b/src/typing.cc
index e5f4ce5..d9420ad 100644
--- a/src/typing.cc
+++ b/src/typing.cc
@@ -393,7 +393,7 @@
     Expression* target = expr->target();
     Property* prop = target->AsProperty();
     if (prop != NULL) {
-      prop->RecordTypeFeedback(oracle(), zone());
+      RECURSE(Visit(expr->target()));
       expr->RecordTypeFeedback(oracle(), zone());
     }
 
@@ -437,7 +437,27 @@
 
 void AstTyper::VisitProperty(Property* expr) {
   // Collect type feedback.
-  expr->RecordTypeFeedback(oracle(), zone());
+  TypeFeedbackId id = expr->PropertyFeedbackId();
+  expr->set_is_uninitialized(oracle()->LoadIsUninitialized(id));
+  if (!expr->IsUninitialized()) {
+    expr->set_is_pre_monomorphic(oracle()->LoadIsPreMonomorphic(id));
+    expr->set_is_monomorphic(oracle()->LoadIsMonomorphicNormal(id));
+    ASSERT(!expr->IsPreMonomorphic() || !expr->IsMonomorphic());
+    if (expr->key()->IsPropertyName()) {
+      Literal* lit_key = expr->key()->AsLiteral();
+      ASSERT(lit_key != NULL && lit_key->value()->IsString());
+      Handle<String> name = Handle<String>::cast(lit_key->value());
+      bool is_prototype;
+      oracle()->PropertyReceiverTypes(
+          id, name, expr->GetReceiverTypes(), &is_prototype);
+      expr->set_is_function_prototype(is_prototype);
+    } else {
+      bool is_string;
+      oracle()->KeyedPropertyReceiverTypes(
+          id, expr->GetReceiverTypes(), &is_string);
+      expr->set_is_string_access(is_string);
+    }
+  }
 
   RECURSE(Visit(expr->obj()));
   RECURSE(Visit(expr->key()));
diff --git a/src/version.cc b/src/version.cc
index b1bd0bf..e4705d2 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     23
-#define BUILD_NUMBER      14
+#define BUILD_NUMBER      15
 #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/ic-x64.cc b/src/x64/ic-x64.cc
index 667a523..e3d477d 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -833,7 +833,7 @@
 void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
                                                int argc,
                                                Code::Kind kind,
-                                               Code::ExtraICState extra_state) {
+                                               ExtraICState extra_state) {
   // ----------- S t a t e -------------
   // rcx                      : function name
   // rdx                      : receiver
@@ -946,7 +946,7 @@
 void CallICBase::GenerateMiss(MacroAssembler* masm,
                               int argc,
                               IC::UtilityId id,
-                              Code::ExtraICState extra_state) {
+                              ExtraICState extra_state) {
   // ----------- S t a t e -------------
   // rcx                 : function name
   // rsp[0]              : return address
@@ -1018,7 +1018,7 @@
 
 void CallIC::GenerateMegamorphic(MacroAssembler* masm,
                                  int argc,
-                                 Code::ExtraICState extra_ic_state) {
+                                 ExtraICState extra_ic_state) {
   // ----------- S t a t e -------------
   // rcx                 : function name
   // rsp[0]              : return address
@@ -1127,7 +1127,7 @@
   GenerateMonomorphicCacheProbe(masm,
                                 argc,
                                 Code::KEYED_CALL_IC,
-                                Code::kNoExtraICState);
+                                kNoExtraICState);
   // Fall through on miss.
 
   __ bind(&slow_call);
@@ -1354,7 +1354,7 @@
 
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeFlags(
-      Code::HANDLER, MONOMORPHIC, Code::kNoExtraICState,
+      Code::HANDLER, MONOMORPHIC, kNoExtraICState,
       Code::NORMAL, Code::LOAD_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
       masm, flags, rax, rcx, rbx, rdx);
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index e56bb54..046edbd 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -4363,11 +4363,11 @@
     __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
                         ToRegister(instr->temp()), kDontSaveFPRegs);
   } else {
+    ASSERT(ToRegister(instr->context()).is(rsi));
     PushSafepointRegistersScope scope(this);
     if (!object_reg.is(rax)) {
       __ movq(rax, object_reg);
     }
-    LoadContextFromDeferred(instr->context());
     __ Move(rbx, to_map);
     TransitionElementsKindStub stub(from_kind, to_kind);
     __ CallStub(&stub);
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 78bc5bb..eb00593 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -2266,7 +2266,7 @@
         object, NULL, new_map_reg, temp_reg);
     return result;
   } else {
-    LOperand* context = UseAny(instr->context());
+    LOperand* context = UseFixed(instr->context(), rsi);
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
     return AssignPointerMap(result);
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index e64698c..192f7ba 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -640,7 +640,7 @@
   CallInterceptorCompiler(StubCompiler* stub_compiler,
                           const ParameterCount& arguments,
                           Register name,
-                          Code::ExtraICState extra_ic_state)
+                          ExtraICState extra_ic_state)
       : stub_compiler_(stub_compiler),
         arguments_(arguments),
         name_(name),
@@ -825,7 +825,7 @@
   StubCompiler* stub_compiler_;
   const ParameterCount& arguments_;
   Register name_;
-  Code::ExtraICState extra_ic_state_;
+  ExtraICState extra_ic_state_;
 };
 
 
@@ -1537,23 +1537,6 @@
 }
 
 
-void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
-                                                   Handle<JSObject> holder,
-                                                   Handle<Name> name,
-                                                   Label* miss) {
-  ASSERT(holder->IsGlobalObject());
-
-  StackArgumentsAccessor args(rsp, arguments());
-  __ movq(rdx, args.GetReceiverOperand());
-
-
-  // Check that the maps haven't changed.
-  __ JumpIfSmi(rdx, miss);
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                  rbx, rax, rdi, name, miss);
-}
-
-
 void CallStubCompiler::GenerateLoadFunctionFromCell(
     Handle<Cell> cell,
     Handle<JSFunction> function,
@@ -1596,28 +1579,10 @@
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
                                                 Handle<Name> name) {
-  // ----------- S t a t e -------------
-  // rcx                 : function name
-  // rsp[0]              : return address
-  // rsp[8]              : argument argc
-  // rsp[16]             : argument argc - 1
-  // ...
-  // rsp[argc * 8]       : argument 1
-  // rsp[(argc + 1) * 8] : argument 0 = receiver
-  // -----------------------------------
   Label miss;
 
-  GenerateNameCheck(name, &miss);
-
-  StackArgumentsAccessor args(rsp, arguments());
-  __ movq(rdx, args.GetReceiverOperand());
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(rdx, &miss);
-
-  // Do the right check and compute the holder register.
-  Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx,
-                                 holder, rbx, rax, rdi, name, &miss);
+  Register reg = HandlerFrontendHeader(
+      object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
                            index.translate(holder), Representation::Tagged());
@@ -1627,12 +1592,7 @@
   __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
   __ j(not_equal, &miss);
 
-  // Patch the receiver on the stack with the global proxy if
-  // necessary.
-  if (object->IsGlobalObject()) {
-    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
-    __ movq(args.GetReceiverOperand(), rdx);
-  }
+  PatchGlobalProxy(object);
 
   // Invoke the function.
   CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
@@ -1641,9 +1601,7 @@
   __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
                     NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::FAST, name);
@@ -1659,28 +1617,16 @@
     Code::StubType type) {
   Label miss;
 
-  // Check that function is still array
-  const int argc = arguments().immediate();
-  StackArgumentsAccessor args(rsp, argc);
-  GenerateNameCheck(name, &miss);
-
-  if (cell.is_null()) {
-    __ movq(rdx, args.GetReceiverOperand());
-
-    // Check that the receiver isn't a smi.
-    __ JumpIfSmi(rdx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                    rbx, rax, rdi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
   Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
   site->SetElementsKind(GetInitialFastElementsKind());
   Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
+  const int argc = arguments().immediate();
   __ movq(rax, Immediate(argc));
   __ Move(rbx, site_feedback_cell);
   __ Move(rdi, function);
@@ -1688,8 +1634,7 @@
   ArrayConstructorStub stub(isolate());
   __ TailCallStub(&stub);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1719,18 +1664,11 @@
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
+
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   const int argc = arguments().immediate();
   StackArgumentsAccessor args(rsp, argc);
-  __ movq(rdx, args.GetReceiverOperand());
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(rdx, &miss);
-
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                  rbx, rax, rdi, name, &miss);
-
   if (argc == 0) {
     // Noop, return the length.
     __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
@@ -1943,8 +1881,7 @@
                                  1);
   }
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -1958,14 +1895,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If object is not an array or is observed, bail out to regular call.
   if (!object->IsJSArray() ||
       !cell.is_null() ||
@@ -1974,17 +1903,8 @@
   }
 
   Label miss, return_undefined, call_builtin;
-  GenerateNameCheck(name, &miss);
 
-  const int argc = arguments().immediate();
-  StackArgumentsAccessor args(rsp, argc);
-  __ movq(rdx, args.GetReceiverOperand());
-
-  // Check that the receiver isn't a smi.
-  __ JumpIfSmi(rdx, &miss);
-
-  CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                  rbx, rax, rdi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
 
   // Get the elements array of the object.
   __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
@@ -2017,6 +1937,7 @@
                        rcx, times_pointer_size,
                        FixedArray::kHeaderSize),
           r9);
+  const int argc = arguments().immediate();
   __ ret((argc + 1) * kPointerSize);
 
   __ bind(&return_undefined);
@@ -2029,8 +1950,7 @@
       argc + 1,
       1);
 
-  __ bind(&miss);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2044,20 +1964,9 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : function name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
-  const int argc = arguments().immediate();
-  StackArgumentsAccessor args(rsp, argc);
-
   Label miss;
   Label name_miss;
   Label index_out_of_range;
@@ -2067,22 +1976,15 @@
        DEFAULT_STRING_STUB)) {
     index_out_of_range_label = &miss;
   }
-  GenerateNameCheck(name, &name_miss);
 
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            rax,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      rax, holder, rbx, rdx, rdi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = rbx;
   Register index = rdi;
   Register result = rax;
+  const int argc = arguments().immediate();
+  StackArgumentsAccessor args(rsp, argc);
+
   __ movq(receiver, args.GetReceiverOperand());
   if (argc > 0) {
     __ movq(index, args.GetArgumentOperand(1));
@@ -2127,14 +2029,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : function name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If object is not a string, bail out to regular call.
   if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
 
@@ -2150,18 +2044,8 @@
        DEFAULT_STRING_STUB)) {
     index_out_of_range_label = &miss;
   }
-  GenerateNameCheck(name, &name_miss);
 
-  // Check that the maps starting from the prototype haven't changed.
-  GenerateDirectLoadGlobalFunctionPrototype(masm(),
-                                            Context::STRING_FUNCTION_INDEX,
-                                            rax,
-                                            &miss);
-  ASSERT(!object.is_identical_to(holder));
-  Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-  CheckPrototypes(
-      IC::CurrentTypeOf(prototype, isolate()),
-      rax, holder, rbx, rdx, rdi, name, &miss);
+  HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
 
   Register receiver = rax;
   Register index = rdi;
@@ -2211,14 +2095,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : function name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
   const int argc = arguments().immediate();
@@ -2226,17 +2102,10 @@
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ movq(rdx, args.GetReceiverOperand());
-    __ JumpIfSmi(rdx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                    rbx, rax, rdi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2268,9 +2137,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), call_kind);
 
-  __ bind(&miss);
-  // rcx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2284,13 +2151,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 4] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 4] : receiver
-  // -----------------------------------
   const int argc = arguments().immediate();
   StackArgumentsAccessor args(rsp, argc);
 
@@ -2300,21 +2160,11 @@
     return Handle<Code>::null();
   }
 
-  Label miss;
-  GenerateNameCheck(name, &miss);
+  Label miss, slow;
 
-  if (cell.is_null()) {
-    __ movq(rdx, args.GetReceiverOperand());
-
-    STATIC_ASSERT(kSmiTag == 0);
-    __ JumpIfSmi(rdx, &miss);
-
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                    rbx, rax, rdi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
 
@@ -2327,7 +2177,6 @@
   __ JumpIfSmi(rax, &smi);
 
   // Check if the argument is a heap number and load its value into xmm0.
-  Label slow;
   __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
   __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
 
@@ -2396,9 +2245,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
 
-  __ bind(&miss);
-  // rcx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2412,14 +2259,6 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // ----------- S t a t e -------------
-  //  -- rcx                 : function name
-  //  -- rsp[0]              : return address
-  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
-  //  -- ...
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-
   // If the object is not a JSObject or we got an unexpected number of
   // arguments, bail out to the regular call.
   const int argc = arguments().immediate();
@@ -2427,19 +2266,13 @@
   if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
 
   Label miss;
-  GenerateNameCheck(name, &miss);
 
-  if (cell.is_null()) {
-    __ movq(rdx, args.GetReceiverOperand());
-    __ JumpIfSmi(rdx, &miss);
-    CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                    rbx, rax, rdi, name, &miss);
-  } else {
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
+  if (!cell.is_null()) {
     ASSERT(cell->value() == *function);
-    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
-                                &miss);
     GenerateLoadFunctionFromCell(cell, function, &miss);
   }
+
   // Load the (only) argument into rax.
   __ movq(rax, args.GetArgumentOperand(1));
 
@@ -2501,9 +2334,7 @@
   __ InvokeFunction(function, expected, arguments(),
                     JUMP_FUNCTION, NullCallWrapper(), call_kind);
 
-  __ bind(&miss);
-  // rcx: function name.
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(type, name);
@@ -2578,28 +2409,30 @@
 }
 
 
-void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
-                                              Handle<JSObject> holder,
-                                              Handle<Name> name,
-                                              CheckType check) {
-  // ----------- S t a t e -------------
-  // rcx                 : function name
-  // rsp[0]              : return address
-  // rsp[8]              : argument argc
-  // rsp[16]             : argument argc - 1
-  // ...
-  // rsp[argc * 8]       : argument 1
-  // rsp[(argc + 1) * 8] : argument 0 = receiver
-  // -----------------------------------
-  Label miss;
-  GenerateNameCheck(name, &miss);
+void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) {
+  if (object->IsGlobalObject()) {
+    StackArgumentsAccessor args(rsp, arguments());
+    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
+    __ movq(args.GetReceiverOperand(), rdx);
+  }
+}
+
+
+Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
+                                                 Handle<JSObject> holder,
+                                                 Handle<Name> name,
+                                                 CheckType check,
+                                                 Label* miss) {
+  GenerateNameCheck(name, miss);
+
+  Register reg = rdx;
 
   StackArgumentsAccessor args(rsp, arguments());
-  __ movq(rdx, args.GetReceiverOperand());
+  __ movq(reg, args.GetReceiverOperand());
 
   // Check that the receiver isn't a smi.
   if (check != NUMBER_CHECK) {
-    __ JumpIfSmi(rdx, &miss);
+    __ JumpIfSmi(reg, miss);
   }
 
   // Make sure that it's okay not to patch the on stack receiver
@@ -2612,80 +2445,57 @@
       __ IncrementCounter(counters->call_const(), 1);
 
       // Check that the maps haven't changed.
-      CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
-                      rbx, rax, rdi, name, &miss);
-
-      // Patch the receiver on the stack with the global proxy if
-      // necessary.
-      if (object->IsGlobalObject()) {
-        __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
-        __ movq(args.GetReceiverOperand(), rdx);
-      }
+      reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
+                            rbx, rax, rdi, name, miss);
       break;
 
     case STRING_CHECK: {
       // Check that the object is a string.
-      __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
-      __ j(above_equal, &miss);
+      __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, rax);
+      __ j(above_equal, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          rax, holder, rbx, rdx, rdi, name, &miss);
+          masm(), Context::STRING_FUNCTION_INDEX, rax, miss);
       break;
     }
     case SYMBOL_CHECK: {
       // Check that the object is a symbol.
-      __ CmpObjectType(rdx, SYMBOL_TYPE, rax);
-      __ j(not_equal, &miss);
+      __ CmpObjectType(reg, SYMBOL_TYPE, rax);
+      __ j(not_equal, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          rax, holder, rbx, rdx, rdi, name, &miss);
+          masm(), Context::SYMBOL_FUNCTION_INDEX, rax, miss);
       break;
     }
     case NUMBER_CHECK: {
       Label fast;
       // Check that the object is a smi or a heap number.
-      __ JumpIfSmi(rdx, &fast);
-      __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax);
-      __ j(not_equal, &miss);
+      __ JumpIfSmi(reg, &fast);
+      __ CmpObjectType(reg, HEAP_NUMBER_TYPE, rax);
+      __ j(not_equal, miss);
       __ bind(&fast);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          rax, holder, rbx, rdx, rdi, name, &miss);
+          masm(), Context::NUMBER_FUNCTION_INDEX, rax, miss);
       break;
     }
     case BOOLEAN_CHECK: {
-      GenerateBooleanCheck(rdx, &miss);
+      GenerateBooleanCheck(reg, miss);
       // Check that the maps starting from the prototype haven't changed.
       GenerateDirectLoadGlobalFunctionPrototype(
-          masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
-      Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
-      CheckPrototypes(
-          IC::CurrentTypeOf(prototype, isolate()),
-          rax, holder, rbx, rdx, rdi, name, &miss);
+          masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, miss);
       break;
     }
   }
 
-  Label success;
-  __ jmp(&success);
+  if (check != RECEIVER_MAP_CHECK) {
+    Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
+    reg = CheckPrototypes(
+        IC::CurrentTypeOf(prototype, isolate()),
+        rax, holder, rbx, rdx, rdi, name, miss);
+  }
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  GenerateMissBranch();
-
-  __ bind(&success);
+  return reg;
 }
 
 
@@ -2714,8 +2524,11 @@
     if (!code.is_null()) return code;
   }
 
-  CompileHandlerFrontend(object, holder, name, check);
+  Label miss;
+  HandlerFrontendHeader(object, holder, name, check, &miss);
+  PatchGlobalProxy(object);
   CompileHandlerBackend(function);
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(function);
@@ -2725,19 +2538,9 @@
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
                                                       Handle<Name> name) {
-  // ----------- S t a t e -------------
-  // rcx                 : function name
-  // rsp[0]              : return address
-  // rsp[8]              : argument argc
-  // rsp[16]             : argument argc - 1
-  // ...
-  // rsp[argc * 8]       : argument 1
-  // rsp[(argc + 1) * 8] : argument 0 = receiver
-  // -----------------------------------
   Label miss;
   GenerateNameCheck(name, &miss);
 
-
   LookupResult lookup(isolate());
   LookupPostInterceptor(holder, name, &lookup);
 
@@ -2787,16 +2590,6 @@
     Handle<PropertyCell> cell,
     Handle<JSFunction> function,
     Handle<Name> name) {
-  // ----------- S t a t e -------------
-  // rcx                 : function name
-  // rsp[0]              : return address
-  // rsp[8]              : argument argc
-  // rsp[16]             : argument argc - 1
-  // ...
-  // rsp[argc * 8]       : argument 1
-  // rsp[(argc + 1) * 8] : argument 0 = receiver
-  // -----------------------------------
-
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(
         object, holder, cell, function, Handle<String>::cast(name),
@@ -2806,17 +2599,9 @@
   }
 
   Label miss;
-  GenerateNameCheck(name, &miss);
-
-  StackArgumentsAccessor args(rsp, arguments());
-  GenerateGlobalReceiverCheck(object, holder, name, &miss);
+  HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
   GenerateLoadFunctionFromCell(cell, function, &miss);
-
-  // Patch the receiver on the stack with the global proxy.
-  if (object->IsGlobalObject()) {
-    __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
-    __ movq(args.GetReceiverOperand(), rdx);
-  }
+  PatchGlobalProxy(object);
 
   // Set up the context (function already in rdi).
   __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
@@ -2835,10 +2620,7 @@
   __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION,
                 NullCallWrapper(), call_kind);
 
-  // Handle call cache miss.
-  __ bind(&miss);
-  __ IncrementCounter(counters->call_global_inline_miss(), 1);
-  GenerateMissBranch();
+  HandlerFrontendFooter(&miss);
 
   // Return the generated code.
   return GetCode(Code::NORMAL, name);
@@ -2942,13 +2724,12 @@
   __ push(receiver());
   __ push(this->name());
   __ push(value());
-  __ Push(Smi::FromInt(strict_mode()));
   __ PushReturnAddressFrom(scratch1());
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
-  __ TailCallExternalReference(store_ic_property, 4, 1);
+  __ TailCallExternalReference(store_ic_property, 3, 1);
 
   // Return the generated code.
   return GetCode(kind(), Code::FAST, name);
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index e496673..fed108d 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -2066,26 +2066,6 @@
     &kHeapProfilerExtension);
 
 
-// This is an example of using checking of JS allocations tracking in a test.
-TEST(HeapObjectsTracker) {
-  const char* extensions[] = { HeapProfilerExtension::kName };
-  v8::ExtensionConfiguration config(1, extensions);
-  LocalContext env(&config);
-  v8::HandleScope scope(env->GetIsolate());
-  HeapObjectsTracker tracker;
-  CompileRun("var a = 1.2");
-  CompileRun("var a = 1.2; var b = 1.0; var c = 1.0;");
-  CompileRun(
-    "var a = [];\n"
-    "for (var i = 0; i < 5; ++i)\n"
-    "    a[i] = i;\n"
-    "findUntrackedObjects();\n"
-    "for (var i = 0; i < 3; ++i)\n"
-    "    a.shift();\n"
-    "findUntrackedObjects();\n");
-}
-
-
 static const v8::HeapGraphNode* GetNodeByPath(const v8::HeapSnapshot* snapshot,
                                               const char* path[],
                                               int depth) {
@@ -2207,6 +2187,39 @@
 }
 
 
+TEST(ArrayGrowLeftTrim) {
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+  heap_profiler->StartRecordingHeapAllocations();
+
+  CompileRun(
+    "var a = [];\n"
+    "for (var i = 0; i < 5; ++i)\n"
+    "    a[i] = i;\n"
+    "for (var i = 0; i < 3; ++i)\n"
+    "    a.shift();\n");
+
+  const char* names[] = { "(anonymous function)" };
+  const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(
+      v8::String::NewFromUtf8(env->GetIsolate(), "Test1"));
+  i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection();
+  AllocationTracker* tracker = collection->allocation_tracker();
+  CHECK_NE(NULL, tracker);
+  // Resolve all function locations.
+  tracker->PrepareForSerialization();
+  // Print for better diagnostics in case of failure.
+  tracker->trace_tree()->Print(tracker);
+
+  AllocationTraceNode* node =
+      FindNode(tracker, Vector<const char*>(names, ARRAY_SIZE(names)));
+  CHECK_NE(NULL, node);
+  CHECK_GE(node->allocation_count(), 2);
+  CHECK_GE(node->allocation_size(), 4 * 5);
+  heap_profiler->StopRecordingHeapAllocations();
+}
+
+
 TEST(TrackHeapAllocations) {
   v8::HandleScope scope(v8::Isolate::GetCurrent());
   LocalContext env;
diff --git a/test/mjsunit/compiler/load-elimination-params.js b/test/mjsunit/compiler/load-elimination-params.js
new file mode 100644
index 0000000..13a4a85
--- /dev/null
+++ b/test/mjsunit/compiler/load-elimination-params.js
@@ -0,0 +1,71 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --load-elimination
+
+// Test local load elimination of redundant loads and stores.
+
+function B(x, y) {
+  this.x = x;
+  this.y = y;
+  return this;
+}
+
+function test_params1(a, b) {
+  var i = a.x;
+  var j = a.x;
+  var k = b.x;
+  var l = b.x;
+  return i + j + k + l;
+}
+
+assertEquals(14, test_params1(new B(3, 4), new B(4, 5)));
+assertEquals(110, test_params1(new B(11, 7), new B(44, 8)));
+
+%OptimizeFunctionOnNextCall(test_params1);
+
+assertEquals(6, test_params1(new B(1, 7), new B(2, 8)));
+
+function test_params2(a, b) {
+  var o = new B(a + 1, b);
+  o.x = a;
+  var i = o.x;
+  o.x = a;
+  var j = o.x;
+  o.x = b;
+  var k = o.x;
+  o.x = b;
+  var l = o.x;
+  return i + j + k + l;
+}
+
+assertEquals(14, test_params2(3, 4));
+assertEquals(110, test_params2(11, 44));
+
+%OptimizeFunctionOnNextCall(test_params2);
+
+assertEquals(6, test_params2(1, 2));
diff --git a/test/mjsunit/regress/regress-324028.js b/test/mjsunit/regress/regress-324028.js
new file mode 100644
index 0000000..7fe0fcd
--- /dev/null
+++ b/test/mjsunit/regress/regress-324028.js
@@ -0,0 +1,38 @@
+// 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.
+
+var badObj = { length : 1e40 };
+
+assertThrows(function() { new Uint8Array(badObj); }, RangeError);
+assertThrows(function() { new Uint8ClampedArray(badObj); }, RangeError);
+assertThrows(function() { new Int8Array(badObj); }, RangeError);
+assertThrows(function() { new Uint16Array(badObj); }, RangeError);
+assertThrows(function() { new Int16Array(badObj); }, RangeError);
+assertThrows(function() { new Uint32Array(badObj); }, RangeError);
+assertThrows(function() { new Int32Array(badObj); }, RangeError);
+assertThrows(function() { new Float32Array(badObj); }, RangeError);
+assertThrows(function() { new Float64Array(badObj); }, RangeError);
diff --git a/test/mjsunit/regress/regress-crbug-323942.js b/test/mjsunit/regress/regress-crbug-323942.js
new file mode 100644
index 0000000..15af494
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-323942.js
@@ -0,0 +1,57 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+"use strict";
+
+// Function is defined on the prototype chain.
+var holder = { f: function() { return 42; } };
+var receiver = { };
+receiver.__proto__ = { };
+receiver.__proto__.__proto__ = holder;
+
+// Inline two levels.
+function h(o) { return o.f.apply(this, arguments); }
+function g(o) { return h(o); }
+
+// Collect type information for apply call.
+assertEquals(42, g(receiver));
+assertEquals(42, g(receiver));
+
+// Sneakily remove the function from the prototype chain.
+// The receiver map does not change.
+receiver.__proto__.__proto__ = {};
+
+// Lookup of o.f during graph creation fails.
+%OptimizeFunctionOnNextCall(g);
+
+assertThrows(function() { g(receiver); });
+
+// Put function back.
+receiver.__proto__.__proto__ = holder;
+assertEquals(42, g(receiver));