Version 3.28.21 (based on bleeding_edge revision r22338)

Make `let` usable as an identifier in ES6 sloppy mode (issue 2198).

Support ES6 Map and Set in heap profiler (issue 3368).

Performance and stability improvements on all platforms.

git-svn-id: https://v8.googlecode.com/svn/trunk@22341 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 6d6e18c..5be394c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2014-07-11: Version 3.28.21
+
+        Make `let` usable as an identifier in ES6 sloppy mode (issue 2198).
+
+        Support ES6 Map and Set in heap profiler (issue 3368).
+
+        Performance and stability improvements on all platforms.
+
+
 2014-07-10: Version 3.28.20
 
         Remove deprecate counter/histogram methods.
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index b55acca..4b52aeb 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -176,5 +176,6 @@
       'v8_linux_layout_dbg': set(['defaulttests']),
       'v8_mac_rel': set(['defaulttests']),
       'v8_win_rel': set(['defaulttests']),
+      'v8_win64_rel': set(['defaulttests']),
     },
   }
diff --git a/include/v8.h b/include/v8.h
index 11bf598..82d5784 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1087,6 +1087,12 @@
 
   /**
    * Compiles the specified script (context-independent).
+   * Cached data as part of the source object can be optionally produced to be
+   * consumed later to speed up compilation of identical source scripts.
+   *
+   * Note that when producing cached data, the source must point to NULL for
+   * cached data. When consuming cached data, the cached data must have been
+   * produced by the same version of V8.
    *
    * \param source Script source code.
    * \return Compiled script object (context independent; for running it must be
diff --git a/src/api.cc b/src/api.cc
index d01d826..106c1fd 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1699,43 +1699,19 @@
     Isolate* v8_isolate,
     Source* source,
     CompileOptions options) {
-  i::ScriptData* script_data_impl = NULL;
+  i::ScriptData* script_data = NULL;
   i::CachedDataMode cached_data_mode = i::NO_CACHED_DATA;
   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
   ON_BAILOUT(isolate, "v8::ScriptCompiler::CompileUnbound()",
              return Local<UnboundScript>());
   if (options & kProduceDataToCache) {
     cached_data_mode = i::PRODUCE_CACHED_DATA;
-    ASSERT(source->cached_data == NULL);
-    if (source->cached_data) {
-      // Asked to produce cached data even though there is some already -> not
-      // good. Fail the compilation.
-      EXCEPTION_PREAMBLE(isolate);
-      i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(
-          "invalid_cached_data", isolate->factory()->NewJSArray(0));
-      isolate->Throw(*result);
-      isolate->ReportPendingMessages();
-      has_pending_exception = true;
-      EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
-    }
+    CHECK(source->cached_data == NULL);
   } else if (source->cached_data) {
     cached_data_mode = i::CONSUME_CACHED_DATA;
-    // ScriptData takes care of aligning, in case the data is not aligned
-    // correctly.
-    script_data_impl = i::ScriptData::New(
-        reinterpret_cast<const char*>(source->cached_data->data),
-        source->cached_data->length);
-    // If the cached data is not valid, fail the compilation.
-    if (script_data_impl == NULL || !script_data_impl->SanityCheck()) {
-      EXCEPTION_PREAMBLE(isolate);
-      i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(
-          "invalid_cached_data", isolate->factory()->NewJSArray(0));
-      isolate->Throw(*result);
-      isolate->ReportPendingMessages();
-      delete script_data_impl;
-      has_pending_exception = true;
-      EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
-    }
+    // ScriptData takes care of pointer-aligning the data.
+    script_data = new i::ScriptData(source->cached_data->data,
+                                    source->cached_data->length);
   }
 
   i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string));
@@ -1763,36 +1739,28 @@
           source->resource_is_shared_cross_origin == v8::True(v8_isolate);
     }
     EXCEPTION_PREAMBLE(isolate);
-    i::Handle<i::SharedFunctionInfo> result =
-        i::Compiler::CompileScript(str,
-                                   name_obj,
-                                   line_offset,
-                                   column_offset,
-                                   is_shared_cross_origin,
-                                   isolate->global_context(),
-                                   NULL,
-                                   &script_data_impl,
-                                   cached_data_mode,
-                                   i::NOT_NATIVES_CODE);
+    i::Handle<i::SharedFunctionInfo> result = i::Compiler::CompileScript(
+        str, name_obj, line_offset, column_offset, is_shared_cross_origin,
+        isolate->global_context(), NULL, &script_data, cached_data_mode,
+        i::NOT_NATIVES_CODE);
     has_pending_exception = result.is_null();
     if (has_pending_exception && cached_data_mode == i::CONSUME_CACHED_DATA) {
       // This case won't happen during normal operation; we have compiled
       // successfully and produced cached data, and but the second compilation
       // of the same source code fails.
-      delete script_data_impl;
-      script_data_impl = NULL;
+      delete script_data;
+      script_data = NULL;
     }
     EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
     raw_result = *result;
-    if ((options & kProduceDataToCache) && script_data_impl != NULL) {
+    if ((options & kProduceDataToCache) && script_data != NULL) {
       // script_data_impl now contains the data that was generated. source will
       // take the ownership.
       source->cached_data = new CachedData(
-          reinterpret_cast<const uint8_t*>(script_data_impl->Data()),
-          script_data_impl->Length(), CachedData::BufferOwned);
-      script_data_impl->owns_store_ = false;
+          script_data->data(), script_data->length(), CachedData::BufferOwned);
+      script_data->ReleaseDataOwnership();
     }
-    delete script_data_impl;
+    delete script_data;
   }
   i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
   return ToApiHandle<UnboundScript>(result);
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 526bc55..5e0e69e 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -87,15 +87,6 @@
 }
 
 
-void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { r2, r1, r0 };
-  descriptor->Initialize(
-      ARRAY_SIZE(registers), registers,
-      FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
-}
-
-
 void TransitionElementsKindStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { r0, r1 };
@@ -230,14 +221,6 @@
 }
 
 
-void StoreGlobalStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { r1, r2, r0 };
-  descriptor->Initialize(ARRAY_SIZE(registers), registers,
-                         FUNCTION_ADDR(StoreIC_MissFromStubFailure));
-}
-
-
 void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { r0, r3, r1, r2 };
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index 8526dd0..310ddb5 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -184,15 +184,11 @@
 
 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
   // Calling convention for IC store (from ic-arm.cc).
-  // ----------- S t a t e -------------
-  //  -- r0    : value
-  //  -- r1    : receiver
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
-  // Registers r0, r1, and r2 contain objects that need to be pushed on the
-  // expression stack of the fake JS frame.
-  Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit(), 0);
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  Register value = StoreIC::ValueRegister();
+  Generate_DebugBreakCallHelper(
+      masm, receiver.bit() | name.bit() | value.bit(), 0);
 }
 
 
@@ -203,12 +199,12 @@
 
 
 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- r0     : value
-  //  -- r1     : key
-  //  -- r2     : receiver
-  //  -- lr     : return address
-  Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit(), 0);
+  // Calling convention for IC keyed store call (from ic-arm.cc).
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  Register value = KeyedStoreIC::ValueRegister();
+  Generate_DebugBreakCallHelper(
+      masm, receiver.bit() | name.bit() | value.bit(), 0);
 }
 
 
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 4255d66..bb9fe95 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1693,8 +1693,9 @@
         if (key->value()->IsInternalizedString()) {
           if (property->emit_store()) {
             VisitForAccumulatorValue(value);
-            __ mov(r2, Operand(key->value()));
-            __ ldr(r1, MemOperand(sp));
+            ASSERT(StoreIC::ValueRegister().is(r0));
+            __ mov(StoreIC::NameRegister(), Operand(key->value()));
+            __ ldr(StoreIC::ReceiverRegister(), MemOperand(sp));
             CallStoreIC(key->LiteralFeedbackId());
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -2420,9 +2421,10 @@
     case NAMED_PROPERTY: {
       __ push(r0);  // Preserve value.
       VisitForAccumulatorValue(prop->obj());
-      __ mov(r1, r0);
-      __ pop(r0);  // Restore value.
-      __ mov(r2, Operand(prop->key()->AsLiteral()->value()));
+      __ Move(StoreIC::ReceiverRegister(), r0);
+      __ pop(StoreIC::ValueRegister());  // Restore value.
+      __ mov(StoreIC::NameRegister(),
+             Operand(prop->key()->AsLiteral()->value()));
       CallStoreIC();
       break;
     }
@@ -2430,8 +2432,8 @@
       __ push(r0);  // Preserve value.
       VisitForStackValue(prop->obj());
       VisitForAccumulatorValue(prop->key());
-      __ mov(r1, r0);
-      __ Pop(r0, r2);  // r0 = restored value.
+      __ Move(KeyedStoreIC::NameRegister(), r0);
+      __ Pop(KeyedStoreIC::ValueRegister(), KeyedStoreIC::ReceiverRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
@@ -2469,8 +2471,8 @@
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
   if (var->IsUnallocated()) {
     // Global var, const, or let.
-    __ mov(r2, Operand(var->name()));
-    __ ldr(r1, GlobalObjectOperand());
+    __ mov(StoreIC::NameRegister(), Operand(var->name()));
+    __ ldr(StoreIC::ReceiverRegister(), GlobalObjectOperand());
     CallStoreIC();
 
   } else if (op == Token::INIT_CONST_LEGACY) {
@@ -2540,9 +2542,8 @@
 
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  __ mov(r2, Operand(prop->key()->AsLiteral()->value()));
-  __ pop(r1);
-
+  __ mov(StoreIC::NameRegister(), Operand(prop->key()->AsLiteral()->value()));
+  __ pop(StoreIC::ReceiverRegister());
   CallStoreIC(expr->AssignmentFeedbackId());
 
   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
@@ -2555,7 +2556,8 @@
 
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  __ Pop(r2, r1);  // r1 = key.
+  __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister());
+  ASSERT(KeyedStoreIC::ValueRegister().is(r0));
 
   Handle<Code> ic = strict_mode() == SLOPPY
       ? isolate()->builtins()->KeyedStoreIC_Initialize()
@@ -4354,8 +4356,9 @@
       }
       break;
     case NAMED_PROPERTY: {
-      __ mov(r2, Operand(prop->key()->AsLiteral()->value()));
-      __ pop(r1);
+      __ mov(StoreIC::NameRegister(),
+             Operand(prop->key()->AsLiteral()->value()));
+      __ pop(StoreIC::ReceiverRegister());
       CallStoreIC(expr->CountStoreFeedbackId());
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -4368,7 +4371,7 @@
       break;
     }
     case KEYED_PROPERTY: {
-      __ Pop(r2, r1);  // r1 = key. r2 = receiver.
+      __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index fc32a48..c49b161 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -497,27 +497,28 @@
 
 
 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- r0     : value
-  //  -- r1     : key
-  //  -- r2     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
+  Register receiver = ReceiverRegister();
+  Register key = NameRegister();
+  Register value = ValueRegister();
+  ASSERT(receiver.is(r2));
+  ASSERT(key.is(r1));
+  ASSERT(value.is(r0));
+
   Label slow, notin;
-  MemOperand mapped_location =
-      GenerateMappedArgumentsLookup(masm, r2, r1, r3, r4, r5, &notin, &slow);
-  __ str(r0, mapped_location);
+  MemOperand mapped_location = GenerateMappedArgumentsLookup(
+      masm, receiver, key, r3, r4, r5, &notin, &slow);
+  __ str(value, mapped_location);
   __ add(r6, r3, r5);
-  __ mov(r9, r0);
+  __ mov(r9, value);
   __ RecordWrite(r3, r6, r9, kLRHasNotBeenSaved, kDontSaveFPRegs);
   __ Ret();
   __ bind(&notin);
   // The unmapped lookup expects that the parameter map is in r3.
   MemOperand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, r1, r3, r4, &slow);
-  __ str(r0, unmapped_location);
+      GenerateUnmappedArgumentsLookup(masm, key, r3, r4, &slow);
+  __ str(value, unmapped_location);
   __ add(r6, r3, r4);
-  __ mov(r9, r0);
+  __ mov(r9, value);
   __ RecordWrite(r3, r6, r9, kLRHasNotBeenSaved, kDontSaveFPRegs);
   __ Ret();
   __ bind(&slow);
@@ -546,6 +547,16 @@
 const Register LoadIC::NameRegister() { return r2; }
 
 
+const Register StoreIC::ReceiverRegister() { return r1; }
+const Register StoreIC::NameRegister() { return r2; }
+const Register StoreIC::ValueRegister() { return r0; }
+
+
+const Register KeyedStoreIC::ReceiverRegister() { return r2; }
+const Register KeyedStoreIC::NameRegister() { return r1; }
+const Register KeyedStoreIC::ValueRegister() { return r0; }
+
+
 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   // The return address is in lr.
 
@@ -792,15 +803,8 @@
 
 
 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- r0     : value
-  //  -- r1     : key
-  //  -- r2     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(r2, r1, r0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   ExternalReference ref =
       ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
@@ -809,15 +813,8 @@
 
 
 void StoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- r0     : value
-  //  -- r2     : key
-  //  -- r1     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(r1, r2, r0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // The slow case calls into the runtime to complete the store without causing
   // an IC miss that would otherwise cause a transition to the generic stub.
@@ -828,15 +825,8 @@
 
 
 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- r0     : value
-  //  -- r1     : key
-  //  -- r2     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(r2, r1, r0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // The slow case calls into the runtime to complete the store without causing
   // an IC miss that would otherwise cause a transition to the generic stub.
@@ -848,15 +838,8 @@
 
 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                               StrictMode strict_mode) {
-  // ---------- S t a t e --------------
-  //  -- r0     : value
-  //  -- r1     : key
-  //  -- r2     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(r2, r1, r0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   __ mov(r0, Operand(Smi::FromInt(strict_mode)));   // Strict mode.
   __ Push(r0);
@@ -1042,9 +1025,12 @@
   Label array, extra, check_if_double_array;
 
   // Register usage.
-  Register value = r0;
-  Register key = r1;
-  Register receiver = r2;
+  Register value = ValueRegister();
+  Register key = NameRegister();
+  Register receiver = ReceiverRegister();
+  ASSERT(receiver.is(r2));
+  ASSERT(key.is(r1));
+  ASSERT(value.is(r0));
   Register receiver_map = r3;
   Register elements_map = r6;
   Register elements = r9;  // Elements array of the receiver.
@@ -1130,18 +1116,17 @@
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- r0    : value
-  //  -- r1    : receiver
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  ASSERT(receiver.is(r1));
+  ASSERT(name.is(r2));
+  ASSERT(ValueRegister().is(r0));
 
   // Get the receiver from the stack and probe the stub cache.
   Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC);
 
   masm->isolate()->stub_cache()->GenerateProbe(
-      masm, flags, r1, r2, r3, r4, r5, r6);
+      masm, flags, receiver, name, r3, r4, r5, r6);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -1149,14 +1134,7 @@
 
 
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- r0    : value
-  //  -- r1    : receiver
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
-
-  __ Push(r1, r2, r0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // Perform tail call to the entry.
   ExternalReference ref =
@@ -1166,17 +1144,17 @@
 
 
 void StoreIC::GenerateNormal(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- r0    : value
-  //  -- r1    : receiver
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
   Label miss;
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  Register value = ValueRegister();
+  ASSERT(receiver.is(r1));
+  ASSERT(name.is(r2));
+  ASSERT(value.is(r0));
 
-  GenerateNameDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, receiver, r3, r4, r5, &miss);
 
-  GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5);
+  GenerateDictionaryStore(masm, &miss, r3, name, value, r4, r5);
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->store_normal_hit(),
                       1, r4, r5);
@@ -1190,14 +1168,7 @@
 
 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                          StrictMode strict_mode) {
-  // ----------- S t a t e -------------
-  //  -- r0    : value
-  //  -- r1    : receiver
-  //  -- r2    : name
-  //  -- lr    : return address
-  // -----------------------------------
-
-  __ Push(r1, r2, r0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   __ mov(r0, Operand(Smi::FromInt(strict_mode)));
   __ Push(r0);
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 21fd783..90ff023 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -2255,9 +2255,9 @@
 
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* obj = UseFixed(instr->object(), r2);
-  LOperand* key = UseFixed(instr->key(), r1);
-  LOperand* val = UseFixed(instr->value(), r0);
+  LOperand* obj = UseFixed(instr->object(), KeyedStoreIC::ReceiverRegister());
+  LOperand* key = UseFixed(instr->key(), KeyedStoreIC::NameRegister());
+  LOperand* val = UseFixed(instr->value(), KeyedStoreIC::ValueRegister());
 
   ASSERT(instr->object()->representation().IsTagged());
   ASSERT(instr->key()->representation().IsTagged());
@@ -2331,8 +2331,8 @@
 
 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* obj = UseFixed(instr->object(), r1);
-  LOperand* val = UseFixed(instr->value(), r0);
+  LOperand* obj = UseFixed(instr->object(), StoreIC::ReceiverRegister());
+  LOperand* val = UseFixed(instr->value(), StoreIC::ValueRegister());
 
   LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val);
   return MarkAsCall(result, instr);
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 34a23e1..13dd7b7 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -4191,11 +4191,10 @@
 
 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->object()).is(r1));
-  ASSERT(ToRegister(instr->value()).is(r0));
+  ASSERT(ToRegister(instr->object()).is(StoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->value()).is(StoreIC::ValueRegister()));
 
-  // Name is always in r2.
-  __ mov(r2, Operand(instr->name()));
+  __ mov(StoreIC::NameRegister(), Operand(instr->name()));
   Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
   CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
 }
@@ -4413,9 +4412,9 @@
 
 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->object()).is(r2));
-  ASSERT(ToRegister(instr->key()).is(r1));
-  ASSERT(ToRegister(instr->value()).is(r0));
+  ASSERT(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister()));
+  ASSERT(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister()));
 
   Handle<Code> ic = instr->strict_mode() == STRICT
       ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 1f7c152..98002dc 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -1280,20 +1280,24 @@
 
 
 Register StoreStubCompiler::value() {
-  return r0;
+  return StoreIC::ValueRegister();
 }
 
 
 Register* StoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { r1, r2, r3, r4, r5 };
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  static Register registers[] = { receiver, name, r3, r4, r5 };
   return registers;
 }
 
 
 Register* KeyedStoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { r2, r1, r3, r4, r5 };
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  static Register registers[] = { receiver, name, r3, r4, r5 };
   return registers;
 }
 
diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc
index e24c7bd..5b76f1a 100644
--- a/src/arm64/code-stubs-arm64.cc
+++ b/src/arm64/code-stubs-arm64.cc
@@ -102,18 +102,6 @@
 }
 
 
-void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  // x2: receiver
-  // x1: key
-  // x0: value
-  Register registers[] = { x2, x1, x0 };
-  descriptor->Initialize(
-      ARRAY_SIZE(registers), registers,
-      FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
-}
-
-
 void TransitionElementsKindStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   // x0: value (js_array)
@@ -250,17 +238,6 @@
 }
 
 
-void StoreGlobalStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  // x1: receiver
-  // x2: key (unused)
-  // x0: value
-  Register registers[] = { x1, x2, x0 };
-  descriptor->Initialize(ARRAY_SIZE(registers), registers,
-                         FUNCTION_ADDR(StoreIC_MissFromStubFailure));
-}
-
-
 void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   // x0: value
diff --git a/src/arm64/debug-arm64.cc b/src/arm64/debug-arm64.cc
index 1578452..5d88903 100644
--- a/src/arm64/debug-arm64.cc
+++ b/src/arm64/debug-arm64.cc
@@ -243,16 +243,12 @@
 
 
 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
-  // Calling convention for IC store (from ic-arm.cc).
-  // ----------- S t a t e -------------
-  //  -- x0    : value
-  //  -- x1    : receiver
-  //  -- x2    : name
-  //  -- lr    : return address
-  // -----------------------------------
-  // Registers x0, x1, and x2 contain objects that need to be pushed on the
-  // expression stack of the fake JS frame.
-  Generate_DebugBreakCallHelper(masm, x0.Bit() | x1.Bit() | x2.Bit(), 0, x10);
+  // Calling convention for IC store (from ic-arm64.cc).
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  Register value = StoreIC::ValueRegister();
+  Generate_DebugBreakCallHelper(
+      masm, receiver.Bit() | name.Bit() | value.Bit(), 0, x10);
 }
 
 
@@ -263,12 +259,12 @@
 
 
 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- x0     : value
-  //  -- x1     : key
-  //  -- x2     : receiver
-  //  -- lr     : return address
-  Generate_DebugBreakCallHelper(masm, x0.Bit() | x1.Bit() | x2.Bit(), 0, x10);
+  // Calling convention for IC keyed store call (from ic-arm64.cc).
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  Register value = KeyedStoreIC::ValueRegister();
+  Generate_DebugBreakCallHelper(
+      masm, receiver.Bit() | name.Bit() | value.Bit(), 0, x10);
 }
 
 
diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc
index f027dc6..f7103f2 100644
--- a/src/arm64/full-codegen-arm64.cc
+++ b/src/arm64/full-codegen-arm64.cc
@@ -1682,8 +1682,9 @@
         if (key->value()->IsInternalizedString()) {
           if (property->emit_store()) {
             VisitForAccumulatorValue(value);
-            __ Mov(x2, Operand(key->value()));
-            __ Peek(x1, 0);
+            ASSERT(StoreIC::ValueRegister().is(x0));
+            __ Mov(StoreIC::NameRegister(), Operand(key->value()));
+            __ Peek(StoreIC::ReceiverRegister(), 0);
             CallStoreIC(key->LiteralFeedbackId());
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -2104,9 +2105,10 @@
       VisitForAccumulatorValue(prop->obj());
       // TODO(all): We could introduce a VisitForRegValue(reg, expr) to avoid
       // this copy.
-      __ Mov(x1, x0);
-      __ Pop(x0);  // Restore value.
-      __ Mov(x2, Operand(prop->key()->AsLiteral()->value()));
+      __ Mov(StoreIC::ReceiverRegister(), x0);
+      __ Pop(StoreIC::ValueRegister());  // Restore value.
+      __ Mov(StoreIC::NameRegister(),
+             Operand(prop->key()->AsLiteral()->value()));
       CallStoreIC();
       break;
     }
@@ -2114,8 +2116,8 @@
       __ Push(x0);  // Preserve value.
       VisitForStackValue(prop->obj());
       VisitForAccumulatorValue(prop->key());
-      __ Mov(x1, x0);
-      __ Pop(x2, x0);
+      __ Mov(KeyedStoreIC::NameRegister(), x0);
+      __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::ValueRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
@@ -2158,8 +2160,8 @@
   ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment");
   if (var->IsUnallocated()) {
     // Global var, const, or let.
-    __ Mov(x2, Operand(var->name()));
-    __ Ldr(x1, GlobalObjectMemOperand());
+    __ Mov(StoreIC::NameRegister(), Operand(var->name()));
+    __ Ldr(StoreIC::ReceiverRegister(), GlobalObjectMemOperand());
     CallStoreIC();
 
   } else if (op == Token::INIT_CONST_LEGACY) {
@@ -2226,9 +2228,8 @@
 
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  __ Mov(x2, Operand(prop->key()->AsLiteral()->value()));
-  __ Pop(x1);
-
+  __ Mov(StoreIC::NameRegister(), Operand(prop->key()->AsLiteral()->value()));
+  __ Pop(StoreIC::ReceiverRegister());
   CallStoreIC(expr->AssignmentFeedbackId());
 
   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
@@ -2243,7 +2244,8 @@
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
   // TODO(all): Could we pass this in registers rather than on the stack?
-  __ Pop(x1, x2);  // Key and object holding the property.
+  __ Pop(KeyedStoreIC::NameRegister(), KeyedStoreIC::ReceiverRegister());
+  ASSERT(KeyedStoreIC::ValueRegister().is(x0));
 
   Handle<Code> ic = strict_mode() == SLOPPY
       ? isolate()->builtins()->KeyedStoreIC_Initialize()
@@ -4043,8 +4045,9 @@
       }
       break;
     case NAMED_PROPERTY: {
-      __ Mov(x2, Operand(prop->key()->AsLiteral()->value()));
-      __ Pop(x1);
+      __ Mov(StoreIC::NameRegister(),
+             Operand(prop->key()->AsLiteral()->value()));
+      __ Pop(StoreIC::ReceiverRegister());
       CallStoreIC(expr->CountStoreFeedbackId());
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -4057,8 +4060,8 @@
       break;
     }
     case KEYED_PROPERTY: {
-      __ Pop(x1);  // Key.
-      __ Pop(x2);  // Receiver.
+      __ Pop(KeyedStoreIC::NameRegister());
+      __ Pop(KeyedStoreIC::ReceiverRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
diff --git a/src/arm64/ic-arm64.cc b/src/arm64/ic-arm64.cc
index 6e6e8ce..5a2dde5 100644
--- a/src/arm64/ic-arm64.cc
+++ b/src/arm64/ic-arm64.cc
@@ -502,17 +502,14 @@
 
 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
   ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments");
-  // ---------- S t a t e --------------
-  //  -- lr     : return address
-  //  -- x0     : value
-  //  -- x1     : key
-  //  -- x2     : receiver
-  // -----------------------------------
   Label slow, notin;
+  Register value = ValueRegister();
+  Register key = NameRegister();
+  Register receiver = ReceiverRegister();
+  ASSERT(receiver.is(x2));
+  ASSERT(key.is(x1));
+  ASSERT(value.is(x0));
 
-  Register value = x0;
-  Register key = x1;
-  Register receiver = x2;
   Register map = x3;
 
   // These registers are used by GenerateMappedArgumentsLookup to build a
@@ -572,6 +569,16 @@
 const Register LoadIC::NameRegister() { return x2; }
 
 
+const Register StoreIC::ReceiverRegister() { return x1; }
+const Register StoreIC::NameRegister() { return x2; }
+const Register StoreIC::ValueRegister() { return x0; }
+
+
+const Register KeyedStoreIC::ReceiverRegister() { return x2; }
+const Register KeyedStoreIC::NameRegister() { return x1; }
+const Register KeyedStoreIC::ValueRegister() { return x0; }
+
+
 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   // The return address is in lr.
   __ Push(ReceiverRegister(), NameRegister());
@@ -847,15 +854,9 @@
 
 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
   ASM_LOCATION("KeyedStoreIC::GenerateMiss");
-  // ---------- S t a t e --------------
-  //  -- x0     : value
-  //  -- x1     : key
-  //  -- x2     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
 
   // Push receiver, key and value for runtime call.
-  __ Push(x2, x1, x0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   ExternalReference ref =
       ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
@@ -865,15 +866,9 @@
 
 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
   ASM_LOCATION("KeyedStoreIC::GenerateSlow");
-  // ---------- S t a t e --------------
-  //  -- lr     : return address
-  //  -- x0     : value
-  //  -- x1     : key
-  //  -- x2     : receiver
-  // -----------------------------------
 
   // Push receiver, key and value for runtime call.
-  __ Push(x2, x1, x0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // The slow case calls into the runtime to complete the store without causing
   // an IC miss that would otherwise cause a transition to the generic stub.
@@ -886,15 +881,9 @@
 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                               StrictMode strict_mode) {
   ASM_LOCATION("KeyedStoreIC::GenerateRuntimeSetProperty");
-  // ---------- S t a t e --------------
-  //  -- x0     : value
-  //  -- x1     : key
-  //  -- x2     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
 
   // Push receiver, key and value for runtime call.
-  __ Push(x2, x1, x0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // Push strict_mode for runtime call.
   __ Mov(x10, Smi::FromInt(strict_mode));
@@ -1067,12 +1056,6 @@
 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
                                    StrictMode strict_mode) {
   ASM_LOCATION("KeyedStoreIC::GenerateGeneric");
-  // ---------- S t a t e --------------
-  //  -- x0     : value
-  //  -- x1     : key
-  //  -- x2     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
   Label slow;
   Label array;
   Label fast_object;
@@ -1081,9 +1064,13 @@
   Label fast_double_grow;
   Label fast_double;
 
-  Register value = x0;
-  Register key = x1;
-  Register receiver = x2;
+  Register value = ValueRegister();
+  Register key = NameRegister();
+  Register receiver = ReceiverRegister();
+  ASSERT(receiver.is(x2));
+  ASSERT(key.is(x1));
+  ASSERT(value.is(x0));
+
   Register receiver_map = x3;
   Register elements = x4;
   Register elements_map = x5;
@@ -1168,17 +1155,14 @@
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- x0    : value
-  //  -- x1    : receiver
-  //  -- x2    : name
-  //  -- lr    : return address
-  // -----------------------------------
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  ASSERT(!AreAliased(receiver, name, ValueRegister(), x3, x4, x5, x6));
 
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
-      masm, flags, x1, x2, x3, x4, x5, x6);
+      masm, flags, receiver, name, x3, x4, x5, x6);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -1186,14 +1170,7 @@
 
 
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- x0    : value
-  //  -- x1    : receiver
-  //  -- x2    : name
-  //  -- lr    : return address
-  // -----------------------------------
-
-  __ Push(x1, x2, x0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // Tail call to the entry.
   ExternalReference ref =
@@ -1203,17 +1180,12 @@
 
 
 void StoreIC::GenerateNormal(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- x0    : value
-  //  -- x1    : receiver
-  //  -- x2    : name
-  //  -- lr    : return address
-  // -----------------------------------
   Label miss;
-  Register value = x0;
-  Register receiver = x1;
-  Register name = x2;
+  Register value = ValueRegister();
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
   Register dictionary = x3;
+  ASSERT(!AreAliased(value, receiver, name, x3, x4, x5));
 
   GenerateNameDictionaryReceiverCheck(
       masm, receiver, dictionary, x4, x5, &miss);
@@ -1233,14 +1205,8 @@
 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                          StrictMode strict_mode) {
   ASM_LOCATION("StoreIC::GenerateRuntimeSetProperty");
-  // ----------- S t a t e -------------
-  //  -- x0    : value
-  //  -- x1    : receiver
-  //  -- x2    : name
-  //  -- lr    : return address
-  // -----------------------------------
 
-  __ Push(x1, x2, x0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   __ Mov(x10, Smi::FromInt(strict_mode));
   __ Push(x10);
@@ -1259,7 +1225,7 @@
   // -----------------------------------
 
   // Push receiver, name and value for runtime call.
-  __ Push(x1, x2, x0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // The slow case calls into the runtime to complete the store without causing
   // an IC miss that would otherwise cause a transition to the generic stub.
diff --git a/src/arm64/lithium-arm64.cc b/src/arm64/lithium-arm64.cc
index acae6b0..3431116 100644
--- a/src/arm64/lithium-arm64.cc
+++ b/src/arm64/lithium-arm64.cc
@@ -2358,9 +2358,10 @@
 
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* object = UseFixed(instr->object(), x2);
-  LOperand* key = UseFixed(instr->key(), x1);
-  LOperand* value = UseFixed(instr->value(), x0);
+  LOperand* object = UseFixed(instr->object(),
+                              KeyedStoreIC::ReceiverRegister());
+  LOperand* key = UseFixed(instr->key(), KeyedStoreIC::NameRegister());
+  LOperand* value = UseFixed(instr->value(), KeyedStoreIC::ValueRegister());
 
   ASSERT(instr->object()->representation().IsTagged());
   ASSERT(instr->key()->representation().IsTagged());
@@ -2402,8 +2403,9 @@
 
 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* object = UseFixed(instr->object(), x1);
-  LOperand* value = UseFixed(instr->value(), x0);
+  LOperand* object = UseFixed(instr->object(), StoreIC::ReceiverRegister());
+  LOperand* value = UseFixed(instr->value(), StoreIC::ValueRegister());
+
   LInstruction* result = new(zone()) LStoreNamedGeneric(context, object, value);
   return MarkAsCall(result, instr);
 }
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc
index dd24b9c..46d88e5 100644
--- a/src/arm64/lithium-codegen-arm64.cc
+++ b/src/arm64/lithium-codegen-arm64.cc
@@ -5322,9 +5322,9 @@
 
 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->object()).Is(x2));
-  ASSERT(ToRegister(instr->key()).Is(x1));
-  ASSERT(ToRegister(instr->value()).Is(x0));
+  ASSERT(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister()));
+  ASSERT(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister()));
 
   Handle<Code> ic = instr->strict_mode() == STRICT
       ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
@@ -5429,11 +5429,10 @@
 
 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->value()).is(x0));
-  ASSERT(ToRegister(instr->object()).is(x1));
+  ASSERT(ToRegister(instr->object()).is(StoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->value()).is(StoreIC::ValueRegister()));
 
-  // Name must be in x2.
-  __ Mov(x2, Operand(instr->name()));
+  __ Mov(StoreIC::NameRegister(), Operand(instr->name()));
   Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
diff --git a/src/arm64/stub-cache-arm64.cc b/src/arm64/stub-cache-arm64.cc
index 85774d9..d52493e 100644
--- a/src/arm64/stub-cache-arm64.cc
+++ b/src/arm64/stub-cache-arm64.cc
@@ -1262,20 +1262,24 @@
 
 
 Register StoreStubCompiler::value() {
-  return x0;
+  return StoreIC::ValueRegister();
 }
 
 
 Register* StoreStubCompiler::registers() {
   // receiver, value, scratch1, scratch2, scratch3.
-  static Register registers[] = { x1, x2, x3, x4, x5 };
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  static Register registers[] = { receiver, name, x3, x4, x5 };
   return registers;
 }
 
 
 Register* KeyedStoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { x2, x1, x3, x4, x5 };
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  static Register registers[] = { receiver, name, x3, x4, x5 };
   return registers;
 }
 
diff --git a/src/assembler.cc b/src/assembler.cc
index 2e5e828..a98ff1e 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -1572,11 +1572,6 @@
   ASSERT(pos != RelocInfo::kNoPosition);
   ASSERT(pos >= 0);
   state_.current_position = pos;
-#ifdef ENABLE_GDB_JIT_INTERFACE
-  if (gdbjit_lineinfo_ != NULL) {
-    gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, false);
-  }
-#endif
   LOG_CODE_EVENT(assembler_->isolate(),
                  CodeLinePosInfoAddPositionEvent(jit_handler_data_,
                                                  assembler_->pc_offset(),
@@ -1588,11 +1583,6 @@
   ASSERT(pos != RelocInfo::kNoPosition);
   ASSERT(pos >= 0);
   state_.current_statement_position = pos;
-#ifdef ENABLE_GDB_JIT_INTERFACE
-  if (gdbjit_lineinfo_ != NULL) {
-    gdbjit_lineinfo_->SetPosition(assembler_->pc_offset(), pos, true);
-  }
-#endif
   LOG_CODE_EVENT(assembler_->isolate(),
                  CodeLinePosInfoAddStatementPositionEvent(
                      jit_handler_data_,
diff --git a/src/assembler.h b/src/assembler.h
index 0ef7f5e..c92ef1e 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -1022,29 +1022,9 @@
  public:
   explicit PositionsRecorder(Assembler* assembler)
       : assembler_(assembler) {
-#ifdef ENABLE_GDB_JIT_INTERFACE
-    gdbjit_lineinfo_ = NULL;
-#endif
     jit_handler_data_ = NULL;
   }
 
-#ifdef ENABLE_GDB_JIT_INTERFACE
-  ~PositionsRecorder() {
-    delete gdbjit_lineinfo_;
-  }
-
-  void StartGDBJITLineInfoRecording() {
-    if (FLAG_gdbjit) {
-      gdbjit_lineinfo_ = new GDBJITLineInfo();
-    }
-  }
-
-  GDBJITLineInfo* DetachGDBJITLineInfo() {
-    GDBJITLineInfo* lineinfo = gdbjit_lineinfo_;
-    gdbjit_lineinfo_ = NULL;  // To prevent deallocation in destructor.
-    return lineinfo;
-  }
-#endif
   void AttachJITHandlerData(void* user_data) {
     jit_handler_data_ = user_data;
   }
@@ -1072,9 +1052,6 @@
  private:
   Assembler* assembler_;
   PositionState state_;
-#ifdef ENABLE_GDB_JIT_INTERFACE
-  GDBJITLineInfo* gdbjit_lineinfo_;
-#endif
 
   // Currently jit_handler_data_ is used to store JITHandler-specific data
   // over the lifetime of a PositionsRecorder
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index c6705c3..bdd168b 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -603,7 +603,9 @@
 template <>
 HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() {
   BuildUncheckedMonomorphicElementAccess(
-      GetParameter(0), GetParameter(1), GetParameter(2),
+      GetParameter(StoreIC::kReceiverIndex),
+      GetParameter(StoreIC::kNameIndex),
+      GetParameter(StoreIC::kValueIndex),
       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
       STORE, NEVER_RETURN_HOLE, casted_stub()->store_mode());
 
@@ -1028,7 +1030,7 @@
   Handle<PropertyCell> placeholder_cell =
       isolate()->factory()->NewPropertyCell(placeholer_value);
 
-  HParameter* value = GetParameter(2);
+  HParameter* value = GetParameter(StoreIC::kValueIndex);
 
   if (stub->check_global()) {
     // Check that the map of the global has not changed: use a placeholder map
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 507d6f5..79eccef 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -634,6 +634,27 @@
 }
 
 
+void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
+    CodeStubInterfaceDescriptor* descriptor) {
+  Register registers[] = { KeyedStoreIC::ReceiverRegister(),
+                           KeyedStoreIC::NameRegister(),
+                           KeyedStoreIC::ValueRegister() };
+  descriptor->Initialize(
+      ARRAY_SIZE(registers), registers,
+      FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
+}
+
+
+void StoreGlobalStub::InitializeInterfaceDescriptor(
+    CodeStubInterfaceDescriptor* descriptor) {
+  Register registers[] = { StoreIC::ReceiverRegister(),
+                           StoreIC::NameRegister(),
+                           StoreIC::ValueRegister() };
+  descriptor->Initialize(ARRAY_SIZE(registers), registers,
+                         FUNCTION_ADDR(StoreIC_MissFromStubFailure));
+}
+
+
 void KeyedLoadDictionaryElementPlatformStub::Generate(
     MacroAssembler* masm) {
   KeyedLoadStubCompiler::GenerateLoadDictionaryElement(masm);
diff --git a/src/compiler.cc b/src/compiler.cc
index 59c6a36..4dc5f30 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -31,6 +31,19 @@
 namespace internal {
 
 
+ScriptData::ScriptData(const byte* data, int length)
+    : owns_data_(false), data_(data), length_(length) {
+  if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) {
+    byte* copy = NewArray<byte>(length);
+    // TODO(yangguo): find out why this is not always the case.
+    // ASSERT(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment));
+    CopyBytes(copy, data, length);
+    data_ = copy;
+    AcquireDataOwnership();
+  }
+}
+
+
 CompilationInfo::CompilationInfo(Handle<Script> script,
                                  Zone* zone)
     : flags_(StrictModeField::encode(SLOPPY)),
diff --git a/src/compiler.h b/src/compiler.h
index b0c4e11..58fb164 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -13,7 +13,6 @@
 namespace internal {
 
 class AstValueFactory;
-class ScriptData;
 class HydrogenCodeStub;
 
 // ParseRestriction is used to restrict the set of valid statements in a
@@ -35,6 +34,36 @@
   int to;
 };
 
+
+class ScriptData {
+ public:
+  ScriptData(const byte* data, int length);
+  ~ScriptData() {
+    if (owns_data_) DeleteArray(data_);
+  }
+
+  const byte* data() const { return data_; }
+  int length() const { return length_; }
+
+  void AcquireDataOwnership() {
+    ASSERT(!owns_data_);
+    owns_data_ = true;
+  }
+
+  void ReleaseDataOwnership() {
+    ASSERT(owns_data_);
+    owns_data_ = false;
+  }
+
+ private:
+  bool owns_data_;
+  const byte* data_;
+  int length_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScriptData);
+};
+
+
 // CompilationInfo encapsulates some information known at compile time.  It
 // is constructed based on the resources available at compile-time.
 class CompilationInfo {
@@ -722,7 +751,6 @@
   DISALLOW_COPY_AND_ASSIGN(CompilationPhase);
 };
 
-
 } }  // namespace v8::internal
 
 #endif  // V8_COMPILER_H_
diff --git a/src/d8.cc b/src/d8.cc
index 4e0d86f..35732b1 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -29,6 +29,10 @@
 #include "include/v8-testing.h"
 #endif  // V8_SHARED
 
+#if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE)
+#include "src/gdb-jit.h"
+#endif
+
 #ifdef ENABLE_VTUNE_JIT_INTERFACE
 #include "src/third_party/vtune/v8-vtune.h"
 #endif
@@ -1577,6 +1581,12 @@
   {
     Isolate::Scope scope(isolate);
     Initialize(isolate);
+#if !defined(V8_SHARED) && defined(ENABLE_GDB_JIT_INTERFACE)
+    if (i::FLAG_gdbjit) {
+      v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault,
+                                     i::GDBJITInterface::EventHandler);
+    }
+#endif
 #ifdef ENABLE_VTUNE_JIT_INTERFACE
     vTune::InitializeVtuneForV8();
 #endif
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index de7faa3..9b9b40d 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -303,9 +303,6 @@
   MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
   if (info->will_serialize()) masm.enable_serializer();
 
-#ifdef ENABLE_GDB_JIT_INTERFACE
-  masm.positions_recorder()->StartGDBJITLineInfoRecording();
-#endif
   LOG_CODE_EVENT(isolate,
                  CodeStartLinePosInfoRecordEvent(masm.positions_recorder()));
 
@@ -332,13 +329,6 @@
   code->set_back_edge_table_offset(table_offset);
   CodeGenerator::PrintCode(code, info);
   info->SetCode(code);
-#ifdef ENABLE_GDB_JIT_INTERFACE
-  if (FLAG_gdbjit) {
-    GDBJITLineInfo* lineinfo =
-        masm.positions_recorder()->DetachGDBJITLineInfo();
-    GDBJIT(RegisterDetailedLineInfo(*code, lineinfo));
-  }
-#endif
   void* line_info = masm.positions_recorder()->DetachJITHandlerData();
   LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info));
   return true;
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index 51895f0..5ca6dfd 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -899,6 +899,32 @@
 #endif  // defined(__ELF)
 
 
+class LineInfo : public Malloced {
+ public:
+  LineInfo() : pc_info_(10) {}
+
+  void SetPosition(intptr_t pc, int pos, bool is_statement) {
+    AddPCInfo(PCInfo(pc, pos, is_statement));
+  }
+
+  struct PCInfo {
+    PCInfo(intptr_t pc, int pos, bool is_statement)
+        : pc_(pc), pos_(pos), is_statement_(is_statement) {}
+
+    intptr_t pc_;
+    int pos_;
+    bool is_statement_;
+  };
+
+  List<PCInfo>* pc_info() { return &pc_info_; }
+
+ private:
+  void AddPCInfo(const PCInfo& pc_info) { pc_info_.Add(pc_info); }
+
+  List<PCInfo> pc_info_;
+};
+
+
 class CodeDescription BASE_EMBEDDED {
  public:
 #if V8_TARGET_ARCH_X64
@@ -910,27 +936,21 @@
   };
 #endif
 
-  CodeDescription(const char* name,
-                  Code* code,
-                  Handle<Script> script,
-                  GDBJITLineInfo* lineinfo,
-                  GDBJITInterface::CodeTag tag,
+  CodeDescription(const char* name, Code* code, Handle<Script> script,
+                  LineInfo* lineinfo, GDBJITInterface::CodeTag tag,
                   CompilationInfo* info)
       : name_(name),
         code_(code),
         script_(script),
         lineinfo_(lineinfo),
         tag_(tag),
-        info_(info) {
-  }
+        info_(info) {}
 
   const char* name() const {
     return name_;
   }
 
-  GDBJITLineInfo* lineinfo() const {
-    return lineinfo_;
-  }
+  LineInfo* lineinfo() const { return lineinfo_; }
 
   GDBJITInterface::CodeTag tag() const {
     return tag_;
@@ -989,7 +1009,7 @@
   const char* name_;
   Code* code_;
   Handle<Script> script_;
-  GDBJITLineInfo* lineinfo_;
+  LineInfo* lineinfo_;
   GDBJITInterface::CodeTag tag_;
   CompilationInfo* info_;
 #if V8_TARGET_ARCH_X64
@@ -1451,12 +1471,12 @@
     intptr_t line = 1;
     bool is_statement = true;
 
-    List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
+    List<LineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
     pc_info->Sort(&ComparePCInfo);
 
     int pc_info_length = pc_info->length();
     for (int i = 0; i < pc_info_length; i++) {
-      GDBJITLineInfo::PCInfo* info = &pc_info->at(i);
+      LineInfo::PCInfo* info = &pc_info->at(i);
       ASSERT(info->pc_ >= pc);
 
       // Reduce bloating in the debug line table by removing duplicate line
@@ -1527,8 +1547,8 @@
     w->Write<uint8_t>(op);
   }
 
-  static int ComparePCInfo(const GDBJITLineInfo::PCInfo* a,
-                           const GDBJITLineInfo::PCInfo* b) {
+  static int ComparePCInfo(const LineInfo::PCInfo* a,
+                           const LineInfo::PCInfo* b) {
     if (a->pc_ == b->pc_) {
       if (a->is_statement_ != b->is_statement_) {
         return b->is_statement_ ? +1 : -1;
@@ -1967,15 +1987,15 @@
 }
 
 
-static void* TagLineInfo(GDBJITLineInfo* ptr) {
+static void* TagLineInfo(LineInfo* ptr) {
   return reinterpret_cast<void*>(
       reinterpret_cast<intptr_t>(ptr) | kLineInfoTag);
 }
 
 
-static GDBJITLineInfo* UntagLineInfo(void* ptr) {
-  return reinterpret_cast<GDBJITLineInfo*>(
-      reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag);
+static LineInfo* UntagLineInfo(void* ptr) {
+  return reinterpret_cast<LineInfo*>(reinterpret_cast<intptr_t>(ptr) &
+                                     ~kLineInfoTag);
 }
 
 
@@ -2051,7 +2071,7 @@
   HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
   if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
 
-  GDBJITLineInfo* lineinfo = UntagLineInfo(e->value);
+  LineInfo* lineinfo = UntagLineInfo(e->value);
   CodeDescription code_desc(name,
                             code,
                             script != NULL ? Handle<Script>(script)
@@ -2167,8 +2187,7 @@
 }
 
 
-void GDBJITInterface::RegisterDetailedLineInfo(Code* code,
-                                               GDBJITLineInfo* line_info) {
+static void RegisterDetailedLineInfo(Code* code, LineInfo* line_info) {
   base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
   ASSERT(!IsLineInfoTagged(line_info));
   HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
@@ -2177,5 +2196,36 @@
 }
 
 
+void GDBJITInterface::EventHandler(const v8::JitCodeEvent* event) {
+  if (!FLAG_gdbjit) return;
+  switch (event->type) {
+    case v8::JitCodeEvent::CODE_ADDED:
+    case v8::JitCodeEvent::CODE_MOVED:
+    case v8::JitCodeEvent::CODE_REMOVED:
+      break;
+    case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
+      LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
+      line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
+                             static_cast<int>(event->line_info.pos),
+                             event->line_info.position_type ==
+                                 v8::JitCodeEvent::STATEMENT_POSITION);
+      break;
+    }
+    case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
+      v8::JitCodeEvent* mutable_event = const_cast<v8::JitCodeEvent*>(event);
+      mutable_event->user_data = new LineInfo();
+      break;
+    }
+    case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
+      LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
+      Code* code = Code::GetCodeFromTargetAddress(
+          reinterpret_cast<Address>(event->code_start));
+      RegisterDetailedLineInfo(code, line_info);
+      break;
+    }
+  }
+}
+
+
 } }  // namespace v8::internal
 #endif
diff --git a/src/gdb-jit.h b/src/gdb-jit.h
index db9c0f2..323038a 100644
--- a/src/gdb-jit.h
+++ b/src/gdb-jit.h
@@ -34,37 +34,6 @@
   V(EVAL)                                       \
   V(FUNCTION)
 
-class GDBJITLineInfo : public Malloced {
- public:
-  GDBJITLineInfo()
-      : pc_info_(10) { }
-
-  void SetPosition(intptr_t pc, int pos, bool is_statement) {
-    AddPCInfo(PCInfo(pc, pos, is_statement));
-  }
-
-  struct PCInfo {
-    PCInfo(intptr_t pc, int pos, bool is_statement)
-        : pc_(pc), pos_(pos), is_statement_(is_statement) { }
-
-    intptr_t pc_;
-    int pos_;
-    bool is_statement_;
-  };
-
-  List<PCInfo>* pc_info() {
-    return &pc_info_;
-  }
-
- private:
-  void AddPCInfo(const PCInfo& pc_info) {
-    pc_info_.Add(pc_info);
-  }
-
-  List<PCInfo> pc_info_;
-};
-
-
 class GDBJITInterface: public AllStatic {
  public:
   enum CodeTag {
@@ -84,6 +53,9 @@
     }
   }
 
+  // Main entry point into GDB JIT realized as a JitCodeEventHandler.
+  static void EventHandler(const v8::JitCodeEvent* event);
+
   static void AddCode(const char* name,
                       Code* code,
                       CodeTag tag,
@@ -104,8 +76,6 @@
   static void RemoveCode(Code* code);
 
   static void RemoveCodeRange(Address start, Address end);
-
-  static void RegisterDetailedLineInfo(Code* code, GDBJITLineInfo* line_info);
 };
 
 #define GDBJIT(action) GDBJITInterface::action
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index f39ac1d..6229386 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -1097,11 +1097,16 @@
     ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj));
   } else if (obj->IsJSArrayBuffer()) {
     ExtractJSArrayBufferReferences(entry, JSArrayBuffer::cast(obj));
-  } else if (obj->IsJSWeakSet()) {
-    ExtractJSWeakCollectionReferences(entry, JSWeakSet::cast(obj));
-  } else if (obj->IsJSWeakMap()) {
-    ExtractJSWeakCollectionReferences(entry, JSWeakMap::cast(obj));
   } else if (obj->IsJSObject()) {
+    if (obj->IsJSWeakSet()) {
+      ExtractJSWeakCollectionReferences(entry, JSWeakSet::cast(obj));
+    } else if (obj->IsJSWeakMap()) {
+      ExtractJSWeakCollectionReferences(entry, JSWeakMap::cast(obj));
+    } else if (obj->IsJSSet()) {
+      ExtractJSCollectionReferences(entry, JSSet::cast(obj));
+    } else if (obj->IsJSMap()) {
+      ExtractJSCollectionReferences(entry, JSMap::cast(obj));
+    }
     ExtractJSObjectReferences(entry, JSObject::cast(obj));
   } else if (obj->IsString()) {
     ExtractStringReferences(entry, String::cast(obj));
@@ -1260,6 +1265,13 @@
 }
 
 
+void V8HeapExplorer::ExtractJSCollectionReferences(int entry,
+                                                   JSCollection* collection) {
+  SetInternalReference(collection, entry, "table", collection->table(),
+                       JSCollection::kTableOffset);
+}
+
+
 void V8HeapExplorer::ExtractJSWeakCollectionReferences(
     int entry, JSWeakCollection* collection) {
   MarkAsWeakContainer(collection->table());
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index e18d70a..329570f 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -370,6 +370,7 @@
   void ExtractJSObjectReferences(int entry, JSObject* js_obj);
   void ExtractStringReferences(int entry, String* obj);
   void ExtractSymbolReferences(int entry, Symbol* symbol);
+  void ExtractJSCollectionReferences(int entry, JSCollection* collection);
   void ExtractJSWeakCollectionReferences(int entry,
                                          JSWeakCollection* collection);
   void ExtractContextReferences(int entry, Context* context);
diff --git a/src/heap.cc b/src/heap.cc
index 8560aa3..d172ceb 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -408,7 +408,7 @@
 }
 
 
-void Heap::GarbageCollectionPrologue(GarbageCollector collector) {
+void Heap::GarbageCollectionPrologue() {
   {  AllowHeapAllocation for_the_first_part_of_prologue;
     ClearJSFunctionResultCaches();
     gc_count_++;
@@ -439,7 +439,7 @@
   ReportStatisticsBeforeGC();
 #endif  // DEBUG
 
-  store_buffer()->GCPrologue(collector == MARK_COMPACTOR);
+  store_buffer()->GCPrologue();
 
   if (isolate()->concurrent_osr_enabled()) {
     isolate()->optimizing_compiler_thread()->AgeBufferedOsrJobs();
@@ -837,7 +837,7 @@
   { GCTracer tracer(this, gc_reason, collector_reason);
     ASSERT(AllowHeapAllocation::IsAllowed());
     DisallowHeapAllocation no_allocation_during_gc;
-    GarbageCollectionPrologue(collector);
+    GarbageCollectionPrologue();
     // The GC count was incremented in the prologue.  Tell the tracer about
     // it.
     tracer.set_gc_count(gc_count_);
diff --git a/src/heap.h b/src/heap.h
index 66f7ce6..a6a14f6 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1698,7 +1698,7 @@
 
   // Code that should be run before and after each GC.  Includes some
   // reporting/verification activities when compiled with DEBUG set.
-  void GarbageCollectionPrologue(GarbageCollector collector);
+  void GarbageCollectionPrologue();
   void GarbageCollectionEpilogue();
 
   // Pretenuring decisions are made based on feedback collected during new
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index e3f1aa6..1dfd62f 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -92,15 +92,6 @@
 }
 
 
-void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { edx, ecx, eax };
-  descriptor->Initialize(
-      ARRAY_SIZE(registers), registers,
-      FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
-}
-
-
 void TransitionElementsKindStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { eax, ebx };
@@ -234,14 +225,6 @@
 }
 
 
-void StoreGlobalStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { edx, ecx, eax };
-  descriptor->Initialize(ARRAY_SIZE(registers), registers,
-                         FUNCTION_ADDR(StoreIC_MissFromStubFailure));
-}
-
-
 void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { eax, ebx, ecx, edx };
diff --git a/src/ia32/debug-ia32.cc b/src/ia32/debug-ia32.cc
index 68cf0dd..763c548 100644
--- a/src/ia32/debug-ia32.cc
+++ b/src/ia32/debug-ia32.cc
@@ -188,13 +188,11 @@
 
 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
   // Register state for IC store call (from ic-ia32.cc).
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : name
-  //  -- edx    : receiver
-  // -----------------------------------
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  Register value = StoreIC::ValueRegister();
   Generate_DebugBreakCallHelper(
-      masm, eax.bit() | ecx.bit() | edx.bit(), 0, false);
+      masm, receiver.bit() | name.bit() | value.bit(), 0, false);
 }
 
 
@@ -205,14 +203,12 @@
 
 
 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
-  // Register state for keyed IC load call (from ic-ia32.cc).
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : key
-  //  -- edx    : receiver
-  // -----------------------------------
+  // Register state for keyed IC store call (from ic-ia32.cc).
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  Register value = KeyedStoreIC::ValueRegister();
   Generate_DebugBreakCallHelper(
-      masm, eax.bit() | ecx.bit() | edx.bit(), 0, false);
+      masm, receiver.bit() | name.bit() | value.bit(), 0, false);
 }
 
 
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index e9f13c1..e3669cf 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1633,8 +1633,9 @@
         if (key->value()->IsInternalizedString()) {
           if (property->emit_store()) {
             VisitForAccumulatorValue(value);
-            __ mov(ecx, Immediate(key->value()));
-            __ mov(edx, Operand(esp, 0));
+            ASSERT(StoreIC::ValueRegister().is(eax));
+            __ mov(StoreIC::NameRegister(), Immediate(key->value()));
+            __ mov(StoreIC::ReceiverRegister(), Operand(esp, 0));
             CallStoreIC(key->LiteralFeedbackId());
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -2349,9 +2350,9 @@
     case NAMED_PROPERTY: {
       __ push(eax);  // Preserve value.
       VisitForAccumulatorValue(prop->obj());
-      __ mov(edx, eax);
-      __ pop(eax);  // Restore value.
-      __ mov(ecx, prop->key()->AsLiteral()->value());
+      __ Move(StoreIC::ReceiverRegister(), eax);
+      __ pop(StoreIC::ValueRegister());  // Restore value.
+      __ mov(StoreIC::NameRegister(), prop->key()->AsLiteral()->value());
       CallStoreIC();
       break;
     }
@@ -2359,9 +2360,9 @@
       __ push(eax);  // Preserve value.
       VisitForStackValue(prop->obj());
       VisitForAccumulatorValue(prop->key());
-      __ mov(ecx, eax);
-      __ pop(edx);  // Receiver.
-      __ pop(eax);  // Restore value.
+      __ Move(KeyedStoreIC::NameRegister(), eax);
+      __ pop(KeyedStoreIC::ReceiverRegister());  // Receiver.
+      __ pop(KeyedStoreIC::ValueRegister());  // Restore value.
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
@@ -2398,8 +2399,8 @@
                                                Token::Value op) {
   if (var->IsUnallocated()) {
     // Global var, const, or let.
-    __ mov(ecx, var->name());
-    __ mov(edx, GlobalObjectOperand());
+    __ mov(StoreIC::NameRegister(), var->name());
+    __ mov(StoreIC::ReceiverRegister(), GlobalObjectOperand());
     CallStoreIC();
 
   } else if (op == Token::INIT_CONST_LEGACY) {
@@ -2470,8 +2471,8 @@
 
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  __ mov(ecx, prop->key()->AsLiteral()->value());
-  __ pop(edx);
+  __ mov(StoreIC::NameRegister(), prop->key()->AsLiteral()->value());
+  __ pop(StoreIC::ReceiverRegister());
   CallStoreIC(expr->AssignmentFeedbackId());
   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
   context()->Plug(eax);
@@ -2484,8 +2485,9 @@
   // esp[0]            : key
   // esp[kPointerSize] : receiver
 
-  __ pop(ecx);  // Key.
-  __ pop(edx);
+  __ pop(KeyedStoreIC::NameRegister());  // Key.
+  __ pop(KeyedStoreIC::ReceiverRegister());
+  ASSERT(KeyedStoreIC::ValueRegister().is(eax));
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
   Handle<Code> ic = strict_mode() == SLOPPY
@@ -4332,8 +4334,8 @@
       }
       break;
     case NAMED_PROPERTY: {
-      __ mov(ecx, prop->key()->AsLiteral()->value());
-      __ pop(edx);
+      __ mov(StoreIC::NameRegister(), prop->key()->AsLiteral()->value());
+      __ pop(StoreIC::ReceiverRegister());
       CallStoreIC(expr->CountStoreFeedbackId());
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -4346,8 +4348,8 @@
       break;
     }
     case KEYED_PROPERTY: {
-      __ pop(ecx);
-      __ pop(edx);
+      __ pop(KeyedStoreIC::NameRegister());
+      __ pop(KeyedStoreIC::ReceiverRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 4536103..379ed0f 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -555,23 +555,14 @@
 }
 
 
-// A register that isn't one of the parameters to the load ic.
-static const Register LoadIC_TempRegister() { return ebx; }
-
-
-// A register that isn't one of the parameters to the load ic.
-static const Register KeyedLoadIC_TempRegister() {
-  return LoadIC_TempRegister();
-}
-
-
 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
   // Return address is on the stack.
   Label miss;
 
   Register receiver = ReceiverRegister();
   Register index = NameRegister();
-  Register scratch = KeyedLoadIC_TempRegister();
+  Register scratch = ebx;
+  ASSERT(!scratch.is(receiver) && !scratch.is(index));
   Register result = eax;
   ASSERT(!result.is(scratch));
 
@@ -665,27 +656,30 @@
 
 
 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : key
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
+  // Return address is on the stack.
   Label slow, notin;
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  Register value = ValueRegister();
+  ASSERT(receiver.is(edx));
+  ASSERT(name.is(ecx));
+  ASSERT(value.is(eax));
+
   Operand mapped_location =
-      GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, edi, &notin, &slow);
-  __ mov(mapped_location, eax);
+      GenerateMappedArgumentsLookup(masm, receiver, name, ebx, edi, &notin,
+                                    &slow);
+  __ mov(mapped_location, value);
   __ lea(ecx, mapped_location);
-  __ mov(edx, eax);
+  __ mov(edx, value);
   __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs);
   __ Ret();
   __ bind(&notin);
   // The unmapped lookup expects that the parameter map is in ebx.
   Operand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, ecx, ebx, edi, &slow);
-  __ mov(unmapped_location, eax);
+      GenerateUnmappedArgumentsLookup(masm, name, ebx, edi, &slow);
+  __ mov(unmapped_location, value);
   __ lea(edi, unmapped_location);
-  __ mov(edx, eax);
+  __ mov(edx, value);
   __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs);
   __ Ret();
   __ bind(&slow);
@@ -703,9 +697,13 @@
   Label transition_smi_elements;
   Label finish_object_store, non_double_value, transition_double_elements;
   Label fast_double_without_map_check;
-  // eax: value
-  // ecx: key (a smi)
-  // edx: receiver
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register key = KeyedStoreIC::NameRegister();
+  Register value = KeyedStoreIC::ValueRegister();
+  ASSERT(receiver.is(edx));
+  ASSERT(key.is(ecx));
+  ASSERT(value.is(eax));
+  // key is a smi.
   // ebx: FixedArray receiver->elements
   // edi: receiver map
   // Fast case: Do the store, could either Object or double.
@@ -720,43 +718,43 @@
   // We have to go to the runtime if the current value is the hole because
   // there may be a callback on the element
   Label holecheck_passed1;
-  __ cmp(FixedArrayElementOperand(ebx, ecx),
+  __ cmp(FixedArrayElementOperand(ebx, key),
          masm->isolate()->factory()->the_hole_value());
   __ j(not_equal, &holecheck_passed1);
-  __ JumpIfDictionaryInPrototypeChain(edx, ebx, edi, slow);
-  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
+  __ JumpIfDictionaryInPrototypeChain(receiver, ebx, edi, slow);
+  __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
 
   __ bind(&holecheck_passed1);
 
   // Smi stores don't require further checks.
   Label non_smi_value;
-  __ JumpIfNotSmi(eax, &non_smi_value);
+  __ JumpIfNotSmi(value, &non_smi_value);
   if (increment_length == kIncrementLength) {
     // Add 1 to receiver->length.
-    __ add(FieldOperand(edx, JSArray::kLengthOffset),
+    __ add(FieldOperand(receiver, JSArray::kLengthOffset),
            Immediate(Smi::FromInt(1)));
   }
   // It's irrelevant whether array is smi-only or not when writing a smi.
-  __ mov(FixedArrayElementOperand(ebx, ecx), eax);
+  __ mov(FixedArrayElementOperand(ebx, key), value);
   __ ret(0);
 
   __ bind(&non_smi_value);
   // Escape to elements kind transition case.
-  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
+  __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset));
   __ CheckFastObjectElements(edi, &transition_smi_elements);
 
   // Fast elements array, store the value to the elements backing store.
   __ bind(&finish_object_store);
   if (increment_length == kIncrementLength) {
     // Add 1 to receiver->length.
-    __ add(FieldOperand(edx, JSArray::kLengthOffset),
+    __ add(FieldOperand(receiver, JSArray::kLengthOffset),
            Immediate(Smi::FromInt(1)));
   }
-  __ mov(FixedArrayElementOperand(ebx, ecx), eax);
+  __ mov(FixedArrayElementOperand(ebx, key), value);
   // Update write barrier for the elements array address.
-  __ mov(edx, eax);  // Preserve the value which is returned.
+  __ mov(edx, value);  // Preserve the value which is returned.
   __ RecordWriteArray(
-      ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+      ebx, edx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
   __ ret(0);
 
   __ bind(fast_double);
@@ -773,26 +771,26 @@
   // We have to see if the double version of the hole is present. If so
   // go to the runtime.
   uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
-  __ cmp(FieldOperand(ebx, ecx, times_4, offset), Immediate(kHoleNanUpper32));
+  __ cmp(FieldOperand(ebx, key, times_4, offset), Immediate(kHoleNanUpper32));
   __ j(not_equal, &fast_double_without_map_check);
-  __ JumpIfDictionaryInPrototypeChain(edx, ebx, edi, slow);
-  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
+  __ JumpIfDictionaryInPrototypeChain(receiver, ebx, edi, slow);
+  __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
 
   __ bind(&fast_double_without_map_check);
-  __ StoreNumberToDoubleElements(eax, ebx, ecx, edi, xmm0,
+  __ StoreNumberToDoubleElements(value, ebx, key, edi, xmm0,
                                  &transition_double_elements);
   if (increment_length == kIncrementLength) {
     // Add 1 to receiver->length.
-    __ add(FieldOperand(edx, JSArray::kLengthOffset),
+    __ add(FieldOperand(receiver, JSArray::kLengthOffset),
            Immediate(Smi::FromInt(1)));
   }
   __ ret(0);
 
   __ bind(&transition_smi_elements);
-  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
+  __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset));
 
   // Transition the array appropriately depending on the value type.
-  __ CheckMap(eax,
+  __ CheckMap(value,
               masm->isolate()->factory()->heap_number_map(),
               &non_double_value,
               DONT_DO_SMI_CHECK);
@@ -807,7 +805,7 @@
   AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS,
                                                     FAST_DOUBLE_ELEMENTS);
   ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, slow);
-  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
+  __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
   __ jmp(&fast_double_without_map_check);
 
   __ bind(&non_double_value);
@@ -820,14 +818,14 @@
   mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS);
   ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm, mode,
                                                                    slow);
-  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
+  __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
   __ jmp(&finish_object_store);
 
   __ bind(&transition_double_elements);
   // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
   // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
   // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
-  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
+  __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset));
   __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
                                          FAST_ELEMENTS,
                                          ebx,
@@ -835,34 +833,33 @@
                                          slow);
   mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS);
   ElementsTransitionGenerator::GenerateDoubleToObject(masm, mode, slow);
-  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
+  __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
   __ jmp(&finish_object_store);
 }
 
 
 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
                                    StrictMode strict_mode) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : key
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
+  // Return address is on the stack.
   Label slow, fast_object, fast_object_grow;
   Label fast_double, fast_double_grow;
   Label array, extra, check_if_double_array;
+  Register receiver = ReceiverRegister();
+  Register key = NameRegister();
+  ASSERT(receiver.is(edx));
+  ASSERT(key.is(ecx));
 
   // Check that the object isn't a smi.
-  __ JumpIfSmi(edx, &slow);
+  __ JumpIfSmi(receiver, &slow);
   // Get the map from the receiver.
-  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
+  __ mov(edi, FieldOperand(receiver, HeapObject::kMapOffset));
   // Check that the receiver does not require access checks and is not observed.
   // The generic stub does not perform map checks or handle observed objects.
   __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
             1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved);
   __ j(not_zero, &slow);
   // Check that the key is a smi.
-  __ JumpIfNotSmi(ecx, &slow);
+  __ JumpIfNotSmi(key, &slow);
   __ CmpInstanceType(edi, JS_ARRAY_TYPE);
   __ j(equal, &array);
   // Check that the object is some kind of JSObject.
@@ -870,13 +867,11 @@
   __ j(below, &slow);
 
   // Object case: Check key against length in the elements array.
-  // eax: value
-  // edx: JSObject
-  // ecx: key (a smi)
+  // Key is a smi.
   // edi: receiver map
-  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
+  __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
   // Check array bounds. Both the key and the length of FixedArray are smis.
-  __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
+  __ cmp(key, FieldOperand(ebx, FixedArray::kLengthOffset));
   __ j(below, &fast_object);
 
   // Slow case: call runtime.
@@ -887,15 +882,14 @@
   // perform the store and update the length. Used for adding one
   // element to the array by writing to array[array.length].
   __ bind(&extra);
-  // eax: value
-  // edx: receiver, a JSArray
-  // ecx: key, a smi.
+  // receiver is a JSArray.
+  // key is a smi.
   // ebx: receiver->elements, a FixedArray
   // edi: receiver map
-  // flags: compare (ecx, edx.length())
+  // flags: compare (key, receiver.length())
   // do not leave holes in the array:
   __ j(not_equal, &slow);
-  __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
+  __ cmp(key, FieldOperand(ebx, FixedArray::kLengthOffset));
   __ j(above_equal, &slow);
   __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset));
   __ cmp(edi, masm->isolate()->factory()->fixed_array_map());
@@ -911,15 +905,14 @@
   // array. Check that the array is in fast mode (and writable); if it
   // is the length is always a smi.
   __ bind(&array);
-  // eax: value
-  // edx: receiver, a JSArray
-  // ecx: key, a smi.
+  // receiver is a JSArray.
+  // key is a smi.
   // edi: receiver map
-  __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
+  __ mov(ebx, FieldOperand(receiver, JSObject::kElementsOffset));
 
   // Check the key against the length in the array and fall through to the
   // common store code.
-  __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // Compare smis.
+  __ cmp(key, FieldOperand(receiver, JSArray::kLengthOffset));  // Compare smis.
   __ j(above_equal, &extra);
 
   KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double,
@@ -974,14 +967,23 @@
 }
 
 
+static void LoadIC_PushArgs(MacroAssembler* masm) {
+  Register receiver = LoadIC::ReceiverRegister();
+  Register name = LoadIC::NameRegister();
+  ASSERT(!ebx.is(receiver) && !ebx.is(name));
+
+  __ pop(ebx);
+  __ push(receiver);
+  __ push(name);
+  __ push(ebx);
+}
+
+
 void LoadIC::GenerateMiss(MacroAssembler* masm) {
   // Return address is on the stack.
   __ IncrementCounter(masm->isolate()->counters()->load_miss(), 1);
 
-  __ pop(LoadIC_TempRegister());
-  __ push(ReceiverRegister());  // receiver
-  __ push(NameRegister());  // name
-  __ push(LoadIC_TempRegister());  // return address
+  LoadIC_PushArgs(masm);
 
   // Perform tail call to the entry.
   ExternalReference ref =
@@ -992,10 +994,7 @@
 
 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   // Return address is on the stack.
-  __ pop(LoadIC_TempRegister());
-  __ push(ReceiverRegister());   // receiver
-  __ push(NameRegister());       // name
-  __ push(LoadIC_TempRegister());  // return address
+  LoadIC_PushArgs(masm);
 
   // Perform tail call to the entry.
   __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
@@ -1006,10 +1005,7 @@
   // Return address is on the stack.
   __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1);
 
-  __ pop(KeyedLoadIC_TempRegister());
-  __ push(ReceiverRegister());  // receiver
-  __ push(NameRegister());  // name
-  __ push(KeyedLoadIC_TempRegister());  // return address
+  LoadIC_PushArgs(masm);
 
   // Perform tail call to the entry.
   ExternalReference ref =
@@ -1023,12 +1019,29 @@
 const Register LoadIC::NameRegister() { return ecx; }
 
 
+const Register StoreIC::ReceiverRegister() { return edx; }
+const Register StoreIC::NameRegister() { return ecx; }
+const Register StoreIC::ValueRegister() { return eax; }
+
+
+const Register KeyedStoreIC::ReceiverRegister() {
+  return StoreIC::ReceiverRegister();
+}
+
+
+const Register KeyedStoreIC::NameRegister() {
+  return StoreIC::NameRegister();
+}
+
+
+const Register KeyedStoreIC::ValueRegister() {
+  return StoreIC::ValueRegister();
+}
+
+
 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   // Return address is on the stack.
-  __ pop(KeyedLoadIC_TempRegister());
-  __ push(ReceiverRegister());  // receiver
-  __ push(NameRegister());  // name
-  __ push(KeyedLoadIC_TempRegister());  // return address
+  LoadIC_PushArgs(masm);
 
   // Perform tail call to the entry.
   __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
@@ -1036,34 +1049,35 @@
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : name
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
+  // Return address is on the stack.
   Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
-      masm, flags, edx, ecx, ebx, no_reg);
+      masm, flags, ReceiverRegister(), NameRegister(),
+      ebx, no_reg);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
 }
 
 
-void StoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : name
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
+static void StoreIC_PushArgs(MacroAssembler* masm) {
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  Register value = StoreIC::ValueRegister();
+
+  ASSERT(!ebx.is(receiver) && !ebx.is(name) && !ebx.is(value));
 
   __ pop(ebx);
-  __ push(edx);
-  __ push(ecx);
-  __ push(eax);
+  __ push(receiver);
+  __ push(name);
+  __ push(value);
   __ push(ebx);
+}
+
+
+void StoreIC::GenerateMiss(MacroAssembler* masm) {
+  // Return address is on the stack.
+  StoreIC_PushArgs(masm);
 
   // Perform tail call to the entry.
   ExternalReference ref =
@@ -1073,29 +1087,26 @@
 
 
 void StoreIC::GenerateNormal(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : name
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-
+  // Return address is on the stack.
   Label miss, restore_miss;
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  Register value = ValueRegister();
 
-  GenerateNameDictionaryReceiverCheck(masm, edx, ebx, edi, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, receiver, ebx, edi, &miss);
 
   // A lot of registers are needed for storing to slow case
   // objects. Push and restore receiver but rely on
   // GenerateDictionaryStore preserving the value and name.
-  __ push(edx);
-  GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi);
+  __ push(receiver);
+  GenerateDictionaryStore(masm, &restore_miss, ebx, name, value, receiver, edi);
   __ Drop(1);
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->store_normal_hit(), 1);
   __ ret(0);
 
   __ bind(&restore_miss);
-  __ pop(edx);
+  __ pop(receiver);
 
   __ bind(&miss);
   __ IncrementCounter(counters->store_normal_miss(), 1);
@@ -1105,16 +1116,13 @@
 
 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                          StrictMode strict_mode) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : name
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
+  // Return address is on the stack.
+  ASSERT(!ebx.is(ReceiverRegister()) && !ebx.is(NameRegister()) &&
+         !ebx.is(ValueRegister()));
   __ pop(ebx);
-  __ push(edx);
-  __ push(ecx);
-  __ push(eax);
+  __ push(ReceiverRegister());
+  __ push(NameRegister());
+  __ push(ValueRegister());
   __ push(Immediate(Smi::FromInt(strict_mode)));
   __ push(ebx);  // return address
 
@@ -1125,19 +1133,15 @@
 
 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                               StrictMode strict_mode) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : key
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-
+  // Return address is on the stack.
+  ASSERT(!ebx.is(ReceiverRegister()) && !ebx.is(NameRegister()) &&
+         !ebx.is(ValueRegister()));
   __ pop(ebx);
-  __ push(edx);
-  __ push(ecx);
-  __ push(eax);
-  __ push(Immediate(Smi::FromInt(strict_mode)));  // Strict mode.
-  __ push(ebx);   // return address
+  __ push(ReceiverRegister());
+  __ push(NameRegister());
+  __ push(ValueRegister());
+  __ push(Immediate(Smi::FromInt(strict_mode)));
+  __ push(ebx);  // return address
 
   // Do tail-call to runtime routine.
   __ TailCallRuntime(Runtime::kSetProperty, 4, 1);
@@ -1145,18 +1149,8 @@
 
 
 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : key
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-
-  __ pop(ebx);
-  __ push(edx);
-  __ push(ecx);
-  __ push(eax);
-  __ push(ebx);
+  // Return address is on the stack.
+  StoreIC_PushArgs(masm);
 
   // Do tail-call to runtime routine.
   ExternalReference ref =
@@ -1166,18 +1160,8 @@
 
 
 void StoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : key
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-
-  __ pop(ebx);
-  __ push(edx);
-  __ push(ecx);
-  __ push(eax);
-  __ push(ebx);   // return address
+  // Return address is on the stack.
+  StoreIC_PushArgs(masm);
 
   // Do tail-call to runtime routine.
   ExternalReference ref(IC_Utility(kStoreIC_Slow), masm->isolate());
@@ -1186,18 +1170,8 @@
 
 
 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- eax    : value
-  //  -- ecx    : key
-  //  -- edx    : receiver
-  //  -- esp[0] : return address
-  // -----------------------------------
-
-  __ pop(ebx);
-  __ push(edx);
-  __ push(ecx);
-  __ push(eax);
-  __ push(ebx);   // return address
+  // Return address is on the stack.
+  StoreIC_PushArgs(masm);
 
   // Do tail-call to runtime routine.
   ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate());
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index f43b0a7..0cd5c36 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -4054,10 +4054,10 @@
 
 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(esi));
-  ASSERT(ToRegister(instr->object()).is(edx));
-  ASSERT(ToRegister(instr->value()).is(eax));
+  ASSERT(ToRegister(instr->object()).is(StoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->value()).is(StoreIC::ValueRegister()));
 
-  __ mov(ecx, instr->name());
+  __ mov(StoreIC::NameRegister(), instr->name());
   Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -4236,9 +4236,9 @@
 
 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(esi));
-  ASSERT(ToRegister(instr->object()).is(edx));
-  ASSERT(ToRegister(instr->key()).is(ecx));
-  ASSERT(ToRegister(instr->value()).is(eax));
+  ASSERT(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister()));
+  ASSERT(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister()));
 
   Handle<Code> ic = instr->strict_mode() == STRICT
       ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index a528fe4..c408288 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -2287,9 +2287,10 @@
 
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), esi);
-  LOperand* object = UseFixed(instr->object(), edx);
-  LOperand* key = UseFixed(instr->key(), ecx);
-  LOperand* value = UseFixed(instr->value(), eax);
+  LOperand* object = UseFixed(instr->object(),
+                              KeyedStoreIC::ReceiverRegister());
+  LOperand* key = UseFixed(instr->key(), KeyedStoreIC::NameRegister());
+  LOperand* value = UseFixed(instr->value(), KeyedStoreIC::ValueRegister());
 
   ASSERT(instr->object()->representation().IsTagged());
   ASSERT(instr->key()->representation().IsTagged());
@@ -2391,8 +2392,8 @@
 
 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), esi);
-  LOperand* object = UseFixed(instr->object(), edx);
-  LOperand* value = UseFixed(instr->value(), eax);
+  LOperand* object = UseFixed(instr->object(), StoreIC::ReceiverRegister());
+  LOperand* value = UseFixed(instr->value(), StoreIC::ValueRegister());
 
   LStoreNamedGeneric* result =
       new(zone()) LStoreNamedGeneric(context, object, value);
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 4878001..7350319 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -1300,20 +1300,24 @@
 
 
 Register StoreStubCompiler::value() {
-  return eax;
+  return StoreIC::ValueRegister();
 }
 
 
 Register* StoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { edx, ecx, ebx, edi, no_reg };
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  static Register registers[] = { receiver, name, ebx, edi, no_reg };
   return registers;
 }
 
 
 Register* KeyedStoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { edx, ecx, ebx, edi, no_reg };
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  static Register registers[] = { receiver, name, ebx, edi, no_reg };
   return registers;
 }
 
diff --git a/src/ic.h b/src/ic.h
index 9ce2ae1..47ffd6e 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -583,6 +583,16 @@
   static const ExtraICState kStrictModeState =
       1 << StrictModeState::kShift;
 
+  enum RegisterInfo {
+    kReceiverIndex,
+    kNameIndex,
+    kValueIndex,
+    kRegisterArgumentCount
+  };
+  static const Register ReceiverRegister();
+  static const Register NameRegister();
+  static const Register ValueRegister();
+
   StoreIC(FrameDepth depth, Isolate* isolate)
       : IC(depth, isolate) {
     ASSERT(IsStoreStub());
@@ -691,6 +701,10 @@
     return ExtraICStateKeyedAccessStoreMode::decode(extra_state);
   }
 
+  static const Register ReceiverRegister();
+  static const Register NameRegister();
+  static const Register ValueRegister();
+
   KeyedStoreIC(FrameDepth depth, Isolate* isolate)
       : StoreIC(depth, isolate) {
     ASSERT(target()->is_keyed_store_stub());
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 9192c58..0df3adc 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -559,7 +559,7 @@
  private:
   // v8::Task overrides.
   virtual void Run() V8_OVERRIDE {
-    heap_->mark_compact_collector()->SweepInParallel(space_);
+    heap_->mark_compact_collector()->SweepInParallel(space_, 0);
     heap_->mark_compact_collector()->pending_sweeper_jobs_semaphore_.Signal();
   }
 
@@ -3544,7 +3544,7 @@
 
         switch (space->identity()) {
           case OLD_DATA_SPACE:
-            SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p);
+            SweepConservatively<SWEEP_ON_MAIN_THREAD>(space, NULL, p);
             break;
           case OLD_POINTER_SPACE:
             SweepPrecisely<SWEEP_AND_VISIT_LIVE_OBJECTS,
@@ -3939,7 +3939,7 @@
                      FreeList* free_list,
                      Address start,
                      int size) {
-  if (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY) {
+  if (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD) {
     return space->Free(start, size);
   } else {
     return size - free_list->Free(start, size);
@@ -3948,9 +3948,9 @@
 
 
 // Force instantiation of templatized SweepConservatively method for
-// SWEEP_SEQUENTIALLY mode.
+// SWEEP_ON_MAIN_THREAD mode.
 template intptr_t MarkCompactCollector::
-    SweepConservatively<MarkCompactCollector::SWEEP_SEQUENTIALLY>(
+    SweepConservatively<MarkCompactCollector::SWEEP_ON_MAIN_THREAD>(
         PagedSpace*, FreeList*, Page*);
 
 
@@ -3975,16 +3975,19 @@
   ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept());
   ASSERT((mode == MarkCompactCollector::SWEEP_IN_PARALLEL &&
          free_list != NULL) ||
-         (mode == MarkCompactCollector::SWEEP_SEQUENTIALLY &&
+         (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD &&
          free_list == NULL));
 
   // When parallel sweeping is active, the page will be marked after
   // sweeping by the main thread.
-  if (mode != MarkCompactCollector::SWEEP_IN_PARALLEL) {
+  if (mode == MarkCompactCollector::SWEEP_IN_PARALLEL) {
+    p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_FINALIZE);
+  } else {
     p->MarkSweptConservatively();
   }
 
   intptr_t freed_bytes = 0;
+  intptr_t max_freed_bytes = 0;
   size_t size = 0;
 
   // Skip over all the dead objects at the start of the page and mark them free.
@@ -3999,8 +4002,9 @@
 
   if (it.Done()) {
     size = p->area_end() - p->area_start();
-    freed_bytes += Free<mode>(space, free_list, p->area_start(),
-                              static_cast<int>(size));
+    freed_bytes = Free<mode>(space, free_list, p->area_start(),
+                             static_cast<int>(size));
+    max_freed_bytes = Max(freed_bytes, max_freed_bytes);
     ASSERT_EQ(0, p->LiveBytes());
     return freed_bytes;
   }
@@ -4010,8 +4014,9 @@
   Address free_end = StartOfLiveObject(cell_base, *cell);
   // Free the first free space.
   size = free_end - p->area_start();
-  freed_bytes += Free<mode>(space, free_list, p->area_start(),
-                            static_cast<int>(size));
+  freed_bytes = Free<mode>(space, free_list, p->area_start(),
+                           static_cast<int>(size));
+  max_freed_bytes = Max(freed_bytes, max_freed_bytes);
 
   // The start of the current free area is represented in undigested form by
   // the address of the last 32-word section that contained a live object and
@@ -4036,8 +4041,9 @@
           // so now we need to find the start of the first live object at the
           // end of the free space.
           free_end = StartOfLiveObject(cell_base, *cell);
-          freed_bytes += Free<mode>(space, free_list, free_start,
-                                    static_cast<int>(free_end - free_start));
+          freed_bytes = Free<mode>(space, free_list, free_start,
+                                   static_cast<int>(free_end - free_start));
+          max_freed_bytes = Max(freed_bytes, max_freed_bytes);
         }
       }
       // Update our undigested record of where the current free area started.
@@ -4051,31 +4057,41 @@
   // Handle the free space at the end of the page.
   if (cell_base - free_start > 32 * kPointerSize) {
     free_start = DigestFreeStart(free_start, free_start_cell);
-    freed_bytes += Free<mode>(space, free_list, free_start,
-                              static_cast<int>(p->area_end() - free_start));
+    freed_bytes = Free<mode>(space, free_list, free_start,
+                             static_cast<int>(p->area_end() - free_start));
+    max_freed_bytes = Max(freed_bytes, max_freed_bytes);
   }
 
   p->ResetLiveBytes();
-  return freed_bytes;
+  return max_freed_bytes;
 }
 
 
-void MarkCompactCollector::SweepInParallel(PagedSpace* space) {
+int MarkCompactCollector::SweepInParallel(PagedSpace* space,
+                                          int required_freed_bytes) {
   PageIterator it(space);
   FreeList* free_list = space == heap()->old_pointer_space()
                             ? free_list_old_pointer_space_.get()
                             : free_list_old_data_space_.get();
   FreeList private_free_list(space);
+  int max_freed = 0;
+  int max_freed_overall = 0;
   while (it.has_next()) {
     Page* p = it.next();
 
     if (p->TryParallelSweeping()) {
-      SweepConservatively<SWEEP_IN_PARALLEL>(space, &private_free_list, p);
+      max_freed = static_cast<int>(SweepConservatively<SWEEP_IN_PARALLEL>(
+          space, &private_free_list, p));
+      ASSERT(max_freed >= 0);
       free_list->Concatenate(&private_free_list);
-      p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_FINALIZE);
+      if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) {
+        return max_freed;
+      }
+      max_freed_overall = Max(max_freed, max_freed_overall);
     }
     if (p == space->end_of_unswept_pages()) break;
   }
+  return max_freed_overall;
 }
 
 
@@ -4131,7 +4147,7 @@
           PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n",
                  reinterpret_cast<intptr_t>(p));
         }
-        SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p);
+        SweepConservatively<SWEEP_ON_MAIN_THREAD>(space, NULL, p);
         pages_swept++;
         break;
       }
@@ -4142,27 +4158,16 @@
             PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n",
                    reinterpret_cast<intptr_t>(p));
           }
-          SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p);
+          SweepConservatively<SWEEP_ON_MAIN_THREAD>(space, NULL, p);
           pages_swept++;
           parallel_sweeping_active = true;
         } else {
-          if (p->scan_on_scavenge()) {
-            SweepPrecisely<SWEEP_ONLY, IGNORE_SKIP_LIST, IGNORE_FREE_SPACE>(
-                space, p, NULL);
-            pages_swept++;
-            if (FLAG_gc_verbose) {
-              PrintF("Sweeping 0x%" V8PRIxPTR
-                  " scan on scavenge page precisely.\n",
-                  reinterpret_cast<intptr_t>(p));
-            }
-          } else {
-            if (FLAG_gc_verbose) {
-              PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in parallel.\n",
-                  reinterpret_cast<intptr_t>(p));
-            }
-            p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_PENDING);
-            space->IncreaseUnsweptFreeBytes(p);
+          if (FLAG_gc_verbose) {
+            PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in parallel.\n",
+                   reinterpret_cast<intptr_t>(p));
           }
+          p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_PENDING);
+          space->IncreaseUnsweptFreeBytes(p);
         }
         space->set_end_of_unswept_pages(p);
         break;
diff --git a/src/mark-compact.h b/src/mark-compact.h
index 6b7c09b..bcbc056 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -577,7 +577,7 @@
   };
 
   enum SweepingParallelism {
-    SWEEP_SEQUENTIALLY,
+    SWEEP_ON_MAIN_THREAD,
     SWEEP_IN_PARALLEL
   };
 
@@ -590,7 +590,7 @@
 #endif
 
   // Sweep a single page from the given space conservatively.
-  // Return a number of reclaimed bytes.
+  // Returns the size of the biggest continuous freed memory chunk in bytes.
   template<SweepingParallelism type>
   static intptr_t SweepConservatively(PagedSpace* space,
                                       FreeList* free_list,
@@ -659,8 +659,11 @@
 
   MarkingParity marking_parity() { return marking_parity_; }
 
-  // Concurrent and parallel sweeping support.
-  void SweepInParallel(PagedSpace* space);
+  // Concurrent and parallel sweeping support. If required_freed_bytes was set
+  // to a value larger than 0, then sweeping returns after a block of at least
+  // required_freed_bytes was freed. If required_freed_bytes was set to zero
+  // then the whole given space is swept.
+  int SweepInParallel(PagedSpace* space, int required_freed_bytes);
 
   void WaitUntilSweepingCompleted();
 
diff --git a/src/messages.js b/src/messages.js
index e3d941b..12cc197 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -127,7 +127,6 @@
   illegal_break:                 ["Illegal break statement"],
   illegal_continue:              ["Illegal continue statement"],
   illegal_return:                ["Illegal return statement"],
-  illegal_let:                   ["Illegal let declaration outside extended mode"],
   error_loading_debugger:        ["Error loading debugger"],
   no_input_to_regexp:            ["No input to ", "%0"],
   invalid_json:                  ["String '", "%0", "' is not valid JSON"],
@@ -137,8 +136,6 @@
   array_indexof_not_defined:     ["Array.getIndexOf: Argument undefined"],
   object_not_extensible:         ["Can't add property ", "%0", ", object is not extensible"],
   illegal_access:                ["Illegal access"],
-  invalid_cached_data_function:  ["Invalid cached data for function ", "%0"],
-  invalid_cached_data:           ["Invalid cached data"],
   strict_mode_with:              ["Strict mode code may not include a with statement"],
   strict_eval_arguments:         ["Unexpected eval or arguments in strict mode"],
   too_many_arguments:            ["Too many arguments in function call (only 65535 allowed)"],
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index a2e1a27..130664d 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -87,15 +87,6 @@
 }
 
 
-void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { a2, a1, a0 };
-  descriptor->Initialize(
-      ARRAY_SIZE(registers), registers,
-      FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
-}
-
-
 void TransitionElementsKindStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { a0, a1 };
@@ -230,14 +221,6 @@
 }
 
 
-void StoreGlobalStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { a1, a2, a0 };
-  descriptor->Initialize(ARRAY_SIZE(registers), registers,
-                         FUNCTION_ADDR(StoreIC_MissFromStubFailure));
-}
-
-
 void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { a0, a3, a1, a2 };
diff --git a/src/mips/debug-mips.cc b/src/mips/debug-mips.cc
index 424a87a..ef28f33 100644
--- a/src/mips/debug-mips.cc
+++ b/src/mips/debug-mips.cc
@@ -193,31 +193,27 @@
 
 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
   // Calling convention for IC store (from ic-mips.cc).
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
-  // Registers a0, a1, and a2 contain objects that need to be pushed on the
-  // expression stack of the fake JS frame.
-  Generate_DebugBreakCallHelper(masm, a0.bit() | a1.bit() | a2.bit(), 0);
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  Register value = StoreIC::ValueRegister();
+  Generate_DebugBreakCallHelper(
+      masm, receiver.bit() | name.bit() | value.bit(), 0);
 }
 
 
 void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
-  // Calling convention for keyed IC load (from ic-arm.cc).
+  // Calling convention for keyed IC load (from ic-mips.cc).
   GenerateLoadICDebugBreak(masm);
 }
 
 
 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- ra     : return address
-  Generate_DebugBreakCallHelper(masm, a0.bit() | a1.bit() | a2.bit(), 0);
+  // Calling convention for IC keyed store call (from ic-mips.cc).
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  Register value = KeyedStoreIC::ValueRegister();
+  Generate_DebugBreakCallHelper(
+      masm, receiver.bit() | name.bit() | value.bit(), 0);
 }
 
 
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 11a67b7..1704b2f 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -1689,9 +1689,10 @@
         if (key->value()->IsInternalizedString()) {
           if (property->emit_store()) {
             VisitForAccumulatorValue(value);
-            __ mov(a0, result_register());
-            __ li(a2, Operand(key->value()));
-            __ lw(a1, MemOperand(sp));
+            __ mov(StoreIC::ValueRegister(), result_register());
+            ASSERT(StoreIC::ValueRegister().is(a0));
+            __ li(StoreIC::NameRegister(), Operand(key->value()));
+            __ lw(StoreIC::ReceiverRegister(), MemOperand(sp));
             CallStoreIC(key->LiteralFeedbackId());
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -2414,9 +2415,10 @@
     case NAMED_PROPERTY: {
       __ push(result_register());  // Preserve value.
       VisitForAccumulatorValue(prop->obj());
-      __ mov(a1, result_register());
-      __ pop(a0);  // Restore value.
-      __ li(a2, Operand(prop->key()->AsLiteral()->value()));
+      __ mov(StoreIC::ReceiverRegister(), result_register());
+      __ pop(StoreIC::ValueRegister());  // Restore value.
+      __ li(StoreIC::NameRegister(),
+            Operand(prop->key()->AsLiteral()->value()));
       CallStoreIC();
       break;
     }
@@ -2424,8 +2426,8 @@
       __ push(result_register());  // Preserve value.
       VisitForStackValue(prop->obj());
       VisitForAccumulatorValue(prop->key());
-      __ mov(a1, result_register());
-      __ Pop(a0, a2);  // a0 = restored value.
+      __ mov(KeyedStoreIC::NameRegister(), result_register());
+      __ Pop(KeyedStoreIC::ValueRegister(), KeyedStoreIC::ReceiverRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
         ? isolate()->builtins()->KeyedStoreIC_Initialize()
         : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
@@ -2462,9 +2464,9 @@
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
   if (var->IsUnallocated()) {
     // Global var, const, or let.
-    __ mov(a0, result_register());
-    __ li(a2, Operand(var->name()));
-    __ lw(a1, GlobalObjectOperand());
+    __ mov(StoreIC::ValueRegister(), result_register());
+    __ li(StoreIC::NameRegister(), Operand(var->name()));
+    __ lw(StoreIC::ReceiverRegister(), GlobalObjectOperand());
     CallStoreIC();
 
   } else if (op == Token::INIT_CONST_LEGACY) {
@@ -2533,10 +2535,9 @@
 
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  __ mov(a0, result_register());  // Load the value.
-  __ li(a2, Operand(prop->key()->AsLiteral()->value()));
-  __ pop(a1);
-
+  __ mov(StoreIC::ValueRegister(), result_register());
+  __ li(StoreIC::NameRegister(), Operand(prop->key()->AsLiteral()->value()));
+  __ pop(StoreIC::ReceiverRegister());
   CallStoreIC(expr->AssignmentFeedbackId());
 
   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
@@ -2554,8 +2555,9 @@
   // - a0 is the value,
   // - a1 is the key,
   // - a2 is the receiver.
-  __ mov(a0, result_register());
-  __ Pop(a2, a1);  // a1 = key.
+  __ mov(KeyedStoreIC::ValueRegister(), result_register());
+  __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister());
+  ASSERT(KeyedStoreIC::ValueRegister().is(a0));
 
   Handle<Code> ic = strict_mode() == SLOPPY
       ? isolate()->builtins()->KeyedStoreIC_Initialize()
@@ -4387,9 +4389,10 @@
       }
       break;
     case NAMED_PROPERTY: {
-      __ mov(a0, result_register());  // Value.
-      __ li(a2, Operand(prop->key()->AsLiteral()->value()));  // Name.
-      __ pop(a1);  // Receiver.
+      __ mov(StoreIC::ValueRegister(), result_register());
+      __ li(StoreIC::NameRegister(),
+            Operand(prop->key()->AsLiteral()->value()));
+      __ pop(StoreIC::ReceiverRegister());
       CallStoreIC(expr->CountStoreFeedbackId());
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -4402,8 +4405,8 @@
       break;
     }
     case KEYED_PROPERTY: {
-      __ mov(a0, result_register());  // Value.
-      __ Pop(a2, a1);  // a1 = key, a2 = receiver.
+      __ mov(KeyedStoreIC::ValueRegister(), result_register());
+      __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index 2ca6b4d..f38e736 100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -507,30 +507,31 @@
 
 
 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
+  Register receiver = ReceiverRegister();
+  Register key = NameRegister();
+  Register value = ValueRegister();
+  ASSERT(receiver.is(a2));
+  ASSERT(key.is(a1));
+  ASSERT(value.is(a0));
+
   Label slow, notin;
   // Store address is returned in register (of MemOperand) mapped_location.
-  MemOperand mapped_location =
-      GenerateMappedArgumentsLookup(masm, a2, a1, a3, t0, t1, &notin, &slow);
-  __ sw(a0, mapped_location);
-  __ mov(t5, a0);
+  MemOperand mapped_location = GenerateMappedArgumentsLookup(
+      masm, receiver, key, a3, t0, t1, &notin, &slow);
+  __ sw(value, mapped_location);
+  __ mov(t5, value);
   ASSERT_EQ(mapped_location.offset(), 0);
   __ RecordWrite(a3, mapped_location.rm(), t5,
                  kRAHasNotBeenSaved, kDontSaveFPRegs);
   __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a0);  // (In delay slot) return the value stored in v0.
+  __ mov(v0, value);  // (In delay slot) return the value stored in v0.
   __ bind(&notin);
   // The unmapped lookup expects that the parameter map is in a3.
   // Store address is returned in register (of MemOperand) unmapped_location.
   MemOperand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, a1, a3, t0, &slow);
-  __ sw(a0, unmapped_location);
-  __ mov(t5, a0);
+      GenerateUnmappedArgumentsLookup(masm, key, a3, t0, &slow);
+  __ sw(value, unmapped_location);
+  __ mov(t5, value);
   ASSERT_EQ(unmapped_location.offset(), 0);
   __ RecordWrite(a3, unmapped_location.rm(), t5,
                  kRAHasNotBeenSaved, kDontSaveFPRegs);
@@ -562,6 +563,16 @@
 const Register LoadIC::NameRegister() { return a2; }
 
 
+const Register StoreIC::ReceiverRegister() { return a1; }
+const Register StoreIC::NameRegister() { return a2; }
+const Register StoreIC::ValueRegister() { return a0; }
+
+
+const Register KeyedStoreIC::ReceiverRegister() { return a2; }
+const Register KeyedStoreIC::NameRegister() { return a1; }
+const Register KeyedStoreIC::ValueRegister() { return a0; }
+
+
 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   // The return address is in ra.
 
@@ -772,15 +783,8 @@
 
 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                               StrictMode strict_mode) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- ra     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(a2, a1, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
   __ li(a0, Operand(Smi::FromInt(strict_mode)));   // Strict mode.
   __ Push(a0);
 
@@ -974,9 +978,12 @@
   Label array, extra, check_if_double_array;
 
   // Register usage.
-  Register value = a0;
-  Register key = a1;
-  Register receiver = a2;
+  Register value = ValueRegister();
+  Register key = NameRegister();
+  Register receiver = ReceiverRegister();
+  ASSERT(receiver.is(a2));
+  ASSERT(key.is(a1));
+  ASSERT(value.is(a0));
   Register receiver_map = a3;
   Register elements_map = t2;
   Register elements = t3;  // Elements array of the receiver.
@@ -1095,15 +1102,8 @@
 
 
 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- ra     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(a2, a1, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   ExternalReference ref =
       ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
@@ -1112,15 +1112,8 @@
 
 
 void StoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a2     : key
-  //  -- a1     : receiver
-  //  -- ra     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(a1, a2, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // The slow case calls into the runtime to complete the store without causing
   // an IC miss that would otherwise cause a transition to the generic stub.
@@ -1131,16 +1124,9 @@
 
 
 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- ra     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
   // We can't use MultiPush as the order of the registers is important.
-  __ Push(a2, a1, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // The slow case calls into the runtime to complete the store without causing
   // an IC miss that would otherwise cause a transition to the generic stub.
@@ -1152,17 +1138,16 @@
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  ASSERT(receiver.is(a1));
+  ASSERT(name.is(a2));
+  ASSERT(ValueRegister().is(a0));
 
   // Get the receiver from the stack and probe the stub cache.
   Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
-      masm, flags, a1, a2, a3, t0, t1, t2);
+      masm, flags, receiver, name, a3, t0, t1, t2);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -1170,14 +1155,7 @@
 
 
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
-
-  __ Push(a1, a2, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
   // Perform tail call to the entry.
   ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss),
                                             masm->isolate());
@@ -1186,17 +1164,17 @@
 
 
 void StoreIC::GenerateNormal(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
   Label miss;
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  Register value = ValueRegister();
+  ASSERT(receiver.is(a1));
+  ASSERT(name.is(a2));
+  ASSERT(value.is(a0));
 
-  GenerateNameDictionaryReceiverCheck(masm, a1, a3, t0, t1, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, receiver, a3, t0, t1, &miss);
 
-  GenerateDictionaryStore(masm, &miss, a3, a2, a0, t0, t1);
+  GenerateDictionaryStore(masm, &miss, a3, name, value, t0, t1);
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->store_normal_hit(), 1, t0, t1);
   __ Ret();
@@ -1209,14 +1187,7 @@
 
 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                          StrictMode strict_mode) {
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
-
-  __ Push(a1, a2, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   __ li(a0, Operand(Smi::FromInt(strict_mode)));
   __ Push(a0);
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 247572a..95f6847 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -4131,11 +4131,10 @@
 
 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->object()).is(a1));
-  ASSERT(ToRegister(instr->value()).is(a0));
+  ASSERT(ToRegister(instr->object()).is(StoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->value()).is(StoreIC::ValueRegister()));
 
-  // Name is always in a2.
-  __ li(a2, Operand(instr->name()));
+  __ li(StoreIC::NameRegister(), Operand(instr->name()));
   Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -4363,9 +4362,9 @@
 
 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->object()).is(a2));
-  ASSERT(ToRegister(instr->key()).is(a1));
-  ASSERT(ToRegister(instr->value()).is(a0));
+  ASSERT(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister()));
+  ASSERT(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister()));
 
   Handle<Code> ic = (instr->strict_mode() == STRICT)
       ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index f264f62..0e0fea3 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -2201,9 +2201,9 @@
 
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* obj = UseFixed(instr->object(), a2);
-  LOperand* key = UseFixed(instr->key(), a1);
-  LOperand* val = UseFixed(instr->value(), a0);
+  LOperand* obj = UseFixed(instr->object(), KeyedStoreIC::ReceiverRegister());
+  LOperand* key = UseFixed(instr->key(), KeyedStoreIC::NameRegister());
+  LOperand* val = UseFixed(instr->value(), KeyedStoreIC::ValueRegister());
 
   ASSERT(instr->object()->representation().IsTagged());
   ASSERT(instr->key()->representation().IsTagged());
@@ -2277,8 +2277,8 @@
 
 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* obj = UseFixed(instr->object(), a1);
-  LOperand* val = UseFixed(instr->value(), a0);
+  LOperand* obj = UseFixed(instr->object(), StoreIC::ReceiverRegister());
+  LOperand* val = UseFixed(instr->value(), StoreIC::ValueRegister());
 
   LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val);
   return MarkAsCall(result, instr);
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 3611a28..d08d597 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -1270,20 +1270,24 @@
 
 
 Register StoreStubCompiler::value() {
-  return a0;
+  return StoreIC::ValueRegister();
 }
 
 
 Register* StoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { a1, a2, a3, t0, t1 };
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  static Register registers[] = { receiver, name, a3, t0, t1 };
   return registers;
 }
 
 
 Register* KeyedStoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { a2, a1, a3, t0, t1 };
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  static Register registers[] = { receiver, name, a3, t0, t1 };
   return registers;
 }
 
diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc
index db42d4b..823ce07 100644
--- a/src/mips64/code-stubs-mips64.cc
+++ b/src/mips64/code-stubs-mips64.cc
@@ -87,15 +87,6 @@
 }
 
 
-void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { a2, a1, a0 };
-  descriptor->Initialize(
-      ARRAY_SIZE(registers), registers,
-      FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
-}
-
-
 void TransitionElementsKindStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { a0, a1 };
@@ -230,14 +221,6 @@
 }
 
 
-void StoreGlobalStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { a1, a2, a0 };
-  descriptor->Initialize(ARRAY_SIZE(registers), registers,
-                         FUNCTION_ADDR(StoreIC_MissFromStubFailure));
-}
-
-
 void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { a0, a3, a1, a2 };
diff --git a/src/mips64/debug-mips64.cc b/src/mips64/debug-mips64.cc
index 6b805c7..cc8895d 100644
--- a/src/mips64/debug-mips64.cc
+++ b/src/mips64/debug-mips64.cc
@@ -195,32 +195,27 @@
 
 
 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
-  // Calling convention for IC store (from ic-mips.cc).
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
-  // Registers a0, a1, and a2 contain objects that need to be pushed on the
-  // expression stack of the fake JS frame.
-  Generate_DebugBreakCallHelper(masm, a0.bit() | a1.bit() | a2.bit(), 0);
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  Register value = StoreIC::ValueRegister();
+  Generate_DebugBreakCallHelper(
+      masm, receiver.bit() | name.bit() | value.bit(), 0);
 }
 
 
 void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
-  // Calling convention for keyed IC load (from ic-arm.cc).
+  // Calling convention for keyed IC load (from ic-mips64.cc).
   GenerateLoadICDebugBreak(masm);
 }
 
 
 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- ra     : return address
-  Generate_DebugBreakCallHelper(masm, a0.bit() | a1.bit() | a2.bit(), 0);
+  // Calling convention for IC keyed store call (from ic-mips64.cc).
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  Register value = KeyedStoreIC::ValueRegister();
+  Generate_DebugBreakCallHelper(
+      masm, receiver.bit() | name.bit() | value.bit(), 0);
 }
 
 
diff --git a/src/mips64/full-codegen-mips64.cc b/src/mips64/full-codegen-mips64.cc
index 5f036b6..15192cb 100644
--- a/src/mips64/full-codegen-mips64.cc
+++ b/src/mips64/full-codegen-mips64.cc
@@ -1686,9 +1686,10 @@
         if (key->value()->IsInternalizedString()) {
           if (property->emit_store()) {
             VisitForAccumulatorValue(value);
-            __ mov(a0, result_register());
-            __ li(a2, Operand(key->value()));
-            __ ld(a1, MemOperand(sp));
+            __ mov(StoreIC::ValueRegister(), result_register());
+            ASSERT(StoreIC::ValueRegister().is(a0));
+            __ li(StoreIC::NameRegister(), Operand(key->value()));
+            __ ld(StoreIC::ReceiverRegister(), MemOperand(sp));
             CallStoreIC(key->LiteralFeedbackId());
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -2409,9 +2410,10 @@
     case NAMED_PROPERTY: {
       __ push(result_register());  // Preserve value.
       VisitForAccumulatorValue(prop->obj());
-      __ mov(a1, result_register());
-      __ pop(a0);  // Restore value.
-      __ li(a2, Operand(prop->key()->AsLiteral()->value()));
+      __ mov(StoreIC::ReceiverRegister(), result_register());
+      __ pop(StoreIC::ValueRegister());  // Restore value.
+      __ li(StoreIC::NameRegister(),
+            Operand(prop->key()->AsLiteral()->value()));
       CallStoreIC();
       break;
     }
@@ -2419,8 +2421,8 @@
       __ push(result_register());  // Preserve value.
       VisitForStackValue(prop->obj());
       VisitForAccumulatorValue(prop->key());
-      __ mov(a1, result_register());
-      __ Pop(a0, a2);  // a0 = restored value.
+      __ Move(KeyedStoreIC::NameRegister(), result_register());
+      __ Pop(KeyedStoreIC::ValueRegister(), KeyedStoreIC::ReceiverRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
         ? isolate()->builtins()->KeyedStoreIC_Initialize()
         : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
@@ -2457,9 +2459,9 @@
 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
   if (var->IsUnallocated()) {
     // Global var, const, or let.
-    __ mov(a0, result_register());
-    __ li(a2, Operand(var->name()));
-    __ ld(a1, GlobalObjectOperand());
+    __ mov(StoreIC::ValueRegister(), result_register());
+    __ li(StoreIC::NameRegister(), Operand(var->name()));
+    __ ld(StoreIC::ReceiverRegister(), GlobalObjectOperand());
     CallStoreIC();
   } else if (op == Token::INIT_CONST_LEGACY) {
     // Const initializers need a write barrier.
@@ -2527,10 +2529,9 @@
 
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  __ mov(a0, result_register());  // Load the value.
-  __ li(a2, Operand(prop->key()->AsLiteral()->value()));
-  __ pop(a1);
-
+  __ mov(StoreIC::ValueRegister(), result_register());
+  __ li(StoreIC::NameRegister(), Operand(prop->key()->AsLiteral()->value()));
+  __ pop(StoreIC::ReceiverRegister());
   CallStoreIC(expr->AssignmentFeedbackId());
 
   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
@@ -2548,8 +2549,9 @@
   // - a0 is the value,
   // - a1 is the key,
   // - a2 is the receiver.
-  __ mov(a0, result_register());
-  __ Pop(a2, a1);  // a1 = key.
+  __ mov(KeyedStoreIC::ValueRegister(), result_register());
+  __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister());
+  ASSERT(KeyedStoreIC::ValueRegister().is(a0));
 
   Handle<Code> ic = strict_mode() == SLOPPY
       ? isolate()->builtins()->KeyedStoreIC_Initialize()
@@ -4380,9 +4382,10 @@
       }
       break;
     case NAMED_PROPERTY: {
-      __ mov(a0, result_register());  // Value.
-      __ li(a2, Operand(prop->key()->AsLiteral()->value()));  // Name.
-      __ pop(a1);  // Receiver.
+      __ mov(StoreIC::ValueRegister(), result_register());
+      __ li(StoreIC::NameRegister(),
+            Operand(prop->key()->AsLiteral()->value()));
+      __ pop(StoreIC::ReceiverRegister());
       CallStoreIC(expr->CountStoreFeedbackId());
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -4395,8 +4398,8 @@
       break;
     }
     case KEYED_PROPERTY: {
-      __ mov(a0, result_register());  // Value.
-      __ Pop(a2, a1);  // a1 = key, a2 = receiver.
+      __ mov(KeyedStoreIC::ValueRegister(), result_register());
+      __ Pop(KeyedStoreIC::ReceiverRegister(), KeyedStoreIC::NameRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
diff --git a/src/mips64/ic-mips64.cc b/src/mips64/ic-mips64.cc
index d8f7173..bafd189 100644
--- a/src/mips64/ic-mips64.cc
+++ b/src/mips64/ic-mips64.cc
@@ -507,30 +507,31 @@
 
 
 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- lr     : return address
-  // -----------------------------------
+  Register receiver = ReceiverRegister();
+  Register key = NameRegister();
+  Register value = ValueRegister();
+  ASSERT(receiver.is(a2));
+  ASSERT(key.is(a1));
+  ASSERT(value.is(a0));
+
   Label slow, notin;
   // Store address is returned in register (of MemOperand) mapped_location.
-  MemOperand mapped_location =
-      GenerateMappedArgumentsLookup(masm, a2, a1, a3, a4, a5, &notin, &slow);
-  __ sd(a0, mapped_location);
-  __ mov(t1, a0);
+  MemOperand mapped_location = GenerateMappedArgumentsLookup(
+      masm, receiver, key, a3, a4, a5, &notin, &slow);
+  __ sd(value, mapped_location);
+  __ mov(t1, value);
   ASSERT_EQ(mapped_location.offset(), 0);
   __ RecordWrite(a3, mapped_location.rm(), t1,
                  kRAHasNotBeenSaved, kDontSaveFPRegs);
   __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a0);  // (In delay slot) return the value stored in v0.
+  __ mov(v0, value);  // (In delay slot) return the value stored in v0.
   __ bind(&notin);
   // The unmapped lookup expects that the parameter map is in a3.
   // Store address is returned in register (of MemOperand) unmapped_location.
   MemOperand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, a1, a3, a4, &slow);
-  __ sd(a0, unmapped_location);
-  __ mov(t1, a0);
+      GenerateUnmappedArgumentsLookup(masm, key, a3, a4, &slow);
+  __ sd(value, unmapped_location);
+  __ mov(t1, value);
   ASSERT_EQ(unmapped_location.offset(), 0);
   __ RecordWrite(a3, unmapped_location.rm(), t1,
                  kRAHasNotBeenSaved, kDontSaveFPRegs);
@@ -562,6 +563,16 @@
 const Register LoadIC::NameRegister() { return a2; }
 
 
+const Register StoreIC::ReceiverRegister() { return a1; }
+const Register StoreIC::NameRegister() { return a2; }
+const Register StoreIC::ValueRegister() { return a0; }
+
+
+const Register KeyedStoreIC::ReceiverRegister() { return a2; }
+const Register KeyedStoreIC::NameRegister() { return a1; }
+const Register KeyedStoreIC::ValueRegister() { return a0; }
+
+
 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   // The return address is in ra.
 
@@ -779,15 +790,9 @@
 
 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                               StrictMode strict_mode) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- ra     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(a2, a1, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
+
   __ li(a0, Operand(Smi::FromInt(strict_mode)));   // Strict mode.
   __ Push(a0);
 
@@ -984,9 +989,12 @@
   Label array, extra, check_if_double_array;
 
   // Register usage.
-  Register value = a0;
-  Register key = a1;
-  Register receiver = a2;
+  Register value = ValueRegister();
+  Register key = NameRegister();
+  Register receiver = ReceiverRegister();
+  ASSERT(receiver.is(a2));
+  ASSERT(key.is(a1));
+  ASSERT(value.is(a0));
   Register receiver_map = a3;
   Register elements_map = a6;
   Register elements = a7;  // Elements array of the receiver.
@@ -1105,15 +1113,8 @@
 
 
 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- ra     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(a2, a1, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   ExternalReference ref =
       ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
@@ -1122,15 +1123,8 @@
 
 
 void StoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a2     : key
-  //  -- a1     : receiver
-  //  -- ra     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
-  __ Push(a1, a2, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   // The slow case calls into the runtime to complete the store without causing
   // an IC miss that would otherwise cause a transition to the generic stub.
@@ -1141,16 +1135,9 @@
 
 
 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- a0     : value
-  //  -- a1     : key
-  //  -- a2     : receiver
-  //  -- ra     : return address
-  // -----------------------------------
-
   // Push receiver, key and value for runtime call.
   // We can't use MultiPush as the order of the registers is important.
-  __ Push(a2, a1, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
   // The slow case calls into the runtime to complete the store without causing
   // an IC miss that would otherwise cause a transition to the generic stub.
   ExternalReference ref =
@@ -1161,17 +1148,16 @@
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  ASSERT(receiver.is(a1));
+  ASSERT(name.is(a2));
+  ASSERT(ValueRegister().is(a0));
 
   // Get the receiver from the stack and probe the stub cache.
   Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
-      masm, flags, a1, a2, a3, a4, a5, a6);
+      masm, flags, receiver, name, a3, a4, a5, a6);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -1179,14 +1165,7 @@
 
 
 void StoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
-
-  __ Push(a1, a2, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
   // Perform tail call to the entry.
   ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss),
                                             masm->isolate());
@@ -1195,17 +1174,17 @@
 
 
 void StoreIC::GenerateNormal(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
   Label miss;
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  Register value = ValueRegister();
+  ASSERT(receiver.is(a1));
+  ASSERT(name.is(a2));
+  ASSERT(value.is(a0));
 
-  GenerateNameDictionaryReceiverCheck(masm, a1, a3, a4, a5, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, receiver, a3, a4, a5, &miss);
 
-  GenerateDictionaryStore(masm, &miss, a3, a2, a0, a4, a5);
+  GenerateDictionaryStore(masm, &miss, a3, name, value, a4, a5);
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->store_normal_hit(), 1, a4, a5);
   __ Ret();
@@ -1218,14 +1197,7 @@
 
 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                          StrictMode strict_mode) {
-  // ----------- S t a t e -------------
-  //  -- a0    : value
-  //  -- a1    : receiver
-  //  -- a2    : name
-  //  -- ra    : return address
-  // -----------------------------------
-
-  __ Push(a1, a2, a0);
+  __ Push(ReceiverRegister(), NameRegister(), ValueRegister());
 
   __ li(a0, Operand(Smi::FromInt(strict_mode)));
   __ Push(a0);
diff --git a/src/mips64/lithium-codegen-mips64.cc b/src/mips64/lithium-codegen-mips64.cc
index bf856b4..1972f13 100644
--- a/src/mips64/lithium-codegen-mips64.cc
+++ b/src/mips64/lithium-codegen-mips64.cc
@@ -4189,11 +4189,10 @@
 
 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->object()).is(a1));
-  ASSERT(ToRegister(instr->value()).is(a0));
+  ASSERT(ToRegister(instr->object()).is(StoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->value()).is(StoreIC::ValueRegister()));
 
-  // Name is always in a2.
-  __ li(a2, Operand(instr->name()));
+  __ li(StoreIC::NameRegister(), Operand(instr->name()));
   Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -4454,9 +4453,9 @@
 
 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->object()).is(a2));
-  ASSERT(ToRegister(instr->key()).is(a1));
-  ASSERT(ToRegister(instr->value()).is(a0));
+  ASSERT(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister()));
+  ASSERT(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister()));
 
   Handle<Code> ic = (instr->strict_mode() == STRICT)
       ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
diff --git a/src/mips64/lithium-mips64.cc b/src/mips64/lithium-mips64.cc
index dd1c6ca..e90760d 100644
--- a/src/mips64/lithium-mips64.cc
+++ b/src/mips64/lithium-mips64.cc
@@ -2200,9 +2200,9 @@
 
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* obj = UseFixed(instr->object(), a2);
-  LOperand* key = UseFixed(instr->key(), a1);
-  LOperand* val = UseFixed(instr->value(), a0);
+  LOperand* obj = UseFixed(instr->object(), KeyedStoreIC::ReceiverRegister());
+  LOperand* key = UseFixed(instr->key(), KeyedStoreIC::NameRegister());
+  LOperand* val = UseFixed(instr->value(), KeyedStoreIC::ValueRegister());
 
   ASSERT(instr->object()->representation().IsTagged());
   ASSERT(instr->key()->representation().IsTagged());
@@ -2276,8 +2276,8 @@
 
 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
-  LOperand* obj = UseFixed(instr->object(), a1);
-  LOperand* val = UseFixed(instr->value(), a0);
+  LOperand* obj = UseFixed(instr->object(), StoreIC::ReceiverRegister());
+  LOperand* val = UseFixed(instr->value(), StoreIC::ValueRegister());
 
   LInstruction* result = new(zone()) LStoreNamedGeneric(context, obj, val);
   return MarkAsCall(result, instr);
diff --git a/src/mips64/stub-cache-mips64.cc b/src/mips64/stub-cache-mips64.cc
index 6c46321..2627049 100644
--- a/src/mips64/stub-cache-mips64.cc
+++ b/src/mips64/stub-cache-mips64.cc
@@ -1270,20 +1270,24 @@
 
 
 Register StoreStubCompiler::value() {
-  return a0;
+  return StoreIC::ValueRegister();
 }
 
 
 Register* StoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { a1, a2, a3, a4, a5 };
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  static Register registers[] = { receiver, name, a3, a4, a5 };
   return registers;
 }
 
 
 Register* KeyedStoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { a2, a1, a3, a4, a5 };
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  static Register registers[] = { receiver, name, a3, a4, a5 };
   return registers;
 }
 
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index 36c0376..57880e2 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -27,8 +27,8 @@
 class Compressor {
  public:
   virtual ~Compressor() {}
-  virtual bool Compress(i::Vector<char> input) = 0;
-  virtual i::Vector<char>* output() = 0;
+  virtual bool Compress(i::Vector<i::byte> input) = 0;
+  virtual i::Vector<i::byte>* output() = 0;
 };
 
 
@@ -63,9 +63,9 @@
       startup_blob_file_ = GetFileDescriptorOrDie(startup_blob_file);
   }
 
-  void WriteSnapshot(const i::List<char>& snapshot_data,
+  void WriteSnapshot(const i::List<i::byte>& snapshot_data,
                      const i::Serializer& serializer,
-                     const i::List<char>& context_snapshot_data,
+                     const i::List<i::byte>& context_snapshot_data,
                      const i::Serializer& context_serializer) const {
     WriteSnapshotFile(snapshot_data, serializer,
                       context_snapshot_data, context_serializer);
@@ -74,14 +74,14 @@
   }
 
  private:
-  void MaybeWriteStartupBlob(const i::List<char>& snapshot_data,
+  void MaybeWriteStartupBlob(const i::List<i::byte>& snapshot_data,
                              const i::Serializer& serializer,
-                             const i::List<char>& context_snapshot_data,
+                             const i::List<i::byte>& context_snapshot_data,
                              const i::Serializer& context_serializer) const {
     if (!startup_blob_file_)
       return;
 
-    i::List<char> startup_blob;
+    i::List<i::byte> startup_blob;
     i::ListSnapshotSink sink(&startup_blob);
 
     int spaces[] = {
@@ -89,13 +89,12 @@
         i::MAP_SPACE, i::CELL_SPACE,  i::PROPERTY_CELL_SPACE
     };
 
-    i::byte* snapshot_bytes = reinterpret_cast<i::byte*>(snapshot_data.begin());
+    i::byte* snapshot_bytes = snapshot_data.begin();
     sink.PutBlob(snapshot_bytes, snapshot_data.length(), "snapshot");
     for (size_t i = 0; i < ARRAY_SIZE(spaces); ++i)
       sink.PutInt(serializer.CurrentAllocationAddress(spaces[i]), "spaces");
 
-    i::byte* context_bytes =
-        reinterpret_cast<i::byte*>(context_snapshot_data.begin());
+    i::byte* context_bytes = context_snapshot_data.begin();
     sink.PutBlob(context_bytes, context_snapshot_data.length(), "context");
     for (size_t i = 0; i < ARRAY_SIZE(spaces); ++i)
       sink.PutInt(context_serializer.CurrentAllocationAddress(spaces[i]),
@@ -109,9 +108,9 @@
     }
   }
 
-  void WriteSnapshotFile(const i::List<char>& snapshot_data,
+  void WriteSnapshotFile(const i::List<i::byte>& snapshot_data,
                          const i::Serializer& serializer,
-                         const i::List<char>& context_snapshot_data,
+                         const i::List<i::byte>& context_snapshot_data,
                          const i::Serializer& context_serializer) const {
     WriteFilePrefix();
     WriteData("", snapshot_data, raw_file_);
@@ -135,11 +134,10 @@
     fprintf(fp_, "}  // namespace v8\n");
   }
 
-  void WriteData(const char* prefix,
-                 const i::List<char>& source_data,
+  void WriteData(const char* prefix, const i::List<i::byte>& source_data,
                  FILE* raw_file) const {
-    const i::List <char>* data_to_be_written = NULL;
-    i::List<char> compressed_data;
+    const i::List<i::byte>* data_to_be_written = NULL;
+    i::List<i::byte> compressed_data;
     if (!compressor_) {
       data_to_be_written = &source_data;
     } else if (compressor_->Compress(source_data.ToVector())) {
@@ -155,7 +153,7 @@
     WriteData(prefix, source_data, data_to_be_written);
   }
 
-  void MaybeWriteRawFile(const i::List<char>* data, FILE* raw_file) const {
+  void MaybeWriteRawFile(const i::List<i::byte>* data, FILE* raw_file) const {
     if (!data || !raw_file)
       return;
 
@@ -170,9 +168,8 @@
     }
   }
 
-  void WriteData(const char* prefix,
-                 const i::List<char>& source_data,
-                 const i::List<char>* data_to_be_written) const {
+  void WriteData(const char* prefix, const i::List<i::byte>& source_data,
+                 const i::List<i::byte>* data_to_be_written) const {
     fprintf(fp_, "const byte Snapshot::%sdata_[] = {\n", prefix);
     WriteSnapshotData(data_to_be_written);
     fprintf(fp_, "};\n");
@@ -209,7 +206,7 @@
             prefix, name, ser.CurrentAllocationAddress(space));
   }
 
-  void WriteSnapshotData(const i::List<char>* data) const {
+  void WriteSnapshotData(const i::List<i::byte>* data) const {
     for (int i = 0; i < data->length(); i++) {
       if ((i & 0x1f) == 0x1f)
         fprintf(fp_, "\n");
@@ -405,12 +402,12 @@
 
     // This results in a somewhat smaller snapshot, probably because it gets
     // rid of some things that are cached between garbage collections.
-    i::List<char> snapshot_data;
+    i::List<i::byte> snapshot_data;
     i::ListSnapshotSink snapshot_sink(&snapshot_data);
     i::StartupSerializer ser(internal_isolate, &snapshot_sink);
     ser.SerializeStrongReferences();
 
-    i::List<char> context_data;
+    i::List<i::byte> context_data;
     i::ListSnapshotSink contex_sink(&context_data);
     i::PartialSerializer context_ser(internal_isolate, &ser, &contex_sink);
     context_ser.Serialize(&raw_context);
diff --git a/src/objects-inl.h b/src/objects-inl.h
index b841ee6..7fa2a0e 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1480,22 +1480,6 @@
 }
 
 
-bool HeapObject::ContainsPointers() {
-  InstanceType type = map()->instance_type();
-  if (type <= LAST_NAME_TYPE) {
-    if (type == SYMBOL_TYPE) {
-      return true;
-    }
-    ASSERT(type < FIRST_NONSTRING_TYPE);
-    // There are four string representations: sequential strings, external
-    // strings, cons strings, and sliced strings.
-    // Only the latter two contain non-map-word pointers to heap objects.
-    return ((type & kIsIndirectStringMask) == kIsIndirectStringTag);
-  }
-  return (type > LAST_DATA_TYPE);
-}
-
-
 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
   v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
                    reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
@@ -6032,8 +6016,7 @@
 }
 
 
-ACCESSORS(JSSet, table, Object, kTableOffset)
-ACCESSORS(JSMap, table, Object, kTableOffset)
+ACCESSORS(JSCollection, table, Object, kTableOffset)
 
 
 #define ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(name, type, offset)    \
diff --git a/src/objects.cc b/src/objects.cc
index 702d8a2..ad066af 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2339,17 +2339,22 @@
 
   // Unless the instance is being migrated, ensure that modify_index is a field.
   PropertyDetails details = descriptors->GetDetails(modify_index);
-  if (store_mode == FORCE_FIELD && details.type() != FIELD) {
+  if (store_mode == FORCE_FIELD &&
+      (details.type() != FIELD || details.attributes() != attributes)) {
+    int field_index = details.type() == FIELD ? details.field_index()
+                                              : new_map->NumberOfFields();
     FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
-                      new_map->NumberOfFields(),
-                      attributes,
-                      Representation::Tagged());
+                      field_index, attributes, Representation::Tagged());
     descriptors->Replace(modify_index, &d);
-    int unused_property_fields = new_map->unused_property_fields() - 1;
-    if (unused_property_fields < 0) {
-      unused_property_fields += JSObject::kFieldsAdded;
+    if (details.type() != FIELD) {
+      int unused_property_fields = new_map->unused_property_fields() - 1;
+      if (unused_property_fields < 0) {
+        unused_property_fields += JSObject::kFieldsAdded;
+      }
+      new_map->set_unused_property_fields(unused_property_fields);
     }
-    new_map->set_unused_property_fields(unused_property_fields);
+  } else {
+    ASSERT(details.attributes() == attributes);
   }
 
   if (FLAG_trace_generalization) {
diff --git a/src/objects.h b/src/objects.h
index 007d4c1..af8cc28 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -44,8 +44,9 @@
 //         - JSArrayBufferView
 //           - JSTypedArray
 //           - JSDataView
-//         - JSSet
-//         - JSMap
+//         - JSCollection
+//           - JSSet
+//           - JSMap
 //         - JSSetIterator
 //         - JSMapIterator
 //         - JSWeakCollection
@@ -716,7 +717,6 @@
   FIXED_UINT8_CLAMPED_ARRAY_TYPE,  // LAST_FIXED_TYPED_ARRAY_TYPE
 
   FIXED_DOUBLE_ARRAY_TYPE,
-  CONSTANT_POOL_ARRAY_TYPE,
   FILLER_TYPE,  // LAST_DATA_TYPE
 
   // Structs.
@@ -743,6 +743,7 @@
   BREAK_POINT_INFO_TYPE,
 
   FIXED_ARRAY_TYPE,
+  CONSTANT_POOL_ARRAY_TYPE,
   SHARED_FUNCTION_INFO_TYPE,
 
   // All the following types are subtypes of JSReceiver, which corresponds to
@@ -1718,10 +1719,6 @@
   // Returns the heap object's size in bytes
   inline int Size();
 
-  // Returns true if this heap object contains only references to other
-  // heap objects.
-  inline bool ContainsPointers();
-
   // Given a heap object's map pointer, returns the heap size in bytes
   // Useful when the map pointer field is used for other purposes.
   // GC internal.
@@ -10078,41 +10075,42 @@
 };
 
 
-// The JSSet describes EcmaScript Harmony sets
-class JSSet: public JSObject {
+class JSCollection : public JSObject {
  public:
-  // [set]: the backing hash set containing keys.
+  // [table]: the backing hash table
   DECL_ACCESSORS(table, Object)
 
+  static const int kTableOffset = JSObject::kHeaderSize;
+  static const int kSize = kTableOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(JSCollection);
+};
+
+
+// The JSSet describes EcmaScript Harmony sets
+class JSSet : public JSCollection {
+ public:
   DECLARE_CAST(JSSet)
 
   // Dispatched behavior.
   DECLARE_PRINTER(JSSet)
   DECLARE_VERIFIER(JSSet)
 
-  static const int kTableOffset = JSObject::kHeaderSize;
-  static const int kSize = kTableOffset + kPointerSize;
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSSet);
 };
 
 
 // The JSMap describes EcmaScript Harmony maps
-class JSMap: public JSObject {
+class JSMap : public JSCollection {
  public:
-  // [table]: the backing hash table mapping keys to values.
-  DECL_ACCESSORS(table, Object)
-
   DECLARE_CAST(JSMap)
 
   // Dispatched behavior.
   DECLARE_PRINTER(JSMap)
   DECLARE_VERIFIER(JSMap)
 
-  static const int kTableOffset = JSObject::kHeaderSize;
-  static const int kSize = kTableOffset + kPointerSize;
-
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap);
 };
diff --git a/src/parser.cc b/src/parser.cc
index 544c8c7..3542b4c 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -182,147 +182,86 @@
 }
 
 
-ScriptData* ScriptData::New(const char* data, int length, bool owns_store) {
-  // The length is obviously invalid.
-  if (length % sizeof(unsigned) != 0) {
-    return NULL;
-  }
-
-  int deserialized_data_length = length / sizeof(unsigned);
-  unsigned* deserialized_data;
-  owns_store =
-      owns_store || reinterpret_cast<intptr_t>(data) % sizeof(unsigned) != 0;
-  if (owns_store) {
-    // Copy the data to align it.
-    deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
-    i::CopyBytes(reinterpret_cast<char*>(deserialized_data),
-                 data, static_cast<size_t>(length));
-  } else {
-    // If aligned, don't create a copy of the data.
-    deserialized_data = reinterpret_cast<unsigned*>(const_cast<char*>(data));
-  }
-  return new ScriptData(
-      Vector<unsigned>(deserialized_data, deserialized_data_length),
-      owns_store);
-}
-
-
-FunctionEntry ScriptData::GetFunctionEntry(int start) {
+FunctionEntry ParseData::GetFunctionEntry(int start) {
   // The current pre-data entry must be a FunctionEntry with the given
   // start position.
-  if ((function_index_ + FunctionEntry::kSize <= store_.length())
-      && (static_cast<int>(store_[function_index_]) == start)) {
+  if ((function_index_ + FunctionEntry::kSize <= Length()) &&
+      (static_cast<int>(Data()[function_index_]) == start)) {
     int index = function_index_;
     function_index_ += FunctionEntry::kSize;
-    return FunctionEntry(store_.SubVector(index,
-                                          index + FunctionEntry::kSize));
+    Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
+    return FunctionEntry(subvector);
   }
   return FunctionEntry();
 }
 
 
-int ScriptData::GetSymbolIdentifier() {
-  return ReadNumber(&symbol_data_);
+int ParseData::FunctionCount() {
+  int functions_size = FunctionsSize();
+  if (functions_size < 0) return 0;
+  if (functions_size % FunctionEntry::kSize != 0) return 0;
+  return functions_size / FunctionEntry::kSize;
 }
 
 
-bool ScriptData::SanityCheck() {
+bool ParseData::IsSane() {
   // Check that the header data is valid and doesn't specify
   // point to positions outside the store.
-  if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
-  if (magic() != PreparseDataConstants::kMagicNumber) return false;
-  if (version() != PreparseDataConstants::kCurrentVersion) return false;
-  if (has_error()) {
-    // Extra sane sanity check for error message encoding.
-    if (store_.length() <= PreparseDataConstants::kHeaderSize
-                         + PreparseDataConstants::kMessageTextPos) {
-      return false;
-    }
-    if (Read(PreparseDataConstants::kMessageStartPos) >
-        Read(PreparseDataConstants::kMessageEndPos)) {
-      return false;
-    }
-    unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
-    int pos = PreparseDataConstants::kMessageTextPos;
-    for (unsigned int i = 0; i <= arg_count; i++) {
-      if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
-        return false;
-      }
-      int length = static_cast<int>(Read(pos));
-      if (length < 0) return false;
-      pos += 1 + length;
-    }
-    if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
-      return false;
-    }
-    return true;
-  }
+  int data_length = Length();
+  if (data_length < PreparseDataConstants::kHeaderSize) return false;
+  if (Magic() != PreparseDataConstants::kMagicNumber) return false;
+  if (Version() != PreparseDataConstants::kCurrentVersion) return false;
+  if (HasError()) return false;
   // Check that the space allocated for function entries is sane.
-  int functions_size =
-      static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
+  int functions_size = FunctionsSize();
   if (functions_size < 0) return false;
   if (functions_size % FunctionEntry::kSize != 0) return false;
   // Check that the total size has room for header and function entries.
   int minimum_size =
       PreparseDataConstants::kHeaderSize + functions_size;
-  if (store_.length() < minimum_size) return false;
+  if (data_length < minimum_size) return false;
   return true;
 }
 
 
-
-const char* ScriptData::ReadString(unsigned* start, int* chars) {
-  int length = start[0];
-  char* result = NewArray<char>(length + 1);
-  for (int i = 0; i < length; i++) {
-    result[i] = start[i + 1];
+void ParseData::Initialize() {
+  // Prepares state for use.
+  int data_length = Length();
+  if (data_length >= PreparseDataConstants::kHeaderSize) {
+    function_index_ = PreparseDataConstants::kHeaderSize;
   }
-  result[length] = '\0';
-  if (chars != NULL) *chars = length;
-  return result;
 }
 
 
-Scanner::Location ScriptData::MessageLocation() const {
-  int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
-  int end_pos = Read(PreparseDataConstants::kMessageEndPos);
-  return Scanner::Location(beg_pos, end_pos);
+bool ParseData::HasError() {
+  return Data()[PreparseDataConstants::kHasErrorOffset];
 }
 
 
-bool ScriptData::IsReferenceError() const {
-  return Read(PreparseDataConstants::kIsReferenceErrorPos);
+unsigned ParseData::Magic() {
+  return Data()[PreparseDataConstants::kMagicOffset];
 }
 
 
-const char* ScriptData::BuildMessage() const {
-  unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
-  return ReadString(start, NULL);
+unsigned ParseData::Version() {
+  return Data()[PreparseDataConstants::kVersionOffset];
 }
 
 
-const char* ScriptData::BuildArg() const {
-  int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
-  ASSERT(arg_count == 0 || arg_count == 1);
-  if (arg_count == 0) {
-    return NULL;
+int ParseData::FunctionsSize() {
+  return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
+}
+
+
+void Parser::SetCachedData() {
+  if (cached_data_mode() == NO_CACHED_DATA) {
+    cached_parse_data_ = NULL;
+  } else {
+    ASSERT(info_->cached_data() != NULL);
+    if (cached_data_mode() == CONSUME_CACHED_DATA) {
+      cached_parse_data_ = new ParseData(*info_->cached_data());
+    }
   }
-  // Position after text found by skipping past length field and
-  // length field content words.
-  int pos = PreparseDataConstants::kMessageTextPos + 1
-      + Read(PreparseDataConstants::kMessageTextPos);
-  int count = 0;
-  return ReadString(ReadAddress(pos), &count);
-}
-
-
-unsigned ScriptData::Read(int position) const {
-  return store_[PreparseDataConstants::kHeaderSize + position];
-}
-
-
-unsigned* ScriptData::ReadAddress(int position) const {
-  return &store_[PreparseDataConstants::kHeaderSize + position];
 }
 
 
@@ -757,18 +696,14 @@
 Parser::Parser(CompilationInfo* info)
     : ParserBase<ParserTraits>(&scanner_,
                                info->isolate()->stack_guard()->real_climit(),
-                               info->extension(),
-                               NULL,
-                               info->zone(),
-                               this),
+                               info->extension(), NULL, info->zone(), this),
       isolate_(info->isolate()),
       script_(info->script()),
       scanner_(isolate_->unicode_cache()),
       reusable_preparser_(NULL),
       original_scope_(NULL),
       target_stack_(NULL),
-      cached_data_(NULL),
-      cached_data_mode_(NO_CACHED_DATA),
+      cached_parse_data_(NULL),
       ast_value_factory_(NULL),
       info_(info),
       has_pending_error_(false),
@@ -805,10 +740,10 @@
 
   // Initialize parser state.
   CompleteParserRecorder recorder;
-  if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
+  if (cached_data_mode() == PRODUCE_CACHED_DATA) {
     log_ = &recorder;
-  } else if (cached_data_mode_ == CONSUME_CACHED_DATA) {
-    (*cached_data_)->Initialize();
+  } else if (cached_data_mode() == CONSUME_CACHED_DATA) {
+    cached_parse_data_->Initialize();
   }
 
   source = String::Flatten(source);
@@ -840,11 +775,8 @@
     }
     PrintF(" - took %0.3f ms]\n", ms);
   }
-  if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
-    if (result != NULL) {
-      Vector<unsigned> store = recorder.ExtractData();
-      *cached_data_ = new ScriptData(store);
-    }
+  if (cached_data_mode() == PRODUCE_CACHED_DATA) {
+    if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
     log_ = NULL;
   }
   return result;
@@ -1158,13 +1090,18 @@
   switch (peek()) {
     case Token::FUNCTION:
       return ParseFunctionDeclaration(NULL, ok);
-    case Token::LET:
-    case Token::CONST:
-      return ParseVariableStatement(kModuleElement, NULL, ok);
     case Token::IMPORT:
       return ParseImportDeclaration(ok);
     case Token::EXPORT:
       return ParseExportDeclaration(ok);
+    case Token::CONST:
+      return ParseVariableStatement(kModuleElement, NULL, ok);
+    case Token::LET:
+      ASSERT(allow_harmony_scoping());
+      if (strict_mode() == STRICT) {
+        return ParseVariableStatement(kModuleElement, NULL, ok);
+      }
+      // Fall through.
     default: {
       Statement* stmt = ParseStatement(labels, CHECK_OK);
       // Handle 'module' as a context-sensitive keyword.
@@ -1545,9 +1482,14 @@
   switch (peek()) {
     case Token::FUNCTION:
       return ParseFunctionDeclaration(NULL, ok);
-    case Token::LET:
     case Token::CONST:
       return ParseVariableStatement(kModuleElement, NULL, ok);
+    case Token::LET:
+      ASSERT(allow_harmony_scoping());
+      if (strict_mode() == STRICT) {
+        return ParseVariableStatement(kModuleElement, NULL, ok);
+      }
+      // Fall through.
     default:
       return ParseStatement(labels, ok);
   }
@@ -1583,11 +1525,6 @@
     case Token::LBRACE:
       return ParseBlock(labels, ok);
 
-    case Token::CONST:  // fall through
-    case Token::LET:
-    case Token::VAR:
-      return ParseVariableStatement(kStatement, NULL, ok);
-
     case Token::SEMICOLON:
       Next();
       return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
@@ -1659,6 +1596,16 @@
     case Token::DEBUGGER:
       return ParseDebuggerStatement(ok);
 
+    case Token::VAR:
+    case Token::CONST:
+      return ParseVariableStatement(kStatement, NULL, ok);
+
+    case Token::LET:
+      ASSERT(allow_harmony_scoping());
+      if (strict_mode() == STRICT) {
+        return ParseVariableStatement(kStatement, NULL, ok);
+      }
+      // Fall through.
     default:
       return ParseExpressionOrLabelledStatement(labels, ok);
   }
@@ -2062,20 +2009,8 @@
     }
     is_const = true;
     needs_init = true;
-  } else if (peek() == Token::LET) {
-    // ES6 Draft Rev4 section 12.2.1:
-    //
-    // LetDeclaration : let LetBindingList ;
-    //
-    // * It is a Syntax Error if the code that matches this production is not
-    //   contained in extended code.
-    //
-    // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
-    if (!allow_harmony_scoping() || strict_mode() == SLOPPY) {
-      ReportMessage("illegal_let");
-      *ok = false;
-      return NULL;
-    }
+  } else if (peek() == Token::LET && strict_mode() == STRICT) {
+    ASSERT(allow_harmony_scoping());
     Consume(Token::LET);
     if (var_context == kStatement) {
       // Let declarations are only allowed in source element positions.
@@ -3114,7 +3049,8 @@
       } else {
         init = variable_statement;
       }
-    } else if (peek() == Token::LET) {
+    } else if (peek() == Token::LET && strict_mode() == STRICT) {
+      ASSERT(allow_harmony_scoping());
       const AstRawString* name = NULL;
       VariableDeclarationProperties decl_props = kHasNoInitializers;
       Block* variable_statement =
@@ -3292,12 +3228,6 @@
 }
 
 
-void Parser::ReportInvalidCachedData(const AstRawString* name, bool* ok) {
-  ParserTraits::ReportMessage("invalid_cached_data_function", name);
-  *ok = false;
-}
-
-
 bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
   if (expression->IsLiteral()) return true;
   MaterializedLiteral* lit = expression->AsMaterializedLiteral();
@@ -3500,8 +3430,8 @@
         fvar_init_op = Token::INIT_CONST;
       }
       VariableMode fvar_mode =
-          allow_harmony_scoping() && strict_mode() == STRICT ? CONST
-                                                             : CONST_LEGACY;
+          allow_harmony_scoping() && strict_mode() == STRICT
+              ? CONST : CONST_LEGACY;
       ASSERT(function_name != NULL);
       fvar = new(zone()) Variable(scope_,
          function_name, fvar_mode, true /* is valid LHS */,
@@ -3614,37 +3544,27 @@
                                   int* expected_property_count,
                                   bool* ok) {
   int function_block_pos = position();
-  if (cached_data_mode_ == CONSUME_CACHED_DATA) {
+  if (cached_data_mode() == CONSUME_CACHED_DATA) {
     // If we have cached data, we use it to skip parsing the function body. The
     // data contains the information we need to construct the lazy function.
     FunctionEntry entry =
-        (*cached_data())->GetFunctionEntry(function_block_pos);
-    if (entry.is_valid()) {
-      if (entry.end_pos() <= function_block_pos) {
-        // End position greater than end of stream is safe, and hard to check.
-        ReportInvalidCachedData(function_name, ok);
-        if (!*ok) {
-          return;
-        }
-      }
-      scanner()->SeekForward(entry.end_pos() - 1);
+        cached_parse_data_->GetFunctionEntry(function_block_pos);
+    // Check that cached data is valid.
+    CHECK(entry.is_valid());
+    // End position greater than end of stream is safe, and hard to check.
+    CHECK(entry.end_pos() > function_block_pos);
+    scanner()->SeekForward(entry.end_pos() - 1);
 
-      scope_->set_end_position(entry.end_pos());
-      Expect(Token::RBRACE, ok);
-      if (!*ok) {
-        return;
-      }
-      isolate()->counters()->total_preparse_skipped()->Increment(
-          scope_->end_position() - function_block_pos);
-      *materialized_literal_count = entry.literal_count();
-      *expected_property_count = entry.property_count();
-      scope_->SetStrictMode(entry.strict_mode());
-    } else {
-      // This case happens when we have preparse data but it doesn't contain an
-      // entry for the function. Fail the compilation.
-      ReportInvalidCachedData(function_name, ok);
+    scope_->set_end_position(entry.end_pos());
+    Expect(Token::RBRACE, ok);
+    if (!*ok) {
       return;
     }
+    isolate()->counters()->total_preparse_skipped()->Increment(
+        scope_->end_position() - function_block_pos);
+    *materialized_literal_count = entry.literal_count();
+    *expected_property_count = entry.property_count();
+    scope_->SetStrictMode(entry.strict_mode());
   } else {
     // With no cached data, we partially parse the function, without building an
     // AST. This gathers the data needed to build a lazy function.
@@ -3674,7 +3594,7 @@
     *materialized_literal_count = logger.literals();
     *expected_property_count = logger.properties();
     scope_->SetStrictMode(logger.strict_mode());
-    if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
+    if (cached_data_mode() == PRODUCE_CACHED_DATA) {
       ASSERT(log_);
       // Position right after terminal '}'.
       int body_end = scanner()->location().end_pos;
@@ -4766,70 +4686,6 @@
 // ----------------------------------------------------------------------------
 // The Parser interface.
 
-ScriptData::~ScriptData() {
-  if (owns_store_) store_.Dispose();
-}
-
-
-int ScriptData::Length() {
-  return store_.length() * sizeof(unsigned);
-}
-
-
-const char* ScriptData::Data() {
-  return reinterpret_cast<const char*>(store_.start());
-}
-
-
-bool ScriptData::HasError() {
-  return has_error();
-}
-
-
-void ScriptData::Initialize() {
-  // Prepares state for use.
-  if (store_.length() >= PreparseDataConstants::kHeaderSize) {
-    function_index_ = PreparseDataConstants::kHeaderSize;
-    int symbol_data_offset = PreparseDataConstants::kHeaderSize
-        + store_[PreparseDataConstants::kFunctionsSizeOffset];
-    if (store_.length() > symbol_data_offset) {
-      symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
-    } else {
-      // Partial preparse causes no symbol information.
-      symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
-    }
-    symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
-  }
-}
-
-
-int ScriptData::ReadNumber(byte** source) {
-  // Reads a number from symbol_data_ in base 128. The most significant
-  // bit marks that there are more digits.
-  // If the first byte is 0x80 (kNumberTerminator), it would normally
-  // represent a leading zero. Since that is useless, and therefore won't
-  // appear as the first digit of any actual value, it is used to
-  // mark the end of the input stream.
-  byte* data = *source;
-  if (data >= symbol_data_end_) return -1;
-  byte input = *data;
-  if (input == PreparseDataConstants::kNumberTerminator) {
-    // End of stream marker.
-    return -1;
-  }
-  int result = input & 0x7f;
-  data++;
-  while ((input & 0x80u) != 0) {
-    if (data >= symbol_data_end_) return -1;
-    input = *data;
-    result = (result << 7) | (input & 0x7f);
-    data++;
-  }
-  *source = data;
-  return result;
-}
-
-
 bool RegExpParser::ParseRegExp(FlatStringReader* input,
                                bool multiline,
                                RegExpCompileData* result,
@@ -4876,7 +4732,7 @@
       result = ParseProgram();
     }
   } else {
-    SetCachedData(info()->cached_data(), info()->cached_data_mode());
+    SetCachedData();
     result = ParseProgram();
   }
   info()->SetFunction(result);
diff --git a/src/parser.h b/src/parser.h
index ac27664..d0b67b7 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -59,73 +59,39 @@
 };
 
 
-class ScriptData {
+// Wrapper around ScriptData to provide parser-specific functionality.
+class ParseData {
  public:
-  explicit ScriptData(Vector<unsigned> store)
-      : store_(store),
-        owns_store_(true) { }
-
-  ScriptData(Vector<unsigned> store, bool owns_store)
-      : store_(store),
-        owns_store_(owns_store) { }
-
-  // The created ScriptData won't take ownership of the data. If the alignment
-  // is not correct, this will copy the data (and the created ScriptData will
-  // take ownership of the copy).
-  static ScriptData* New(const char* data, int length, bool owns_store = false);
-
-  virtual ~ScriptData();
-  virtual int Length();
-  virtual const char* Data();
-  virtual bool HasError();
-
-  void Initialize();
-  void ReadNextSymbolPosition();
-
-  FunctionEntry GetFunctionEntry(int start);
-  int GetSymbolIdentifier();
-  bool SanityCheck();
-
-  Scanner::Location MessageLocation() const;
-  bool IsReferenceError() const;
-  const char* BuildMessage() const;
-  const char* BuildArg() const;
-
-  int function_count() {
-    int functions_size =
-        static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
-    if (functions_size < 0) return 0;
-    if (functions_size % FunctionEntry::kSize != 0) return 0;
-    return functions_size / FunctionEntry::kSize;
+  explicit ParseData(ScriptData* script_data) : script_data_(script_data) {
+    CHECK(IsAligned(script_data->length(), sizeof(unsigned)));
+    CHECK(IsSane());
   }
-  // The following functions should only be called if SanityCheck has
-  // returned true.
-  bool has_error() { return store_[PreparseDataConstants::kHasErrorOffset]; }
-  unsigned magic() { return store_[PreparseDataConstants::kMagicOffset]; }
-  unsigned version() { return store_[PreparseDataConstants::kVersionOffset]; }
+  void Initialize();
+  FunctionEntry GetFunctionEntry(int start);
+  int FunctionCount();
+
+  bool HasError();
+
+  unsigned* Data() {  // Writable data as unsigned int array.
+    return reinterpret_cast<unsigned*>(const_cast<byte*>(script_data_->data()));
+  }
 
  private:
-  // Disable copying and assigning; because of owns_store they won't be correct.
-  ScriptData(const ScriptData&);
-  ScriptData& operator=(const ScriptData&);
+  bool IsSane();
+  unsigned Magic();
+  unsigned Version();
+  int FunctionsSize();
+  int Length() const {
+    // Script data length is already checked to be a multiple of unsigned size.
+    return script_data_->length() / sizeof(unsigned);
+  }
 
-  friend class v8::ScriptCompiler;
-  Vector<unsigned> store_;
-  unsigned char* symbol_data_;
-  unsigned char* symbol_data_end_;
+  ScriptData* script_data_;
   int function_index_;
-  bool owns_store_;
 
-  unsigned Read(int position) const;
-  unsigned* ReadAddress(int position) const;
-  // Reads a number from the current symbols
-  int ReadNumber(byte** source);
-
-  // Read strings written by ParserRecorder::WriteString.
-  static const char* ReadString(unsigned* start, int* chars);
+  DISALLOW_COPY_AND_ASSIGN(ParseData);
 };
 
-
 // ----------------------------------------------------------------------------
 // REGEXP PARSING
 
@@ -595,6 +561,8 @@
   ~Parser() {
     delete reusable_preparser_;
     reusable_preparser_ = NULL;
+    delete cached_parse_data_;
+    cached_parse_data_ = NULL;
   }
 
   // Parses the source code represented by the compilation info and sets its
@@ -646,23 +614,10 @@
   FunctionLiteral* DoParseProgram(CompilationInfo* info,
                                   Handle<String> source);
 
-  // Report syntax error
-  void ReportInvalidCachedData(const AstRawString* name, bool* ok);
-
-  void SetCachedData(ScriptData** data,
-                     CachedDataMode cached_data_mode) {
-    cached_data_mode_ = cached_data_mode;
-    if (cached_data_mode == NO_CACHED_DATA) {
-      cached_data_ = NULL;
-    } else {
-      ASSERT(data != NULL);
-      cached_data_ = data;
-    }
-  }
+  void SetCachedData();
 
   bool inside_with() const { return scope_->inside_with(); }
-  ScriptData** cached_data() const { return cached_data_; }
-  CachedDataMode cached_data_mode() const { return cached_data_mode_; }
+  CachedDataMode cached_data_mode() const { return info_->cached_data_mode(); }
   Scope* DeclarationScope(VariableMode mode) {
     return IsLexicalVariableMode(mode)
         ? scope_ : scope_->DeclarationScope();
@@ -809,7 +764,7 @@
   PreParser* reusable_preparser_;
   Scope* original_scope_;  // for ES5 function declarations in sloppy eval
   Target* target_stack_;  // for break, continue statements
-  ScriptData** cached_data_;
+  ParseData* cached_parse_data_;
   CachedDataMode cached_data_mode_;
   AstValueFactory* ast_value_factory_;
 
diff --git a/src/preparse-data.cc b/src/preparse-data.cc
index 50e9120..3dd02bd 100644
--- a/src/preparse-data.cc
+++ b/src/preparse-data.cc
@@ -4,6 +4,7 @@
 
 #include "include/v8stdint.h"
 #include "src/base/logging.h"
+#include "src/compiler.h"
 #include "src/globals.h"
 #include "src/hashmap.h"
 #include "src/preparse-data.h"
@@ -34,7 +35,7 @@
                                         const char* message,
                                         const char* arg_opt,
                                         bool is_reference_error) {
-  if (has_error()) return;
+  if (HasError()) return;
   preamble_[PreparseDataConstants::kHasErrorOffset] = true;
   function_store_.Reset();
   STATIC_ASSERT(PreparseDataConstants::kMessageStartPos == 0);
@@ -59,17 +60,21 @@
 }
 
 
-Vector<unsigned> CompleteParserRecorder::ExtractData() {
+ScriptData* CompleteParserRecorder::GetScriptData() {
   int function_size = function_store_.size();
   int total_size = PreparseDataConstants::kHeaderSize + function_size;
-  Vector<unsigned> data = Vector<unsigned>::New(total_size);
+  unsigned* data = NewArray<unsigned>(total_size);
   preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
-  MemCopy(data.start(), preamble_, sizeof(preamble_));
+  MemCopy(data, preamble_, sizeof(preamble_));
   if (function_size > 0) {
-    function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
-                                           total_size));
+    function_store_.WriteTo(Vector<unsigned>(
+        data + PreparseDataConstants::kHeaderSize, function_size));
   }
-  return data;
+  ASSERT(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment));
+  ScriptData* result = new ScriptData(reinterpret_cast<byte*>(data),
+                                      total_size * sizeof(unsigned));
+  result->AcquireDataOwnership();
+  return result;
 }
 
 
diff --git a/src/preparse-data.h b/src/preparse-data.h
index 36c481c..caae0ef 100644
--- a/src/preparse-data.h
+++ b/src/preparse-data.h
@@ -13,6 +13,8 @@
 namespace v8 {
 namespace internal {
 
+class ScriptData;
+
 
 // Abstract interface for preparse data recorder.
 class ParserRecorder {
@@ -149,13 +151,17 @@
                           const char* message,
                           const char* argument_opt,
                           bool is_reference_error_);
-  Vector<unsigned> ExtractData();
+  ScriptData* GetScriptData();
 
- private:
-  bool has_error() {
+  bool HasError() {
     return static_cast<bool>(preamble_[PreparseDataConstants::kHasErrorOffset]);
   }
+  Vector<unsigned> ErrorMessageData() {
+    ASSERT(HasError());
+    return function_store_.ToVector();
+  }
 
+ private:
   void WriteString(Vector<const char> str);
 
   // Write a non-negative number to the symbol store.
diff --git a/src/preparser.cc b/src/preparser.cc
index df9e48e..8c8746d 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -61,6 +61,8 @@
   } else if (scanner->current_token() ==
              Token::FUTURE_STRICT_RESERVED_WORD) {
     return PreParserIdentifier::FutureStrictReserved();
+  } else if (scanner->current_token() == Token::LET) {
+    return PreParserIdentifier::Let();
   } else if (scanner->current_token() == Token::YIELD) {
     return PreParserIdentifier::Yield();
   }
@@ -167,9 +169,14 @@
   switch (peek()) {
     case Token::FUNCTION:
       return ParseFunctionDeclaration(ok);
-    case Token::LET:
     case Token::CONST:
       return ParseVariableStatement(kSourceElement, ok);
+    case Token::LET:
+      ASSERT(allow_harmony_scoping());
+      if (strict_mode() == STRICT) {
+        return ParseVariableStatement(kSourceElement, ok);
+      }
+      // Fall through.
     default:
       return ParseStatement(ok);
   }
@@ -237,11 +244,6 @@
     case Token::LBRACE:
       return ParseBlock(ok);
 
-    case Token::CONST:
-    case Token::LET:
-    case Token::VAR:
-      return ParseVariableStatement(kStatement, ok);
-
     case Token::SEMICOLON:
       Next();
       return Statement::Default();
@@ -297,6 +299,16 @@
     case Token::DEBUGGER:
       return ParseDebuggerStatement(ok);
 
+    case Token::VAR:
+    case Token::CONST:
+      return ParseVariableStatement(kStatement, ok);
+
+    case Token::LET:
+      ASSERT(allow_harmony_scoping());
+      if (strict_mode() == STRICT) {
+        return ParseVariableStatement(kStatement, ok);
+      }
+      // Fall through.
     default:
       return ParseExpressionOrLabelledStatement(ok);
   }
@@ -415,23 +427,9 @@
         return Statement::Default();
       }
     }
-  } else if (peek() == Token::LET) {
-    // ES6 Draft Rev4 section 12.2.1:
-    //
-    // LetDeclaration : let LetBindingList ;
-    //
-    // * It is a Syntax Error if the code that matches this production is not
-    //   contained in extended code.
-    //
-    // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
-    if (!allow_harmony_scoping() || strict_mode() == SLOPPY) {
-      ReportMessageAt(scanner()->peek_location(), "illegal_let");
-      *ok = false;
-      return Statement::Default();
-    }
+  } else if (peek() == Token::LET && strict_mode() == STRICT) {
     Consume(Token::LET);
-    if (var_context != kSourceElement &&
-        var_context != kForStatement) {
+    if (var_context != kSourceElement && var_context != kForStatement) {
       ReportMessageAt(scanner()->peek_location(), "unprotected_let");
       *ok = false;
       return Statement::Default();
@@ -669,7 +667,7 @@
   Expect(Token::LPAREN, CHECK_OK);
   if (peek() != Token::SEMICOLON) {
     if (peek() == Token::VAR || peek() == Token::CONST ||
-        peek() == Token::LET) {
+        (peek() == Token::LET && strict_mode() == STRICT)) {
       bool is_let = peek() == Token::LET;
       int decl_count;
       VariableDeclarationProperties decl_props = kHasNoInitializers;
diff --git a/src/preparser.h b/src/preparser.h
index d143938..902d20a 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -301,6 +301,7 @@
     return next == Token::IDENTIFIER ||
         next == Token::FUTURE_RESERVED_WORD ||
         next == Token::FUTURE_STRICT_RESERVED_WORD ||
+        next == Token::LET ||
         next == Token::YIELD;
   }
 
@@ -548,6 +549,9 @@
   static PreParserIdentifier FutureStrictReserved() {
     return PreParserIdentifier(kFutureStrictReservedIdentifier);
   }
+  static PreParserIdentifier Let() {
+    return PreParserIdentifier(kLetIdentifier);
+  }
   static PreParserIdentifier Yield() {
     return PreParserIdentifier(kYieldIdentifier);
   }
@@ -566,6 +570,7 @@
     kUnknownIdentifier,
     kFutureReservedIdentifier,
     kFutureStrictReservedIdentifier,
+    kLetIdentifier,
     kYieldIdentifier,
     kEvalIdentifier,
     kArgumentsIdentifier
@@ -1271,6 +1276,7 @@
       return ReportMessageAt(source_location, "unexpected_token_identifier");
     case Token::FUTURE_RESERVED_WORD:
       return ReportMessageAt(source_location, "unexpected_reserved");
+    case Token::LET:
     case Token::YIELD:
     case Token::FUTURE_STRICT_RESERVED_WORD:
       return ReportMessageAt(source_location, strict_mode() == SLOPPY
@@ -1298,6 +1304,7 @@
     return name;
   } else if (strict_mode() == SLOPPY &&
              (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+             (next == Token::LET) ||
              (next == Token::YIELD && !is_generator()))) {
     return this->GetSymbol(scanner());
   } else {
@@ -1316,6 +1323,7 @@
   if (next == Token::IDENTIFIER) {
     *is_strict_reserved = false;
   } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+             next == Token::LET ||
              (next == Token::YIELD && !this->is_generator())) {
     *is_strict_reserved = true;
   } else {
@@ -1332,6 +1340,7 @@
 ParserBase<Traits>::ParseIdentifierName(bool* ok) {
   Token::Value next = Next();
   if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
+      next != Token::LET && next != Token::YIELD &&
       next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
     this->ReportUnexpectedToken(next);
     *ok = false;
@@ -1427,6 +1436,7 @@
       break;
 
     case Token::IDENTIFIER:
+    case Token::LET:
     case Token::YIELD:
     case Token::FUTURE_STRICT_RESERVED_WORD: {
       // Using eval or arguments in this context is OK even in strict mode.
@@ -1564,6 +1574,8 @@
     switch (next) {
       case Token::FUTURE_RESERVED_WORD:
       case Token::FUTURE_STRICT_RESERVED_WORD:
+      case Token::LET:
+      case Token::YIELD:
       case Token::IDENTIFIER: {
         bool is_getter = false;
         bool is_setter = false;
@@ -1579,6 +1591,8 @@
           if (next != i::Token::IDENTIFIER &&
               next != i::Token::FUTURE_RESERVED_WORD &&
               next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
+              next != i::Token::LET &&
+              next != i::Token::YIELD &&
               next != i::Token::NUMBER &&
               next != i::Token::STRING &&
               !Token::IsKeyword(next)) {
diff --git a/src/serialize.cc b/src/serialize.cc
index 9e203b5..30fde9b 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -1799,13 +1799,12 @@
 }
 
 
-void Serializer::PadByte() { sink_->Put(kNop, "Padding"); }
-
-
 void Serializer::Pad() {
   // The non-branching GetInt will read up to 3 bytes too far, so we need
   // to pad the snapshot to make sure we don't read over the end.
-  for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) PadByte();
+  for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) {
+    sink_->Put(kNop, "Padding");
+  }
 }
 
 
@@ -1817,33 +1816,16 @@
 
 ScriptData* CodeSerializer::Serialize(Handle<SharedFunctionInfo> info) {
   // Serialize code object.
-  List<char> payload;
-  ListSnapshotSink listsink(&payload);
-  CodeSerializer ser(info->GetIsolate(), &listsink);
+  List<byte> payload;
+  ListSnapshotSink list_sink(&payload);
+  CodeSerializer cs(info->GetIsolate(), &list_sink);
   DisallowHeapAllocation no_gc;
   Object** location = Handle<Object>::cast(info).location();
-  ser.VisitPointer(location);
-  ser.Pad();
+  cs.VisitPointer(location);
+  cs.Pad();
 
-  // Allocate storage.  The payload length may not be aligned.  Round up.
-  // TODO(yangguo) replace ScriptData with a more generic super class.
-  int payload_length = payload.length();
-  int raw_length = payload_length / sizeof(unsigned) + kHeaderSize;
-  if (!IsAligned(payload_length, sizeof(unsigned))) raw_length++;
-  unsigned* raw_data = i::NewArray<unsigned>(raw_length);
-  char* payload_data = reinterpret_cast<char*>(raw_data + kHeaderSize);
-
-  // Write header.
-  raw_data[kVersionHashOffset] = Version::Hash();
-  raw_data[kPayloadLengthOffset] = payload_length;
-  STATIC_ASSERT(NEW_SPACE == 0);
-  for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
-    raw_data[kReservationsOffset + i] = ser.CurrentAllocationAddress(i);
-  }
-
-  CopyBytes(payload_data, payload.begin(), static_cast<size_t>(payload_length));
-
-  return new ScriptData(Vector<unsigned>(raw_data, raw_length), true);
+  SerializedCodeData data(&payload, &cs);
+  return data.GetScriptData();
 }
 
 
@@ -1892,20 +1874,13 @@
 
 
 Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) {
-  const unsigned* raw_data = reinterpret_cast<const unsigned*>(data->Data());
-  CHECK_EQ(Version::Hash(), raw_data[kVersionHashOffset]);
-  int payload_length = raw_data[kPayloadLengthOffset];
-  const byte* payload_data =
-      reinterpret_cast<const byte*>(raw_data + kHeaderSize);
-  ASSERT_LE(payload_length, data->Length() - kHeaderSize);
-
-  SnapshotByteSource payload(payload_data, payload_length);
+  SerializedCodeData scd(data);
+  SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
   Deserializer deserializer(&payload);
   STATIC_ASSERT(NEW_SPACE == 0);
   // TODO(yangguo) what happens if remaining new space is too small?
   for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
-    deserializer.set_reservation(
-        i, raw_data[CodeSerializer::kReservationsOffset + i]);
+    deserializer.set_reservation(i, scd.GetReservation(i));
   }
   Object* root;
   deserializer.DeserializePartial(isolate, &root);
@@ -1913,4 +1888,27 @@
   ASSERT(root->IsSharedFunctionInfo());
   return root;
 }
+
+
+SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
+    : owns_script_data_(true) {
+  int data_length = payload->length() + kHeaderEntries * kIntSize;
+  byte* data = NewArray<byte>(data_length);
+  ASSERT(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment));
+  CopyBytes(data + kHeaderEntries * kIntSize, payload->begin(),
+            static_cast<size_t>(payload->length()));
+  script_data_ = new ScriptData(data, data_length);
+  script_data_->AcquireDataOwnership();
+  SetHeaderValue(kVersionHashOffset, Version::Hash());
+  STATIC_ASSERT(NEW_SPACE == 0);
+  for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
+    SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i));
+  }
+}
+
+
+bool SerializedCodeData::IsSane() {
+  return GetHeaderValue(kVersionHashOffset) == Version::Hash() &&
+         PayloadLength() >= SharedFunctionInfo::kSize;
+}
 } }  // namespace v8::internal
diff --git a/src/serialize.h b/src/serialize.h
index 6cc90ea..72bcfe5 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -5,10 +5,10 @@
 #ifndef V8_SERIALIZE_H_
 #define V8_SERIALIZE_H_
 
+#include "src/compiler.h"
 #include "src/hashmap.h"
 #include "src/heap-profiler.h"
 #include "src/isolate.h"
-#include "src/parser.h"
 #include "src/snapshot-source-sink.h"
 
 namespace v8 {
@@ -470,7 +470,6 @@
   SerializationAddressMapper address_mapper_;
   intptr_t root_index_wave_front_;
   void Pad();
-  void PadByte();
 
   friend class ObjectSerializer;
   friend class Deserializer;
@@ -576,6 +575,67 @@
   static const int kPayloadLengthOffset = 1;
   static const int kReservationsOffset = 2;
 };
+
+
+// Wrapper around ScriptData to provide code-serializer-specific functionality.
+class SerializedCodeData {
+ public:
+  // Used by when consuming.
+  explicit SerializedCodeData(ScriptData* data)
+      : script_data_(data), owns_script_data_(false) {
+    CHECK(IsSane());
+  }
+
+  // Used when producing.
+  SerializedCodeData(List<byte>* payload, CodeSerializer* cs);
+
+  ~SerializedCodeData() {
+    if (owns_script_data_) delete script_data_;
+  }
+
+  // Return ScriptData object and relinquish ownership over it to the caller.
+  ScriptData* GetScriptData() {
+    ScriptData* result = script_data_;
+    script_data_ = NULL;
+    ASSERT(owns_script_data_);
+    owns_script_data_ = false;
+    return result;
+  }
+
+  const byte* Payload() const {
+    return script_data_->data() + kHeaderEntries * kIntSize;
+  }
+
+  int PayloadLength() const {
+    return script_data_->length() - kHeaderEntries * kIntSize;
+  }
+
+  int GetReservation(int space) const {
+    return GetHeaderValue(kReservationsOffset + space);
+  }
+
+ private:
+  void SetHeaderValue(int offset, int value) {
+    reinterpret_cast<int*>(const_cast<byte*>(script_data_->data()))[offset] =
+        value;
+  }
+
+  int GetHeaderValue(int offset) const {
+    return reinterpret_cast<const int*>(script_data_->data())[offset];
+  }
+
+  bool IsSane();
+
+  // The data header consists of int-sized entries:
+  // [0] version hash
+  // [1..7] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
+  static const int kVersionHashOffset = 0;
+  static const int kReservationsOffset = 1;
+  static const int kHeaderEntries = 8;
+
+  ScriptData* script_data_;
+  bool owns_script_data_;
+};
 } }  // namespace v8::internal
 
 #endif  // V8_SERIALIZE_H_
diff --git a/src/snapshot-source-sink.cc b/src/snapshot-source-sink.cc
index e9988eb..b223b58 100644
--- a/src/snapshot-source-sink.cc
+++ b/src/snapshot-source-sink.cc
@@ -92,9 +92,9 @@
 }
 
 
-void DebugSnapshotSink::Put(int byte, const char* description) {
-  PrintF("%24s: %x\n", description, byte);
-  sink_->Put(byte, description);
+void DebugSnapshotSink::Put(byte b, const char* description) {
+  PrintF("%24s: %x\n", description, b);
+  sink_->Put(b, description);
 }
 
 }  // namespace v8::internal
diff --git a/src/snapshot-source-sink.h b/src/snapshot-source-sink.h
index eae8606..f98b5d0 100644
--- a/src/snapshot-source-sink.h
+++ b/src/snapshot-source-sink.h
@@ -71,9 +71,10 @@
 class SnapshotByteSink {
  public:
   virtual ~SnapshotByteSink() { }
-  virtual void Put(int byte, const char* description) = 0;
-  virtual void PutSection(int byte, const char* description) {
-    Put(byte, description);
+  virtual void Put(byte b, const char* description) = 0;
+  virtual void PutSection(int b, const char* description) {
+    ASSERT_LE(b, kMaxUInt8);
+    Put(static_cast<byte>(b), description);
   }
   void PutInt(uintptr_t integer, const char* description);
   void PutRaw(byte* data, int number_of_bytes, const char* description);
@@ -86,7 +87,7 @@
  public:
   DummySnapshotSink() : length_(0) {}
   virtual ~DummySnapshotSink() {}
-  virtual void Put(int byte, const char* description) { length_++; }
+  virtual void Put(byte b, const char* description) { length_++; }
   virtual int Position() { return length_; }
 
  private:
@@ -98,7 +99,7 @@
 class DebugSnapshotSink : public SnapshotByteSink {
  public:
   explicit DebugSnapshotSink(SnapshotByteSink* chained) : sink_(chained) {}
-  virtual void Put(int byte, const char* description) V8_OVERRIDE;
+  virtual void Put(byte b, const char* description) V8_OVERRIDE;
   virtual int Position() V8_OVERRIDE { return sink_->Position(); }
 
  private:
@@ -108,14 +109,14 @@
 
 class ListSnapshotSink : public i::SnapshotByteSink {
  public:
-  explicit ListSnapshotSink(i::List<char>* data) : data_(data) {}
-  virtual void Put(int byte, const char* description) V8_OVERRIDE {
-    data_->Add(byte);
+  explicit ListSnapshotSink(i::List<byte>* data) : data_(data) {}
+  virtual void Put(byte b, const char* description) V8_OVERRIDE {
+    data_->Add(b);
   }
   virtual int Position() V8_OVERRIDE { return data_->length(); }
 
  private:
-  i::List<char>* data_;
+  i::List<byte>* data_;
 };
 
 }  // namespace v8::internal
diff --git a/src/spaces.cc b/src/spaces.cc
index 12613c7..e7cb8cc 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -18,9 +18,6 @@
 // HeapObjectIterator
 
 HeapObjectIterator::HeapObjectIterator(PagedSpace* space) {
-  // Check that we actually can iterate this space.
-  ASSERT(space->is_iterable());
-
   // You can't actually iterate over the anchor page.  It is not a real page,
   // just an anchor for the double linked page list.  Initialize as if we have
   // reached the end of the anchor page, then the first iteration will move on
@@ -35,9 +32,6 @@
 
 HeapObjectIterator::HeapObjectIterator(PagedSpace* space,
                                        HeapObjectCallback size_func) {
-  // Check that we actually can iterate this space.
-  ASSERT(space->is_iterable());
-
   // You can't actually iterate over the anchor page.  It is not a real page,
   // just an anchor for the double linked page list.  Initialize the current
   // address and end as NULL, then the first iteration will move on
@@ -72,6 +66,9 @@
                                     Address cur, Address end,
                                     HeapObjectIterator::PageMode mode,
                                     HeapObjectCallback size_f) {
+  // Check that we actually can iterate this space.
+  ASSERT(space->is_iterable());
+
   space_ = space;
   cur_addr_ = cur;
   cur_end_ = end;
@@ -2581,12 +2578,23 @@
 }
 
 
-HeapObject* PagedSpace::WaitForSweeperThreadsAndRetryAllocation(
+HeapObject* PagedSpace::EnsureSweepingProgress(
     int size_in_bytes) {
   MarkCompactCollector* collector = heap()->mark_compact_collector();
 
-  // If sweeper threads are still running, wait for them.
   if (collector->IsConcurrentSweepingInProgress(this)) {
+    // If sweeping is still in progress try to sweep pages on the main thread.
+    int free_chunk =
+        collector->SweepInParallel(this, size_in_bytes);
+    if (free_chunk >= size_in_bytes) {
+      HeapObject* object = free_list_.Allocate(size_in_bytes);
+      // We should be able to allocate an object here since we just freed that
+      // much memory.
+      ASSERT(object != NULL);
+      if (object != NULL) return object;
+    }
+
+    // Wait for the sweeper threads here and complete the sweeping phase.
     collector->WaitUntilSweepingCompleted();
 
     // After waiting for the sweeper threads, there may be new free-list
@@ -2617,7 +2625,7 @@
       && heap()->OldGenerationAllocationLimitReached()) {
     // If sweeper threads are active, wait for them at that point and steal
     // elements form their free-lists.
-    HeapObject* object = WaitForSweeperThreadsAndRetryAllocation(size_in_bytes);
+    HeapObject* object = EnsureSweepingProgress(size_in_bytes);
     if (object != NULL) return object;
   }
 
@@ -2630,7 +2638,7 @@
   // If sweeper threads are active, wait for them at that point and steal
   // elements form their free-lists. Allocation may still fail their which
   // would indicate that there is not enough memory for the given allocation.
-  return WaitForSweeperThreadsAndRetryAllocation(size_in_bytes);
+  return EnsureSweepingProgress(size_in_bytes);
 }
 
 
diff --git a/src/spaces.h b/src/spaces.h
index 71b7054..8553598 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -2014,8 +2014,10 @@
   // address denoted by top in allocation_info_.
   inline HeapObject* AllocateLinearly(int size_in_bytes);
 
-  MUST_USE_RESULT HeapObject*
-      WaitForSweeperThreadsAndRetryAllocation(int size_in_bytes);
+  // If sweeping is still in progress try to sweep unswept pages. If that is
+  // not successful, wait for the sweeper threads and re-try free-list
+  // allocation.
+  MUST_USE_RESULT HeapObject* EnsureSweepingProgress(int size_in_bytes);
 
   // Slow path of AllocateRaw.  This function is space-dependent.
   MUST_USE_RESULT HeapObject* SlowAllocateRaw(int size_in_bytes);
diff --git a/src/store-buffer.cc b/src/store-buffer.cc
index a9e1356..3745d91 100644
--- a/src/store-buffer.cc
+++ b/src/store-buffer.cc
@@ -11,7 +11,6 @@
 #include "src/base/atomicops.h"
 #include "src/counters.h"
 #include "src/store-buffer-inl.h"
-#include "src/utils.h"
 
 namespace v8 {
 namespace internal {
@@ -23,13 +22,10 @@
       old_start_(NULL),
       old_limit_(NULL),
       old_top_(NULL),
-      old_regular_limit_(NULL),
       old_reserved_limit_(NULL),
-      old_virtual_memory_(NULL),
-      old_store_buffer_length_(0),
       old_buffer_is_sorted_(false),
       old_buffer_is_filtered_(false),
-      allow_overflow_(false),
+      during_gc_(false),
       store_buffer_rebuilding_enabled_(false),
       callback_(NULL),
       may_move_store_buffer_entries_(true),
@@ -48,16 +44,8 @@
       reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize * 2));
   limit_ = start_ + (kStoreBufferSize / kPointerSize);
 
-  // We set the maximum store buffer size to the maximum size of a semi-space.
-  // The store buffer may reach this limit during a full garbage collection.
-  // Note that half of the semi-space should be good enough since half of the
-  // memory in the semi-space are not object pointers.
-  old_store_buffer_length_ =
-      Max(static_cast<int>(heap_->MaxSemiSpaceSize() / sizeof(Address)),
-          kOldRegularStoreBufferLength);
-
   old_virtual_memory_ =
-      new base::VirtualMemory(old_store_buffer_length_ * kPointerSize);
+      new base::VirtualMemory(kOldStoreBufferLength * kPointerSize);
   old_top_ = old_start_ =
       reinterpret_cast<Address*>(old_virtual_memory_->address());
   // Don't know the alignment requirements of the OS, but it is certainly not
@@ -66,12 +54,9 @@
   int initial_length =
       static_cast<int>(base::OS::CommitPageSize() / kPointerSize);
   ASSERT(initial_length > 0);
-  ASSERT(initial_length <= kOldRegularStoreBufferLength);
-  ASSERT(initial_length <= old_store_buffer_length_);
-  ASSERT(kOldRegularStoreBufferLength <= old_store_buffer_length_);
+  ASSERT(initial_length <= kOldStoreBufferLength);
   old_limit_ = old_start_ + initial_length;
-  old_regular_limit_ = old_start_ + kOldRegularStoreBufferLength;
-  old_reserved_limit_ = old_start_ + old_store_buffer_length_;
+  old_reserved_limit_ = old_start_ + kOldStoreBufferLength;
 
   CHECK(old_virtual_memory_->Commit(
             reinterpret_cast<void*>(old_start_),
@@ -108,13 +93,8 @@
   delete old_virtual_memory_;
   delete[] hash_set_1_;
   delete[] hash_set_2_;
-  old_start_ = NULL;
-  old_top_ = NULL;
-  old_limit_ = NULL;
-  old_reserved_limit_ = NULL;
-  old_regular_limit_ = NULL;
-  start_ = NULL;
-  limit_ = NULL;
+  old_start_ = old_top_ = old_limit_ = old_reserved_limit_ = NULL;
+  start_ = limit_ = NULL;
   heap_->public_set_store_buffer_top(start_);
 }
 
@@ -148,35 +128,9 @@
 }
 
 
-template<StoreBuffer::ExemptPopularPagesMode mode>
-void StoreBuffer::IterativelyExemptPopularPages(intptr_t space_needed) {
-  // Sample 1 entry in 97 and filter out the pages where we estimate that more
-  // than 1 in 8 pointers are to new space.
-  static const int kSampleFinenesses = 5;
-  static const struct Samples {
-    int prime_sample_step;
-    int threshold;
-  } samples[kSampleFinenesses] =  {
-    { 97, ((Page::kPageSize / kPointerSize) / 97) / 8 },
-    { 23, ((Page::kPageSize / kPointerSize) / 23) / 16 },
-    { 7, ((Page::kPageSize / kPointerSize) / 7) / 32 },
-    { 3, ((Page::kPageSize / kPointerSize) / 3) / 256 },
-    { 1, 0}
-  };
-  for (int i = 0; i < kSampleFinenesses; i++) {
-    ExemptPopularPages(samples[i].prime_sample_step, samples[i].threshold);
-    // As a last resort we mark all pages as being exempt from the store buffer.
-    ASSERT(i != (kSampleFinenesses - 1) || old_top_ == old_start_);
-    if (mode == ENSURE_SPACE && SpaceAvailable(space_needed)) return;
-    else if (mode == SHRINK_TO_REGULAR_SIZE && old_top_ < old_limit_) return;
-  }
-}
-
-
 void StoreBuffer::EnsureSpace(intptr_t space_needed) {
   while (old_limit_ - old_top_ < space_needed &&
-      ((!allow_overflow_ && old_limit_ < old_regular_limit_) ||
-          (allow_overflow_ && old_limit_ < old_reserved_limit_))) {
+         old_limit_ < old_reserved_limit_) {
     size_t grow = old_limit_ - old_start_;  // Double size.
     CHECK(old_virtual_memory_->Commit(reinterpret_cast<void*>(old_limit_),
                                       grow * kPointerSize,
@@ -208,8 +162,26 @@
 
   if (SpaceAvailable(space_needed)) return;
 
-  IterativelyExemptPopularPages<ENSURE_SPACE>(space_needed);
-  ASSERT(SpaceAvailable(space_needed));
+  // Sample 1 entry in 97 and filter out the pages where we estimate that more
+  // than 1 in 8 pointers are to new space.
+  static const int kSampleFinenesses = 5;
+  static const struct Samples {
+    int prime_sample_step;
+    int threshold;
+  } samples[kSampleFinenesses] =  {
+    { 97, ((Page::kPageSize / kPointerSize) / 97) / 8 },
+    { 23, ((Page::kPageSize / kPointerSize) / 23) / 16 },
+    { 7, ((Page::kPageSize / kPointerSize) / 7) / 32 },
+    { 3, ((Page::kPageSize / kPointerSize) / 3) / 256 },
+    { 1, 0}
+  };
+  for (int i = 0; i < kSampleFinenesses; i++) {
+    ExemptPopularPages(samples[i].prime_sample_step, samples[i].threshold);
+    // As a last resort we mark all pages as being exempt from the store buffer.
+    ASSERT(i != (kSampleFinenesses - 1) || old_top_ == old_start_);
+    if (SpaceAvailable(space_needed)) return;
+  }
+  UNREACHABLE();
 }
 
 
@@ -356,9 +328,9 @@
 }
 
 
-void StoreBuffer::GCPrologue(bool allow_overflow) {
+void StoreBuffer::GCPrologue() {
   ClearFilteringHashSets();
-  allow_overflow_ = allow_overflow;
+  during_gc_ = true;
 }
 
 
@@ -394,13 +366,7 @@
 
 
 void StoreBuffer::GCEpilogue() {
-  if (allow_overflow_ && old_limit_ > old_regular_limit_) {
-    IterativelyExemptPopularPages<SHRINK_TO_REGULAR_SIZE>(0);
-    ASSERT(old_limit_ < old_regular_limit_);
-    old_virtual_memory_->Uncommit(old_limit_, old_regular_limit_ - old_limit_);
-  }
-
-  allow_overflow_ = false;
+  during_gc_ = false;
 #ifdef VERIFY_HEAP
   if (FLAG_verify_heap) {
     Verify();
@@ -522,22 +488,25 @@
           FindPointersToNewSpaceInRegion(start, end, slot_callback, clear_maps);
         } else {
           Page* page = reinterpret_cast<Page*>(chunk);
-          ASSERT(page->owner() == heap_->map_space() ||
-                 page->owner() == heap_->old_pointer_space());
-          CHECK(!page->WasSweptConservatively());
-
-          HeapObjectIterator iterator(page, NULL);
-          for (HeapObject* heap_object = iterator.Next();
-               heap_object != NULL;
-               heap_object = iterator.Next()) {
-            // We iterate over objects that contain pointers only.
-            if (heap_object->ContainsPointers()) {
-              FindPointersToNewSpaceInRegion(
-                  heap_object->address() + HeapObject::kHeaderSize,
-                  heap_object->address() + heap_object->Size(),
-                  slot_callback,
-                  clear_maps);
+          PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
+          Address start = page->area_start();
+          Address end = page->area_end();
+          if (owner == heap_->map_space()) {
+            ASSERT(page->WasSweptPrecisely());
+            HeapObjectIterator iterator(page, NULL);
+            for (HeapObject* heap_object = iterator.Next(); heap_object != NULL;
+                 heap_object = iterator.Next()) {
+              // We skip free space objects.
+              if (!heap_object->IsFiller()) {
+                FindPointersToNewSpaceInRegion(
+                    heap_object->address() + HeapObject::kHeaderSize,
+                    heap_object->address() + heap_object->Size(), slot_callback,
+                    clear_maps);
+              }
             }
+          } else {
+            FindPointersToNewSpaceInRegion(
+                start, end, slot_callback, clear_maps);
           }
         }
       }
diff --git a/src/store-buffer.h b/src/store-buffer.h
index 20ff6ff..9101c0e 100644
--- a/src/store-buffer.h
+++ b/src/store-buffer.h
@@ -19,6 +19,11 @@
 
 typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to);
 
+typedef void (StoreBuffer::*RegionCallback)(Address start,
+                                            Address end,
+                                            ObjectSlotCallback slot_callback,
+                                            bool clear_maps);
+
 // Used to implement the write barrier by collecting addresses of pointers
 // between spaces.
 class StoreBuffer {
@@ -63,13 +68,13 @@
   static const int kStoreBufferOverflowBit = 1 << (14 + kPointerSizeLog2);
   static const int kStoreBufferSize = kStoreBufferOverflowBit;
   static const int kStoreBufferLength = kStoreBufferSize / sizeof(Address);
-  static const int kOldRegularStoreBufferLength = kStoreBufferLength * 16;
+  static const int kOldStoreBufferLength = kStoreBufferLength * 16;
   static const int kHashSetLengthLog2 = 12;
   static const int kHashSetLength = 1 << kHashSetLengthLog2;
 
   void Compact();
 
-  void GCPrologue(bool allow_overflow);
+  void GCPrologue();
   void GCEpilogue();
 
   Object*** Limit() { return reinterpret_cast<Object***>(old_limit_); }
@@ -113,27 +118,12 @@
   Address* old_start_;
   Address* old_limit_;
   Address* old_top_;
-
-  // The regular limit specifies how big the store buffer may become during
-  // mutator execution or while scavenging.
-  Address* old_regular_limit_;
-
-  // The reserved limit is bigger then the regular limit. It should be the size
-  // of a semi-space to avoid new scan-on-scavenge during new space evacuation
-  // after sweeping in a full garbage collection.
   Address* old_reserved_limit_;
-
   base::VirtualMemory* old_virtual_memory_;
-  int old_store_buffer_length_;
 
   bool old_buffer_is_sorted_;
   bool old_buffer_is_filtered_;
-
-  // If allow_overflow_ is set, we allow the store buffer to grow until
-  // old_reserved_limit_. But we will shrink the store buffer in the epilogue to
-  // stay within the old_regular_limit_.
-  bool allow_overflow_;
-
+  bool during_gc_;
   // The garbage collector iterates over many pointers to new space that are not
   // handled by the store buffer.  This flag indicates whether the pointers
   // found by the callbacks should be added to the store buffer or not.
@@ -156,14 +146,6 @@
   void Uniq();
   void ExemptPopularPages(int prime_sample_step, int threshold);
 
-  enum ExemptPopularPagesMode {
-    ENSURE_SPACE,
-    SHRINK_TO_REGULAR_SIZE
-  };
-
-  template <ExemptPopularPagesMode mode>
-  void IterativelyExemptPopularPages(intptr_t space_needed);
-
   // Set the map field of the object to NULL if contains a map.
   inline void ClearDeadObject(HeapObject *object);
 
@@ -174,6 +156,17 @@
                                       ObjectSlotCallback slot_callback,
                                       bool clear_maps);
 
+  // For each region of pointers on a page in use from an old space call
+  // visit_pointer_region callback.
+  // If either visit_pointer_region or callback can cause an allocation
+  // in old space and changes in allocation watermark then
+  // can_preallocate_during_iteration should be set to true.
+  void IteratePointersOnPage(
+      PagedSpace* space,
+      Page* page,
+      RegionCallback region_callback,
+      ObjectSlotCallback slot_callback);
+
   void IteratePointersInStoreBuffer(ObjectSlotCallback slot_callback,
                                     bool clear_maps);
 
diff --git a/src/sweeper-thread.cc b/src/sweeper-thread.cc
index 9ce5ec4..fee3e92 100644
--- a/src/sweeper-thread.cc
+++ b/src/sweeper-thread.cc
@@ -41,8 +41,8 @@
       return;
     }
 
-    collector_->SweepInParallel(heap_->old_data_space());
-    collector_->SweepInParallel(heap_->old_pointer_space());
+    collector_->SweepInParallel(heap_->old_data_space(), 0);
+    collector_->SweepInParallel(heap_->old_pointer_space(), 0);
     end_sweeping_semaphore_.Signal();
   }
 }
diff --git a/src/types.cc b/src/types.cc
index 024d9f6..3cd349b 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -181,10 +181,10 @@
     case ODDBALL_TYPE: {
       Heap* heap = map->GetHeap();
       if (map == heap->undefined_map()) return kUndefined;
-      if (map == heap->the_hole_map()) return kAny;  // TODO(rossberg): kNone?
       if (map == heap->null_map()) return kNull;
       if (map == heap->boolean_map()) return kBoolean;
-      ASSERT(map == heap->uninitialized_map() ||
+      ASSERT(map == heap->the_hole_map() ||
+             map == heap->uninitialized_map() ||
              map == heap->no_interceptor_result_sentinel_map() ||
              map == heap->termination_exception_map() ||
              map == heap->arguments_marker_map());
diff --git a/src/version.cc b/src/version.cc
index 7ff8fb4..331dffd 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     28
-#define BUILD_NUMBER      20
+#define BUILD_NUMBER      21
 #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/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 63b1b8f..486917f 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -89,15 +89,6 @@
 }
 
 
-void KeyedStoreFastElementStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { rdx, rcx, rax };
-  descriptor->Initialize(
-      ARRAY_SIZE(registers), registers,
-      FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure));
-}
-
-
 void TransitionElementsKindStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { rax, rbx };
@@ -231,14 +222,6 @@
 }
 
 
-void StoreGlobalStub::InitializeInterfaceDescriptor(
-    CodeStubInterfaceDescriptor* descriptor) {
-  Register registers[] = { rdx, rcx, rax };
-  descriptor->Initialize(ARRAY_SIZE(registers), registers,
-                         FUNCTION_ADDR(StoreIC_MissFromStubFailure));
-}
-
-
 void ElementsTransitionAndStoreStub::InitializeInterfaceDescriptor(
     CodeStubInterfaceDescriptor* descriptor) {
   Register registers[] = { rax, rbx, rcx, rdx };
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index 1870384..f00a4ef 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -170,13 +170,11 @@
 
 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
   // Register state for IC store call (from ic-x64.cc).
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : name
-  //  -- rdx    : receiver
-  // -----------------------------------
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  Register value = StoreIC::ValueRegister();
   Generate_DebugBreakCallHelper(
-      masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false);
+      masm, receiver.bit() | name.bit() | value.bit(), 0, false);
 }
 
 
@@ -187,14 +185,12 @@
 
 
 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
-  // Register state for keyed IC load call (from ic-x64.cc).
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : key
-  //  -- rdx    : receiver
-  // -----------------------------------
+  // Register state for keyed IC store call (from ic-x64.cc).
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  Register value = KeyedStoreIC::ValueRegister();
   Generate_DebugBreakCallHelper(
-      masm, rax.bit() | rcx.bit() | rdx.bit(), 0, false);
+      masm, receiver.bit() | name.bit() | value.bit(), 0, false);
 }
 
 
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index e0fe835..7fc7c76 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1666,8 +1666,9 @@
         if (key->value()->IsInternalizedString()) {
           if (property->emit_store()) {
             VisitForAccumulatorValue(value);
-            __ Move(rcx, key->value());
-            __ movp(rdx, Operand(rsp, 0));
+            ASSERT(StoreIC::ValueRegister().is(rax));
+            __ Move(StoreIC::NameRegister(), key->value());
+            __ movp(StoreIC::ReceiverRegister(), Operand(rsp, 0));
             CallStoreIC(key->LiteralFeedbackId());
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -2347,9 +2348,9 @@
     case NAMED_PROPERTY: {
       __ Push(rax);  // Preserve value.
       VisitForAccumulatorValue(prop->obj());
-      __ movp(rdx, rax);
-      __ Pop(rax);  // Restore value.
-      __ Move(rcx, prop->key()->AsLiteral()->value());
+      __ Move(StoreIC::ReceiverRegister(), rax);
+      __ Pop(StoreIC::ValueRegister());  // Restore value.
+      __ Move(StoreIC::NameRegister(), prop->key()->AsLiteral()->value());
       CallStoreIC();
       break;
     }
@@ -2357,9 +2358,9 @@
       __ Push(rax);  // Preserve value.
       VisitForStackValue(prop->obj());
       VisitForAccumulatorValue(prop->key());
-      __ movp(rcx, rax);
-      __ Pop(rdx);
-      __ Pop(rax);  // Restore value.
+      __ Move(KeyedStoreIC::NameRegister(), rax);
+      __ Pop(KeyedStoreIC::ReceiverRegister());
+      __ Pop(KeyedStoreIC::ValueRegister());  // Restore value.
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
@@ -2396,8 +2397,8 @@
                                                Token::Value op) {
   if (var->IsUnallocated()) {
     // Global var, const, or let.
-    __ Move(rcx, var->name());
-    __ movp(rdx, GlobalObjectOperand());
+    __ Move(StoreIC::NameRegister(), var->name());
+    __ movp(StoreIC::ReceiverRegister(), GlobalObjectOperand());
     CallStoreIC();
 
   } else if (op == Token::INIT_CONST_LEGACY) {
@@ -2465,8 +2466,8 @@
 
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  __ Move(rcx, prop->key()->AsLiteral()->value());
-  __ Pop(rdx);
+  __ Move(StoreIC::NameRegister(), prop->key()->AsLiteral()->value());
+  __ Pop(StoreIC::ReceiverRegister());
   CallStoreIC(expr->AssignmentFeedbackId());
 
   PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
@@ -2477,8 +2478,9 @@
 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
   // Assignment to a property, using a keyed store IC.
 
-  __ Pop(rcx);
-  __ Pop(rdx);
+  __ Pop(KeyedStoreIC::NameRegister());  // Key.
+  __ Pop(KeyedStoreIC::ReceiverRegister());
+  ASSERT(KeyedStoreIC::ValueRegister().is(rax));
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
   Handle<Code> ic = strict_mode() == SLOPPY
@@ -4340,8 +4342,8 @@
       }
       break;
     case NAMED_PROPERTY: {
-      __ Move(rcx, prop->key()->AsLiteral()->value());
-      __ Pop(rdx);
+      __ Move(StoreIC::NameRegister(), prop->key()->AsLiteral()->value());
+      __ Pop(StoreIC::ReceiverRegister());
       CallStoreIC(expr->CountStoreFeedbackId());
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -4354,8 +4356,8 @@
       break;
     }
     case KEYED_PROPERTY: {
-      __ Pop(rcx);
-      __ Pop(rdx);
+      __ Pop(KeyedStoreIC::NameRegister());
+      __ Pop(KeyedStoreIC::ReceiverRegister());
       Handle<Code> ic = strict_mode() == SLOPPY
           ? isolate()->builtins()->KeyedStoreIC_Initialize()
           : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index 43d3228..caa8d4c 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -567,12 +567,16 @@
   Label transition_smi_elements;
   Label finish_object_store, non_double_value, transition_double_elements;
   Label fast_double_without_map_check;
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register key = KeyedStoreIC::NameRegister();
+  Register value = KeyedStoreIC::ValueRegister();
+  ASSERT(receiver.is(rdx));
+  ASSERT(key.is(rcx));
+  ASSERT(value.is(rax));
   // Fast case: Do the store, could be either Object or double.
   __ bind(fast_object);
-  // rax: value
   // rbx: receiver's elements array (a FixedArray)
-  // rcx: index
-  // rdx: receiver (a JSArray)
+  // receiver is a JSArray.
   // r9: map of receiver
   if (check_map == kCheckMap) {
     __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
@@ -585,26 +589,26 @@
   // there may be a callback on the element
   Label holecheck_passed1;
   __ movp(kScratchRegister, FieldOperand(rbx,
-                                         rcx,
+                                         key,
                                          times_pointer_size,
                                          FixedArray::kHeaderSize));
   __ CompareRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
   __ j(not_equal, &holecheck_passed1);
-  __ JumpIfDictionaryInPrototypeChain(rdx, rdi, kScratchRegister, slow);
+  __ JumpIfDictionaryInPrototypeChain(receiver, rdi, kScratchRegister, slow);
 
   __ bind(&holecheck_passed1);
 
   // Smi stores don't require further checks.
   Label non_smi_value;
-  __ JumpIfNotSmi(rax, &non_smi_value);
+  __ JumpIfNotSmi(value, &non_smi_value);
   if (increment_length == kIncrementLength) {
     // Add 1 to receiver->length.
-    __ leal(rdi, Operand(rcx, 1));
-    __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
+    __ leal(rdi, Operand(key, 1));
+    __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi);
   }
   // It's irrelevant whether array is smi-only or not when writing a smi.
-  __ movp(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
-          rax);
+  __ movp(FieldOperand(rbx, key, times_pointer_size, FixedArray::kHeaderSize),
+          value);
   __ ret(0);
 
   __ bind(&non_smi_value);
@@ -615,14 +619,14 @@
   __ bind(&finish_object_store);
   if (increment_length == kIncrementLength) {
     // Add 1 to receiver->length.
-    __ leal(rdi, Operand(rcx, 1));
-    __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
+    __ leal(rdi, Operand(key, 1));
+    __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi);
   }
-  __ movp(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
-          rax);
-  __ movp(rdx, rax);  // Preserve the value which is returned.
+  __ movp(FieldOperand(rbx, key, times_pointer_size, FixedArray::kHeaderSize),
+          value);
+  __ movp(rdx, value);  // Preserve the value which is returned.
   __ RecordWriteArray(
-      rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+      rbx, rdx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
   __ ret(0);
 
   __ bind(fast_double);
@@ -638,25 +642,25 @@
   // We have to see if the double version of the hole is present. If so
   // go to the runtime.
   uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
-  __ cmpl(FieldOperand(rbx, rcx, times_8, offset), Immediate(kHoleNanUpper32));
+  __ cmpl(FieldOperand(rbx, key, times_8, offset), Immediate(kHoleNanUpper32));
   __ j(not_equal, &fast_double_without_map_check);
-  __ JumpIfDictionaryInPrototypeChain(rdx, rdi, kScratchRegister, slow);
+  __ JumpIfDictionaryInPrototypeChain(receiver, rdi, kScratchRegister, slow);
 
   __ bind(&fast_double_without_map_check);
-  __ StoreNumberToDoubleElements(rax, rbx, rcx, xmm0,
+  __ StoreNumberToDoubleElements(value, rbx, key, xmm0,
                                  &transition_double_elements);
   if (increment_length == kIncrementLength) {
     // Add 1 to receiver->length.
-    __ leal(rdi, Operand(rcx, 1));
-    __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
+    __ leal(rdi, Operand(key, 1));
+    __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi);
   }
   __ ret(0);
 
   __ bind(&transition_smi_elements);
-  __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
+  __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
 
   // Transition the array appropriately depending on the value type.
-  __ movp(r9, FieldOperand(rax, HeapObject::kMapOffset));
+  __ movp(r9, FieldOperand(value, HeapObject::kMapOffset));
   __ CompareRoot(r9, Heap::kHeapNumberMapRootIndex);
   __ j(not_equal, &non_double_value);
 
@@ -670,7 +674,7 @@
   AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS,
                                                     FAST_DOUBLE_ELEMENTS);
   ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, slow);
-  __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
+  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
   __ jmp(&fast_double_without_map_check);
 
   __ bind(&non_double_value);
@@ -683,14 +687,14 @@
   mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS);
   ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm, mode,
                                                                    slow);
-  __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
+  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
   __ jmp(&finish_object_store);
 
   __ bind(&transition_double_elements);
   // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
   // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
   // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
-  __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
+  __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
   __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
                                          FAST_ELEMENTS,
                                          rbx,
@@ -698,35 +702,34 @@
                                          slow);
   mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS);
   ElementsTransitionGenerator::GenerateDoubleToObject(masm, mode, slow);
-  __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
+  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
   __ jmp(&finish_object_store);
 }
 
 
 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
                                    StrictMode strict_mode) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : key
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
+  // Return address is on the stack.
   Label slow, slow_with_tagged_index, fast_object, fast_object_grow;
   Label fast_double, fast_double_grow;
   Label array, extra, check_if_double_array;
+  Register receiver = ReceiverRegister();
+  Register key = NameRegister();
+  ASSERT(receiver.is(rdx));
+  ASSERT(key.is(rcx));
 
   // Check that the object isn't a smi.
-  __ JumpIfSmi(rdx, &slow_with_tagged_index);
+  __ JumpIfSmi(receiver, &slow_with_tagged_index);
   // Get the map from the receiver.
-  __ movp(r9, FieldOperand(rdx, HeapObject::kMapOffset));
+  __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset));
   // Check that the receiver does not require access checks and is not observed.
   // The generic stub does not perform map checks or handle observed objects.
   __ testb(FieldOperand(r9, Map::kBitFieldOffset),
            Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
   __ j(not_zero, &slow_with_tagged_index);
   // Check that the key is a smi.
-  __ JumpIfNotSmi(rcx, &slow_with_tagged_index);
-  __ SmiToInteger32(rcx, rcx);
+  __ JumpIfNotSmi(key, &slow_with_tagged_index);
+  __ SmiToInteger32(key, key);
 
   __ CmpInstanceType(r9, JS_ARRAY_TYPE);
   __ j(equal, &array);
@@ -735,20 +738,15 @@
   __ j(below, &slow);
 
   // Object case: Check key against length in the elements array.
-  // rax: value
-  // rdx: JSObject
-  // rcx: index
-  __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
+  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
   // Check array bounds.
-  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
-  // rax: value
+  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key);
   // rbx: FixedArray
-  // rcx: index
   __ j(above, &fast_object);
 
   // Slow case: call runtime.
   __ bind(&slow);
-  __ Integer32ToSmi(rcx, rcx);
+  __ Integer32ToSmi(key, key);
   __ bind(&slow_with_tagged_index);
   GenerateRuntimeSetProperty(masm, strict_mode);
   // Never returns to here.
@@ -757,13 +755,11 @@
   // perform the store and update the length. Used for adding one
   // element to the array by writing to array[array.length].
   __ bind(&extra);
-  // rax: value
-  // rdx: receiver (a JSArray)
+  // receiver is a JSArray.
   // rbx: receiver's elements array (a FixedArray)
-  // rcx: index
-  // flags: smicompare (rdx.length(), rbx)
+  // flags: smicompare (receiver.length(), rbx)
   __ j(not_equal, &slow);  // do not leave holes in the array
-  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
+  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key);
   __ j(below_equal, &slow);
   // Increment index to get new length.
   __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
@@ -781,14 +777,12 @@
   // array. Check that the array is in fast mode (and writable); if it
   // is the length is always a smi.
   __ bind(&array);
-  // rax: value
-  // rdx: receiver (a JSArray)
-  // rcx: index
-  __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
+  // receiver is a JSArray.
+  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
 
   // Check the key against the length in the array, compute the
   // address to store into and fall through to fast case.
-  __ SmiCompareInteger32(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
+  __ SmiCompareInteger32(FieldOperand(receiver, JSArray::kLengthOffset), key);
   __ j(below_equal, &extra);
 
   KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double,
@@ -906,18 +900,20 @@
 
 
 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : key
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
+  // The return address is on the stack.
   Label slow, notin;
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  Register value = ValueRegister();
+  ASSERT(receiver.is(rdx));
+  ASSERT(name.is(rcx));
+  ASSERT(value.is(rax));
+
   Operand mapped_location = GenerateMappedArgumentsLookup(
-      masm, rdx, rcx, rbx, rdi, r8, &notin, &slow);
-  __ movp(mapped_location, rax);
+      masm, receiver, name, rbx, rdi, r8, &notin, &slow);
+  __ movp(mapped_location, value);
   __ leap(r9, mapped_location);
-  __ movp(r8, rax);
+  __ movp(r8, value);
   __ RecordWrite(rbx,
                  r9,
                  r8,
@@ -928,10 +924,10 @@
   __ bind(&notin);
   // The unmapped lookup expects that the parameter map is in rbx.
   Operand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, rcx, rbx, rdi, &slow);
-  __ movp(unmapped_location, rax);
+      GenerateUnmappedArgumentsLookup(masm, name, rbx, rdi, &slow);
+  __ movp(unmapped_location, value);
   __ leap(r9, unmapped_location);
-  __ movp(r8, rax);
+  __ movp(r8, value);
   __ RecordWrite(rbx,
                  r9,
                  r8,
@@ -1049,6 +1045,26 @@
 const Register LoadIC::NameRegister() { return rcx; }
 
 
+const Register StoreIC::ReceiverRegister() { return rdx; }
+const Register StoreIC::NameRegister() { return rcx; }
+const Register StoreIC::ValueRegister() { return rax; }
+
+
+const Register KeyedStoreIC::ReceiverRegister() {
+  return StoreIC::ReceiverRegister();
+}
+
+
+const Register KeyedStoreIC::NameRegister() {
+  return StoreIC::NameRegister();
+}
+
+
+const Register KeyedStoreIC::ValueRegister() {
+  return StoreIC::ValueRegister();
+}
+
+
 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
   // The return address is on the stack.
 
@@ -1063,36 +1079,36 @@
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : name
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
+  // The return address is on the stack.
 
   // Get the receiver from the stack and probe the stub cache.
   Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
-      masm, flags, rdx, rcx, rbx, no_reg);
+      masm, flags, ReceiverRegister(), NameRegister(), rbx, no_reg);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
 }
 
 
-void StoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : name
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
+static void StoreIC_PushArgs(MacroAssembler* masm) {
+  Register receiver = StoreIC::ReceiverRegister();
+  Register name = StoreIC::NameRegister();
+  Register value = StoreIC::ValueRegister();
+
+  ASSERT(!rbx.is(receiver) && !rbx.is(name) && !rbx.is(value));
 
   __ PopReturnAddressTo(rbx);
-  __ Push(rdx);  // receiver
-  __ Push(rcx);  // name
-  __ Push(rax);  // value
+  __ Push(receiver);
+  __ Push(name);
+  __ Push(value);
   __ PushReturnAddressFrom(rbx);
+}
+
+
+void StoreIC::GenerateMiss(MacroAssembler* masm) {
+  // Return address is on the stack.
+  StoreIC_PushArgs(masm);
 
   // Perform tail call to the entry.
   ExternalReference ref =
@@ -1102,18 +1118,16 @@
 
 
 void StoreIC::GenerateNormal(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : name
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
+  // Return address is on the stack.
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  Register value = ValueRegister();
 
   Label miss;
 
-  GenerateNameDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, receiver, rbx, rdi, &miss);
 
-  GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9);
+  GenerateDictionaryStore(masm, &miss, rbx, name, value, r8, r9);
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->store_normal_hit(), 1);
   __ ret(0);
@@ -1126,16 +1140,14 @@
 
 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                          StrictMode strict_mode) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : name
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
+  // Return address is on the stack.
+  ASSERT(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) &&
+         !rbx.is(ValueRegister()));
+
   __ PopReturnAddressTo(rbx);
-  __ Push(rdx);
-  __ Push(rcx);
-  __ Push(rax);
+  __ Push(ReceiverRegister());
+  __ Push(NameRegister());
+  __ Push(ValueRegister());
   __ Push(Smi::FromInt(strict_mode));
   __ PushReturnAddressFrom(rbx);
 
@@ -1146,17 +1158,14 @@
 
 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
                                               StrictMode strict_mode) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : key
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
+  // Return address is on the stack.
+  ASSERT(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) &&
+         !rbx.is(ValueRegister()));
 
   __ PopReturnAddressTo(rbx);
-  __ Push(rdx);  // receiver
-  __ Push(rcx);  // key
-  __ Push(rax);  // value
+  __ Push(ReceiverRegister());
+  __ Push(NameRegister());
+  __ Push(ValueRegister());
   __ Push(Smi::FromInt(strict_mode));   // Strict mode.
   __ PushReturnAddressFrom(rbx);
 
@@ -1166,18 +1175,8 @@
 
 
 void StoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : key
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
-
-  __ PopReturnAddressTo(rbx);
-  __ Push(rdx);  // receiver
-  __ Push(rcx);  // key
-  __ Push(rax);  // value
-  __ PushReturnAddressFrom(rbx);
+  // Return address is on the stack.
+  StoreIC_PushArgs(masm);
 
   // Do tail-call to runtime routine.
   ExternalReference ref(IC_Utility(kStoreIC_Slow), masm->isolate());
@@ -1186,18 +1185,8 @@
 
 
 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : key
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
-
-  __ PopReturnAddressTo(rbx);
-  __ Push(rdx);  // receiver
-  __ Push(rcx);  // key
-  __ Push(rax);  // value
-  __ PushReturnAddressFrom(rbx);
+  // Return address is on the stack.
+  StoreIC_PushArgs(masm);
 
   // Do tail-call to runtime routine.
   ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate());
@@ -1206,18 +1195,8 @@
 
 
 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- rax    : value
-  //  -- rcx    : key
-  //  -- rdx    : receiver
-  //  -- rsp[0] : return address
-  // -----------------------------------
-
-  __ PopReturnAddressTo(rbx);
-  __ Push(rdx);  // receiver
-  __ Push(rcx);  // key
-  __ Push(rax);  // value
-  __ PushReturnAddressFrom(rbx);
+  // Return address is on the stack.
+  StoreIC_PushArgs(masm);
 
   // Do tail-call to runtime routine.
   ExternalReference ref =
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index b524e8a..426673a 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -4174,10 +4174,10 @@
 
 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(rsi));
-  ASSERT(ToRegister(instr->object()).is(rdx));
-  ASSERT(ToRegister(instr->value()).is(rax));
+  ASSERT(ToRegister(instr->object()).is(StoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->value()).is(StoreIC::ValueRegister()));
 
-  __ Move(rcx, instr->hydrogen()->name());
+  __ Move(StoreIC::NameRegister(), instr->hydrogen()->name());
   Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
@@ -4439,9 +4439,9 @@
 
 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(rsi));
-  ASSERT(ToRegister(instr->object()).is(rdx));
-  ASSERT(ToRegister(instr->key()).is(rcx));
-  ASSERT(ToRegister(instr->value()).is(rax));
+  ASSERT(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister()));
+  ASSERT(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister()));
 
   Handle<Code> ic = instr->strict_mode() == STRICT
       ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 6d1c3dd..c0be3a5 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -2272,9 +2272,10 @@
 
 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), rsi);
-  LOperand* object = UseFixed(instr->object(), rdx);
-  LOperand* key = UseFixed(instr->key(), rcx);
-  LOperand* value = UseFixed(instr->value(), rax);
+  LOperand* object = UseFixed(instr->object(),
+                              KeyedStoreIC::ReceiverRegister());
+  LOperand* key = UseFixed(instr->key(), KeyedStoreIC::NameRegister());
+  LOperand* value = UseFixed(instr->value(), KeyedStoreIC::ValueRegister());
 
   ASSERT(instr->object()->representation().IsTagged());
   ASSERT(instr->key()->representation().IsTagged());
@@ -2369,8 +2370,8 @@
 
 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), rsi);
-  LOperand* object = UseFixed(instr->object(), rdx);
-  LOperand* value = UseFixed(instr->value(), rax);
+  LOperand* object = UseFixed(instr->object(), StoreIC::ReceiverRegister());
+  LOperand* value = UseFixed(instr->value(), StoreIC::ValueRegister());
 
   LStoreNamedGeneric* result =
       new(zone()) LStoreNamedGeneric(context, object, value);
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index b305392..886d9ad 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -1239,20 +1239,24 @@
 
 
 Register StoreStubCompiler::value() {
-  return rax;
+  return StoreIC::ValueRegister();
 }
 
 
 Register* StoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { rdx, rcx, rbx, rdi, r8 };
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  static Register registers[] = { receiver, name, rbx, rdi, r8 };
   return registers;
 }
 
 
 Register* KeyedStoreStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3.
-  static Register registers[] = { rdx, rcx, rbx, rdi, r8 };
+  Register receiver = KeyedStoreIC::ReceiverRegister();
+  Register name = KeyedStoreIC::NameRegister();
+  static Register registers[] = { receiver, name, rbx, rdi, r8 };
   return registers;
 }
 
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 6afdf1b..6251172 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -14814,134 +14814,21 @@
                               v8::ScriptCompiler::kProduceDataToCache);
   // Serialize.
   const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
-  char* serialized_data = i::NewArray<char>(cd->length);
+  i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
   i::MemCopy(serialized_data, cd->data, cd->length);
 
   // Deserialize.
-  i::ScriptData* deserialized = i::ScriptData::New(serialized_data, cd->length);
+  i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
 
   // Verify that the original is the same as the deserialized.
-  CHECK_EQ(cd->length, deserialized->Length());
-  CHECK_EQ(0, memcmp(cd->data, deserialized->Data(), cd->length));
+  CHECK_EQ(cd->length, deserialized->length());
+  CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
 
   delete deserialized;
   i::DeleteArray(serialized_data);
 }
 
 
-// Attempts to deserialize bad data.
-TEST(PreCompileDeserializationError) {
-  v8::V8::Initialize();
-  const char* data = "DONT CARE";
-  int invalid_size = 3;
-  i::ScriptData* sd = i::ScriptData::New(data, invalid_size);
-  CHECK_EQ(NULL, sd);
-}
-
-
-TEST(CompileWithInvalidCachedData) {
-  v8::V8::Initialize();
-  v8::Isolate* isolate = CcTest::isolate();
-  LocalContext context;
-  v8::HandleScope scope(context->GetIsolate());
-  i::FLAG_min_preparse_length = 0;
-
-  const char* script = "function foo(){ return 5;}\n"
-      "function bar(){ return 6 + 7;}  foo();";
-  v8::ScriptCompiler::Source source(v8_str(script));
-  v8::ScriptCompiler::Compile(isolate, &source,
-                              v8::ScriptCompiler::kProduceDataToCache);
-  // source owns its cached data. Create a ScriptData based on it. The user
-  // never needs to create ScriptDatas any more; we only need it here because we
-  // want to modify the data before passing it back.
-  const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
-  // ScriptData does not take ownership of the buffers passed to it.
-  i::ScriptData* sd =
-      i::ScriptData::New(reinterpret_cast<const char*>(cd->data), cd->length);
-  CHECK(!sd->HasError());
-  // ScriptData private implementation details
-  const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
-  const int kFunctionEntrySize = i::FunctionEntry::kSize;
-  const int kFunctionEntryStartOffset = 0;
-  const int kFunctionEntryEndOffset = 1;
-  unsigned* sd_data =
-      reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
-
-  // Overwrite function bar's end position with 0.
-  sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
-  v8::TryCatch try_catch;
-
-  // Make the script slightly different so that we don't hit the compilation
-  // cache. Don't change the lenghts of tokens.
-  const char* script2 = "function foo(){ return 6;}\n"
-      "function bar(){ return 6 + 7;}  foo();";
-  v8::ScriptCompiler::Source source2(
-      v8_str(script2),
-      // CachedData doesn't take ownership of the buffers, Source takes
-      // ownership of CachedData.
-      new v8::ScriptCompiler::CachedData(
-          reinterpret_cast<const uint8_t*>(sd->Data()), sd->Length()));
-  Local<v8::UnboundScript> compiled_script =
-      v8::ScriptCompiler::CompileUnbound(isolate, &source2);
-
-  CHECK(try_catch.HasCaught());
-  {
-    String::Utf8Value exception_value(try_catch.Message()->Get());
-    CHECK_EQ("Uncaught SyntaxError: Invalid cached data for function bar",
-             *exception_value);
-  }
-
-  try_catch.Reset();
-  delete sd;
-
-  // Overwrite function bar's start position with 200. The function entry will
-  // not be found when searching for it by position, and the compilation fails.
-
-  // ScriptData does not take ownership of the buffers passed to it.
-  sd = i::ScriptData::New(reinterpret_cast<const char*>(cd->data), cd->length);
-  sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
-  sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
-      200;
-  const char* script3 = "function foo(){ return 7;}\n"
-      "function bar(){ return 6 + 7;}  foo();";
-  v8::ScriptCompiler::Source source3(
-      v8_str(script3),
-      new v8::ScriptCompiler::CachedData(
-          reinterpret_cast<const uint8_t*>(sd->Data()), sd->Length()));
-  compiled_script =
-      v8::ScriptCompiler::CompileUnbound(isolate, &source3);
-  CHECK(try_catch.HasCaught());
-  {
-    String::Utf8Value exception_value(try_catch.Message()->Get());
-    CHECK_EQ("Uncaught SyntaxError: Invalid cached data for function bar",
-             *exception_value);
-  }
-  CHECK(compiled_script.IsEmpty());
-  try_catch.Reset();
-  delete sd;
-
-  // Try passing in cached data which is obviously invalid (wrong length).
-  sd = i::ScriptData::New(reinterpret_cast<const char*>(cd->data), cd->length);
-  const char* script4 =
-      "function foo(){ return 8;}\n"
-      "function bar(){ return 6 + 7;}  foo();";
-  v8::ScriptCompiler::Source source4(
-      v8_str(script4),
-      new v8::ScriptCompiler::CachedData(
-          reinterpret_cast<const uint8_t*>(sd->Data()), sd->Length() - 1));
-  compiled_script =
-      v8::ScriptCompiler::CompileUnbound(isolate, &source4);
-  CHECK(try_catch.HasCaught());
-  {
-    String::Utf8Value exception_value(try_catch.Message()->Get());
-    CHECK_EQ("Uncaught SyntaxError: Invalid cached data",
-             *exception_value);
-  }
-  CHECK(compiled_script.IsEmpty());
-  delete sd;
-}
-
-
 // This tests that we do not allow dictionary load/call inline caches
 // to use functions that have not yet been compiled.  The potential
 // problem of loading a function that has not yet been compiled can
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index db6b9da..33528fb 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -502,9 +502,10 @@
   v8::HandleScope scope(env->GetIsolate());
   v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
 
-  CompileRun("k = {}; v = {};\n"
-             "ws = new WeakSet(); ws.add(k); ws.add(v);\n"
-             "wm = new WeakMap(); wm.set(k, v);\n");
+  CompileRun(
+      "k = {}; v = {}; s = 'str';\n"
+      "ws = new WeakSet(); ws.add(k); ws.add(v); ws[s] = s;\n"
+      "wm = new WeakMap(); wm.set(k, v); wm[s] = s;\n");
   const v8::HeapSnapshot* snapshot =
       heap_profiler->TakeHeapSnapshot(v8_str("WeakCollections"));
   CHECK(ValidateSnapshot(snapshot));
@@ -515,6 +516,9 @@
   const v8::HeapGraphNode* v =
       GetProperty(global, v8::HeapGraphEdge::kProperty, "v");
   CHECK_NE(NULL, v);
+  const v8::HeapGraphNode* s =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "s");
+  CHECK_NE(NULL, s);
 
   const v8::HeapGraphNode* ws =
       GetProperty(global, v8::HeapGraphEdge::kProperty, "ws");
@@ -535,6 +539,10 @@
     }
   }
   CHECK_EQ(1, weak_entries);
+  const v8::HeapGraphNode* ws_s =
+      GetProperty(ws, v8::HeapGraphEdge::kProperty, "str");
+  CHECK_NE(NULL, ws_s);
+  CHECK_EQ(static_cast<int>(s->GetId()), static_cast<int>(ws_s->GetId()));
 
   const v8::HeapGraphNode* wm =
       GetProperty(global, v8::HeapGraphEdge::kProperty, "wm");
@@ -556,6 +564,85 @@
     }
   }
   CHECK_EQ(2, weak_entries);
+  const v8::HeapGraphNode* wm_s =
+      GetProperty(wm, v8::HeapGraphEdge::kProperty, "str");
+  CHECK_NE(NULL, wm_s);
+  CHECK_EQ(static_cast<int>(s->GetId()), static_cast<int>(wm_s->GetId()));
+}
+
+
+TEST(HeapSnapshotCollection) {
+  i::FLAG_harmony_collections = true;
+
+  LocalContext env;
+  v8::HandleScope scope(env->GetIsolate());
+  v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+  CompileRun(
+      "k = {}; v = {}; s = 'str';\n"
+      "set = new Set(); set.add(k); set.add(v); set[s] = s;\n"
+      "map = new Map(); map.set(k, v); map[s] = s;\n");
+  const v8::HeapSnapshot* snapshot =
+      heap_profiler->TakeHeapSnapshot(v8_str("Collections"));
+  CHECK(ValidateSnapshot(snapshot));
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  const v8::HeapGraphNode* k =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "k");
+  CHECK_NE(NULL, k);
+  const v8::HeapGraphNode* v =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "v");
+  CHECK_NE(NULL, v);
+  const v8::HeapGraphNode* s =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "s");
+  CHECK_NE(NULL, s);
+
+  const v8::HeapGraphNode* set =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "set");
+  CHECK_NE(NULL, set);
+  CHECK_EQ(v8::HeapGraphNode::kObject, set->GetType());
+  CHECK_EQ(v8_str("Set"), set->GetName());
+
+  const v8::HeapGraphNode* set_table =
+      GetProperty(set, v8::HeapGraphEdge::kInternal, "table");
+  CHECK_EQ(v8::HeapGraphNode::kArray, set_table->GetType());
+  CHECK_GT(set_table->GetChildrenCount(), 0);
+  int entries = 0;
+  for (int i = 0, count = set_table->GetChildrenCount(); i < count; ++i) {
+    const v8::HeapGraphEdge* prop = set_table->GetChild(i);
+    const v8::SnapshotObjectId to_node_id = prop->GetToNode()->GetId();
+    if (to_node_id == k->GetId() || to_node_id == v->GetId()) {
+      ++entries;
+    }
+  }
+  CHECK_EQ(2, entries);
+  const v8::HeapGraphNode* set_s =
+      GetProperty(set, v8::HeapGraphEdge::kProperty, "str");
+  CHECK_NE(NULL, set_s);
+  CHECK_EQ(static_cast<int>(s->GetId()), static_cast<int>(set_s->GetId()));
+
+  const v8::HeapGraphNode* map =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, "map");
+  CHECK_NE(NULL, map);
+  CHECK_EQ(v8::HeapGraphNode::kObject, map->GetType());
+  CHECK_EQ(v8_str("Map"), map->GetName());
+
+  const v8::HeapGraphNode* map_table =
+      GetProperty(map, v8::HeapGraphEdge::kInternal, "table");
+  CHECK_EQ(v8::HeapGraphNode::kArray, map_table->GetType());
+  CHECK_GT(map_table->GetChildrenCount(), 0);
+  entries = 0;
+  for (int i = 0, count = map_table->GetChildrenCount(); i < count; ++i) {
+    const v8::HeapGraphEdge* prop = map_table->GetChild(i);
+    const v8::SnapshotObjectId to_node_id = prop->GetToNode()->GetId();
+    if (to_node_id == k->GetId() || to_node_id == v->GetId()) {
+      ++entries;
+    }
+  }
+  CHECK_EQ(2, entries);
+  const v8::HeapGraphNode* map_s =
+      GetProperty(map, v8::HeapGraphEdge::kProperty, "str");
+  CHECK_NE(NULL, map_s);
+  CHECK_EQ(static_cast<int>(s->GetId()), static_cast<int>(map_s->GetId()));
 }
 
 
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index b12098a..8a1e429 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -157,8 +157,7 @@
     preparser.set_allow_lazy(true);
     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
-    i::ScriptData data(log.ExtractData());
-    CHECK(!data.has_error());
+    CHECK(!log.HasError());
   }
 
   for (int i = 0; fail_tests[i]; i++) {
@@ -173,8 +172,7 @@
     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     // Even in the case of a syntax error, kPreParseSuccess is returned.
     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
-    i::ScriptData data(log.ExtractData());
-    CHECK(data.has_error());
+    CHECK(log.HasError());
   }
 }
 
@@ -306,8 +304,7 @@
     preparser.set_allow_natives_syntax(true);
     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
-    i::ScriptData data(log.ExtractData());
-    CHECK(!data.has_error());
+    CHECK(!log.HasError());
   }
 }
 
@@ -339,9 +336,7 @@
     preparser.set_allow_lazy(true);
     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
-    i::ScriptData data(log.ExtractData());
-    // Data contains syntax error.
-    CHECK(data.has_error());
+    CHECK(log.HasError());
   }
 }
 
@@ -407,8 +402,7 @@
   i::PreParser::PreParseResult result = preparser.PreParseProgram();
   // Even in the case of a syntax error, kPreParseSuccess is returned.
   CHECK_EQ(i::PreParser::kPreParseSuccess, result);
-  i::ScriptData data(log.ExtractData());
-  CHECK(data.has_error());
+  CHECK(log.HasError());
 }
 
 
@@ -438,15 +432,15 @@
   preparser.set_allow_lazy(true);
   i::PreParser::PreParseResult result = preparser.PreParseProgram();
   CHECK_EQ(i::PreParser::kPreParseSuccess, result);
-  i::ScriptData data(log.ExtractData());
-  CHECK(!data.has_error());
-  data.Initialize();
+  i::ScriptData* sd = log.GetScriptData();
+  i::ParseData pd(sd);
+  pd.Initialize();
 
   int first_function =
       static_cast<int>(strstr(program, "function") - program);
   int first_lbrace = first_function + i::StrLength("function () ");
   CHECK_EQ('{', program[first_lbrace]);
-  i::FunctionEntry entry1 = data.GetFunctionEntry(first_lbrace);
+  i::FunctionEntry entry1 = pd.GetFunctionEntry(first_lbrace);
   CHECK(!entry1.is_valid());
 
   int second_function =
@@ -454,9 +448,10 @@
   int second_lbrace =
       second_function + i::StrLength("function () ");
   CHECK_EQ('{', program[second_lbrace]);
-  i::FunctionEntry entry2 = data.GetFunctionEntry(second_lbrace);
+  i::FunctionEntry entry2 = pd.GetFunctionEntry(second_lbrace);
   CHECK(entry2.is_valid());
   CHECK_EQ('}', program[entry2.end_pos() - 1]);
+  delete sd;
 }
 
 
@@ -1134,20 +1129,41 @@
 }
 
 
-i::Handle<i::String> FormatMessage(i::ScriptData* data) {
+const char* ReadString(unsigned* start) {
+  int length = start[0];
+  char* result = i::NewArray<char>(length + 1);
+  for (int i = 0; i < length; i++) {
+    result[i] = start[i + 1];
+  }
+  result[length] = '\0';
+  return result;
+}
+
+
+i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) {
   i::Isolate* isolate = CcTest::i_isolate();
   i::Factory* factory = isolate->factory();
-  const char* message = data->BuildMessage();
+  const char* message =
+      ReadString(&data[i::PreparseDataConstants::kMessageTextPos]);
   i::Handle<i::String> format = v8::Utils::OpenHandle(
       *v8::String::NewFromUtf8(CcTest::isolate(), message));
-  const char* arg = data->BuildArg();
-  i::Handle<i::JSArray> args_array = factory->NewJSArray(arg == NULL ? 0 : 1);
-  if (arg != NULL) {
-    i::JSArray::SetElement(
-        args_array, 0, v8::Utils::OpenHandle(*v8::String::NewFromUtf8(
-                                                  CcTest::isolate(), arg)),
-        NONE, i::SLOPPY).Check();
+  int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos];
+  const char* arg = NULL;
+  i::Handle<i::JSArray> args_array;
+  if (arg_count == 1) {
+    // Position after text found by skipping past length field and
+    // length field content words.
+    int pos = i::PreparseDataConstants::kMessageTextPos + 1 +
+              data[i::PreparseDataConstants::kMessageTextPos];
+    arg = ReadString(&data[pos]);
+    args_array = factory->NewJSArray(1);
+    i::JSArray::SetElement(args_array, 0, v8::Utils::OpenHandle(*v8_str(arg)),
+                           NONE, i::SLOPPY).Check();
+  } else {
+    CHECK_EQ(0, arg_count);
+    args_array = factory->NewJSArray(0);
   }
+
   i::Handle<i::JSObject> builtins(isolate->js_builtins_object());
   i::Handle<i::Object> format_fun = i::Object::GetProperty(
       isolate, builtins, "FormatMessage").ToHandleChecked();
@@ -1157,6 +1173,7 @@
   CHECK(result->IsString());
   i::DeleteArray(message);
   i::DeleteArray(arg);
+  data.Dispose();
   return i::Handle<i::String>::cast(result);
 }
 
@@ -1211,7 +1228,8 @@
     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
   }
-  i::ScriptData data(log.ExtractData());
+
+  bool preparse_error = log.HasError();
 
   // Parse the data
   i::FunctionLiteral* function;
@@ -1246,7 +1264,7 @@
       CHECK(false);
     }
 
-    if (!data.has_error()) {
+    if (!preparse_error) {
       v8::base::OS::Print(
           "Parser failed on:\n"
           "\t%s\n"
@@ -1257,7 +1275,8 @@
       CHECK(false);
     }
     // Check that preparser and parser produce the same error.
-    i::Handle<i::String> preparser_message = FormatMessage(&data);
+    i::Handle<i::String> preparser_message =
+        FormatMessage(log.ErrorMessageData());
     if (!i::String::Equals(message_string, preparser_message)) {
       v8::base::OS::Print(
           "Expected parser and preparser to produce the same error on:\n"
@@ -1270,14 +1289,15 @@
           preparser_message->ToCString().get());
       CHECK(false);
     }
-  } else if (data.has_error()) {
+  } else if (preparse_error) {
     v8::base::OS::Print(
         "Preparser failed on:\n"
         "\t%s\n"
         "with error:\n"
         "\t%s\n"
         "However, the parser succeeded",
-        source->ToCString().get(), FormatMessage(&data)->ToCString().get());
+        source->ToCString().get(),
+        FormatMessage(log.ErrorMessageData())->ToCString().get());
     CHECK(false);
   } else if (result == kError) {
     v8::base::OS::Print(
@@ -1708,9 +1728,43 @@
 }
 
 
+TEST(NoErrorsLetSloppyAllModes) {
+  // In sloppy mode, it's okay to use "let" as identifier.
+  const char* context_data[][2] = {
+    { "", "" },
+    { "function f() {", "}" },
+    { "(function f() {", "})" },
+    { NULL, NULL }
+  };
+
+  const char* statement_data[] = {
+    "var let;",
+    "var foo, let;",
+    "try { } catch (let) { }",
+    "function let() { }",
+    "(function let() { })",
+    "function foo(let) { }",
+    "function foo(bar, let) { }",
+    "let = 1;",
+    "var foo = let = 1;",
+    "let * 2;",
+    "++let;",
+    "let++;",
+    "let: 34",
+    "function let(let) { let: let(let + let(0)); }",
+    "({ let: 1 })",
+    "({ get let() { 1 } })",
+    "let(100)",
+    NULL
+  };
+
+  RunParserSyncTest(context_data, statement_data, kSuccess);
+}
+
+
 TEST(NoErrorsYieldSloppyAllModes) {
   // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
-  // generator (see next test).
+  // generator (see other test).
   const char* context_data[][2] = {
     { "", "" },
     { "function not_gen() {", "}" },
@@ -1728,13 +1782,15 @@
     "function foo(bar, yield) { }",
     "yield = 1;",
     "var foo = yield = 1;",
+    "yield * 2;",
     "++yield;",
     "yield++;",
     "yield: 34",
-    "function yield(yield) { yield: yield (yield + yield (0)); }",
+    "function yield(yield) { yield: yield (yield + yield(0)); }",
     "({ yield: 1 })",
     "({ get yield() { 1 } })",
-    "yield (100)",
+    "yield(100)",
+    "yield[100]",
     NULL
   };
 
@@ -1766,20 +1822,20 @@
     "(function * yield() { })",
     "yield = 1;",
     "var foo = yield = 1;",
+    "yield * 2;",
     "++yield;",
     "yield++;",
     "yield: 34",
-    "function yield(yield) { yield: yield (yield + yield (0)); }",
+    "function yield(yield) { yield: yield (yield + yield(0)); }",
     "({ yield: 1 })",
     "({ get yield() { 1 } })",
-    "yield (100)",
+    "yield(100)",
+    "yield[100]",
     NULL
   };
 
   // This test requires kAllowGenerators to succeed.
-  static const ParserFlag always_true_flags[] = {
-    kAllowGenerators
-  };
+  static const ParserFlag always_true_flags[] = { kAllowGenerators };
   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
                     always_true_flags, 1);
 }
@@ -2165,22 +2221,20 @@
         factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
     i::Handle<i::Script> script = factory->NewScript(source);
     i::CompilationInfoWithZone info(script);
-    i::ScriptData* data = NULL;
-    info.SetCachedData(&data, i::PRODUCE_CACHED_DATA);
+    i::ScriptData* sd = NULL;
+    info.SetCachedData(&sd, i::PRODUCE_CACHED_DATA);
     i::Parser::Parse(&info, true);
-    CHECK(data);
-    CHECK(!data->HasError());
+    i::ParseData pd(sd);
 
-    if (data->function_count() != test_cases[i].functions) {
+    if (pd.FunctionCount() != test_cases[i].functions) {
       v8::base::OS::Print(
           "Expected preparse data for program:\n"
           "\t%s\n"
           "to contain %d functions, however, received %d functions.\n",
-          program, test_cases[i].functions,
-          data->function_count());
+          program, test_cases[i].functions, pd.FunctionCount());
       CHECK(false);
     }
-    delete data;
+    delete sd;
   }
 }
 
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index c29f51f..d692ffc 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -177,9 +177,9 @@
       fclose(fp_);
     }
   }
-  virtual void Put(int byte, const char* description) {
+  virtual void Put(byte b, const char* description) {
     if (fp_ != NULL) {
-      fputc(byte, fp_);
+      fputc(b, fp_);
     }
   }
   virtual int Position() {
diff --git a/test/mjsunit/harmony/block-early-errors.js b/test/mjsunit/harmony/block-early-errors.js
index 791f001..8ed5ea8 100644
--- a/test/mjsunit/harmony/block-early-errors.js
+++ b/test/mjsunit/harmony/block-early-errors.js
@@ -30,7 +30,6 @@
 function CheckException(e) {
   var string = e.toString();
   assertInstanceof(e, SyntaxError);
-  assertTrue(string.indexOf("Illegal let") >= 0);
 }
 
 function Check(str) {
@@ -49,7 +48,7 @@
 }
 
 // Check for early syntax errors when using let
-// declarations outside of extended mode.
+// declarations outside of strict mode.
 Check("let x;");
 Check("let x = 1;");
 Check("let x, y;");
diff --git a/test/mjsunit/harmony/iteration-syntax.js b/test/mjsunit/harmony/iteration-syntax.js
index 3bda78e..015523d 100644
--- a/test/mjsunit/harmony/iteration-syntax.js
+++ b/test/mjsunit/harmony/iteration-syntax.js
@@ -25,7 +25,7 @@
 // (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: --harmony-iteration --harmony-scoping
+// Flags: --harmony-iteration --harmony-scoping --use-strict
 
 // Test for-of syntax.
 
diff --git a/tools/testrunner/local/execution.py b/tools/testrunner/local/execution.py
index a6dce63..36ce7be 100644
--- a/tools/testrunner/local/execution.py
+++ b/tools/testrunner/local/execution.py
@@ -65,6 +65,7 @@
     self.perf_data_manager = perfdata.PerfDataManager(self.datapath)
     self.perfdata = self.perf_data_manager.GetStore(context.arch, context.mode)
     self.perf_failures = False
+    self.printed_allocations = False
     self.tests = [ t for s in suites for t in s.tests ]
     if not context.no_sorting:
       for t in self.tests:
@@ -149,6 +150,15 @@
     return not has_unexpected_output
 
   def _ProcessTestPredictable(self, test, result, pool):
+    def HasDifferentAllocations(output1, output2):
+      def AllocationStr(stdout):
+        for line in reversed((stdout or "").splitlines()):
+          if line.startswith("### Allocations = "):
+            self.printed_allocations = True
+            return line
+        return ""
+      return (AllocationStr(output1.stdout) != AllocationStr(output2.stdout))
+
     # Always pass the test duration for the database update.
     test.duration = result[2]
     if test.run == 1 and result[1].HasTimedOut():
@@ -159,10 +169,10 @@
       self.remaining -= 1
       self.failed.append(test)
       self.indicator.HasRun(test, True)
-    if test.run > 1 and test.output != result[1]:
-      # From the second run on, check for differences. If a difference is
-      # found, call the indicator twice to report both tests. All runs of each
-      # test are counted as one for the statistic.
+    if test.run > 1 and HasDifferentAllocations(test.output, result[1]):
+      # From the second run on, check for different allocations. If a
+      # difference is found, call the indicator twice to report both tests.
+      # All runs of each test are counted as one for the statistic.
       self.indicator.AboutToRun(test)
       self.remaining -= 1
       self.failed.append(test)
@@ -233,6 +243,8 @@
     if queued_exception:
       raise queued_exception
 
+    # Make sure that any allocations were printed in predictable mode.
+    assert not self.context.predictable or self.printed_allocations
 
   def GetCommand(self, test):
     d8testflag = []
diff --git a/tools/testrunner/objects/output.py b/tools/testrunner/objects/output.py
index 6b5b0cd..87b4c84 100644
--- a/tools/testrunner/objects/output.py
+++ b/tools/testrunner/objects/output.py
@@ -38,12 +38,6 @@
     self.stdout = stdout
     self.stderr = stderr
 
-  def __ne__(self, other):
-    return (self.exit_code != other.exit_code or
-            self.timed_out != other.timed_out or
-            self.stdout != other.stdout or
-            self.stderr != other.stderr)
-
   def HasCrashed(self):
     if utils.IsWindows():
       return 0x80000000 & self.exit_code and not (0x3FFFFF00 & self.exit_code)