Version 2.5.3

Fixed a bug that prevents constants from overwriting function values in object literals (issue 907).

Fixed a bug with reporting of impossible nested calls of DOM functions (issue http://crbug.com/60753).


git-svn-id: http://v8.googlecode.com/svn/trunk@5748 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index 2df31df..617922d 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1155,13 +1155,13 @@
 
 ScriptData* ScriptData::PreCompile(const char* input, int length) {
   unibrow::Utf8InputBuffer<> buf(input, length);
-  return i::Parser::PreParse(i::Handle<i::String>(), &buf, NULL);
+  return i::ParserApi::PreParse(i::Handle<i::String>(), &buf, NULL);
 }
 
 
 ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
   i::Handle<i::String> str = Utils::OpenHandle(*source);
-  return i::Parser::PreParse(str, NULL, NULL);
+  return i::ParserApi::PreParse(str, NULL, NULL);
 }
 
 
diff --git a/src/apiutils.h b/src/apiutils.h
index 8c791eb..1313dda 100644
--- a/src/apiutils.h
+++ b/src/apiutils.h
@@ -29,7 +29,6 @@
 #define V8_APIUTILS_H_
 
 namespace v8 {
-
 class ImplementationUtilities {
  public:
   static v8::Handle<v8::Primitive> Undefined();
@@ -45,12 +44,21 @@
     return that->names_;
   }
 
-  static v8::Arguments NewArguments(Local<Value> data,
-                                    Local<Object> holder,
-                                    Local<Function> callee,
-                                    bool is_construct_call,
-                                    void** argv, int argc) {
-    return v8::Arguments(data, holder, callee, is_construct_call, argv, argc);
+  // Packs additional parameters for the NewArguments function. |implicit_args|
+  // is a pointer to the last element of 3-elements array controlled by GC.
+  static void PrepareArgumentsData(internal::Object** implicit_args,
+                                   internal::Object* data,
+                                   internal::JSFunction* callee,
+                                   internal::Object* holder) {
+    implicit_args[v8::Arguments::kDataIndex] = data;
+    implicit_args[v8::Arguments::kCalleeIndex] = callee;
+    implicit_args[v8::Arguments::kHolderIndex] = holder;
+  }
+
+  static v8::Arguments NewArguments(internal::Object** implicit_args,
+                                    internal::Object** argv, int argc,
+                                    bool is_construct_call) {
+    return v8::Arguments(implicit_args, argv, argc, is_construct_call);
   }
 
   // Introduce an alias for the handle scope data to allow non-friends
diff --git a/src/arguments.h b/src/arguments.h
index c17f4cf..d51c9e4 100644
--- a/src/arguments.h
+++ b/src/arguments.h
@@ -84,6 +84,15 @@
     values_[1] = holder;
     values_[0] = data;
   }
+
+  inline CustomArguments() {
+#ifdef DEBUG
+    for (size_t i = 0; i < ARRAY_SIZE(values_); i++) {
+      values_[i] = reinterpret_cast<Object*>(kZapValue);
+    }
+#endif
+  }
+
   void IterateInstance(ObjectVisitor* v);
   Object** end() { return values_ + ARRAY_SIZE(values_) - 1; }
  private:
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 7d368bf..ebbd9b1 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -1004,7 +1004,7 @@
   int h = ((branch_offset & 2) >> 1)*B24;
   int imm24 = branch_offset >> 2;
   ASSERT(is_int24(imm24));
-  emit(15 << 28 | B27 | B25 | h | (imm24 & Imm24Mask));
+  emit(nv | B27 | B25 | h | (imm24 & Imm24Mask));
 }
 
 
@@ -1634,15 +1634,29 @@
 
 
 // Exception-generating instructions and debugging support.
-void Assembler::stop(const char* msg) {
+// Stops with a non-negative code less than kNumOfWatchedStops support
+// enabling/disabling and a counter feature. See simulator-arm.h .
+void Assembler::stop(const char* msg, Condition cond, int32_t code) {
 #ifndef __arm__
-  // The simulator handles these special instructions and stops execution.
-  emit(15 << 28 | ((intptr_t) msg));
+  // See constants-arm.h SoftwareInterruptCodes. Unluckily the Assembler and
+  // Simulator do not share constants declaration.
+  ASSERT(code >= kDefaultStopCode);
+  static const uint32_t kStopInterruptCode = 1 << 23;
+  static const uint32_t kMaxStopCode = kStopInterruptCode - 1;
+  // The Simulator will handle the stop instruction and get the message address.
+  // It expects to find the address just after the svc instruction.
+  BlockConstPoolFor(2);
+  if (code >= 0) {
+    svc(kStopInterruptCode + code, cond);
+  } else {
+    svc(kStopInterruptCode + kMaxStopCode, cond);
+  }
+  emit(reinterpret_cast<Instr>(msg));
 #else  // def __arm__
 #ifdef CAN_USE_ARMV5_INSTRUCTIONS
   bkpt(0);
 #else  // ndef CAN_USE_ARMV5_INSTRUCTIONS
-  swi(0x9f0001);
+  svc(0x9f0001);
 #endif  // ndef CAN_USE_ARMV5_INSTRUCTIONS
 #endif  // def __arm__
 }
@@ -1654,7 +1668,7 @@
 }
 
 
-void Assembler::swi(uint32_t imm24, Condition cond) {
+void Assembler::svc(uint32_t imm24, Condition cond) {
   ASSERT(is_uint24(imm24));
   emit(cond | 15*B24 | imm24);
 }
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 1c4fd60..5b647a7 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -904,10 +904,13 @@
   void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
 
   // Exception-generating instructions and debugging support
-  void stop(const char* msg);
+  static const int kDefaultStopCode = -1;
+  void stop(const char* msg,
+            Condition cond = al,
+            int32_t code = kDefaultStopCode);
 
   void bkpt(uint32_t imm16);  // v5 and above
-  void swi(uint32_t imm24, Condition cond = al);
+  void svc(uint32_t imm24, Condition cond = al);
 
   // Coprocessor instructions
 
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 0c060f0..70ff244 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -3596,6 +3596,12 @@
     frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
   }
   frame_->EmitPush(r0);  // save the result
+
+  // Mark all computed expressions that are bound to a key that
+  // is shadowed by a later occurrence of the same key. For the
+  // marked expressions, no store code is emitted.
+  node->CalculateEmitStore();
+
   for (int i = 0; i < node->properties()->length(); i++) {
     // At the start of each iteration, the top of stack contains
     // the newly created object literal.
@@ -3612,11 +3618,15 @@
         if (key->handle()->IsSymbol()) {
           Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
           Load(value);
-          frame_->PopToR0();
-          // Fetch the object literal.
-          frame_->SpillAllButCopyTOSToR1();
-          __ mov(r2, Operand(key->handle()));
-          frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
+          if (property->emit_store()) {
+            frame_->PopToR0();
+            // Fetch the object literal.
+            frame_->SpillAllButCopyTOSToR1();
+            __ mov(r2, Operand(key->handle()));
+            frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
+          } else {
+            frame_->Drop();
+          }
           break;
         }
         // else fall through
@@ -3624,7 +3634,11 @@
         frame_->Dup();
         Load(key);
         Load(value);
-        frame_->CallRuntime(Runtime::kSetProperty, 3);
+        if (property->emit_store()) {
+          frame_->CallRuntime(Runtime::kSetProperty, 3);
+        } else {
+          frame_->Drop(3);
+        }
         break;
       }
       case ObjectLiteral::Property::SETTER: {
diff --git a/src/arm/constants-arm.h b/src/arm/constants-arm.h
index b2b5cb5..123c5e7 100644
--- a/src/arm/constants-arm.h
+++ b/src/arm/constants-arm.h
@@ -186,12 +186,18 @@
 
 // Special Software Interrupt codes when used in the presence of the ARM
 // simulator.
+// svc (formerly swi) provides a 24bit immediate value. Use bits 22:0 for
+// standard SoftwareInterrupCode. Bit 23 is reserved for the stop feature.
 enum SoftwareInterruptCodes {
   // transition to C code
   call_rt_redirected = 0x10,
   // break point
-  break_point = 0x20
+  break_point = 0x20,
+  // stop
+  stop = 1 << 23
 };
+static const int32_t kStopCodeMask = stop - 1;
+static const uint32_t kMaxStopCode = stop - 1;
 
 
 // Type of VFP register. Determines register encoding.
@@ -325,7 +331,7 @@
   inline int SImmed24Field() const { return ((InstructionBits() << 8) >> 8); }
 
   // Fields used in Software interrupt instructions
-  inline SoftwareInterruptCodes SwiField() const {
+  inline SoftwareInterruptCodes SvcField() const {
     return static_cast<SoftwareInterruptCodes>(Bits(23, 0));
   }
 
diff --git a/src/arm/cpu-arm.cc b/src/arm/cpu-arm.cc
index a3bf483..e998b6f 100644
--- a/src/arm/cpu-arm.cc
+++ b/src/arm/cpu-arm.cc
@@ -70,7 +70,7 @@
       // __arm__ may be defined in thumb mode.
       register uint32_t scno asm("r7") = __ARM_NR_cacheflush;
       asm volatile(
-          "swi 0x0"
+          "svc 0x0"
           : "=r" (beg)
           : "0" (beg), "r" (end), "r" (flg), "r" (scno));
     #else
@@ -83,7 +83,7 @@
           ".ARM            \n"
       "1:  push {r7}       \n\t"
           "mov r7, %4      \n\t"
-          "swi 0x0         \n\t"
+          "svc 0x0         \n\t"
           "pop {r7}        \n\t"
       "@   Enter THUMB Mode\n\t"
           "adr r3, 2f+1    \n\t"
@@ -98,20 +98,20 @@
     #if defined (__arm__) && !defined(__thumb__)
       // __arm__ may be defined in thumb mode.
       asm volatile(
-          "swi %1"
+          "svc %1"
           : "=r" (beg)
           : "i" (__ARM_NR_cacheflush), "0" (beg), "r" (end), "r" (flg));
     #else
       // Do not use the value of __ARM_NR_cacheflush in the inline assembly
       // below, because the thumb mode value would be used, which would be
-      // wrong, since we switch to ARM mode before executing the swi instruction
+      // wrong, since we switch to ARM mode before executing the svc instruction
       asm volatile(
       "@   Enter ARM Mode  \n\t"
           "adr r3, 1f      \n\t"
           "bx  r3          \n\t"
           ".ALIGN 4        \n\t"
           ".ARM            \n"
-      "1:  swi 0x9f0002    \n"
+      "1:  svc 0x9f0002    \n"
       "@   Enter THUMB Mode\n\t"
           "adr r3, 2f+1    \n\t"
           "bx  r3          \n\t"
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index 5122f43..4e7580f 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -108,7 +108,7 @@
   void PrintShiftImm(Instr* instr);
   void PrintShiftSat(Instr* instr);
   void PrintPU(Instr* instr);
-  void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
+  void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
 
   // Handle formatting of instructions and their options.
   int FormatRegister(Instr* instr, const char* option);
@@ -126,8 +126,8 @@
   void DecodeType4(Instr* instr);
   void DecodeType5(Instr* instr);
   void DecodeType6(Instr* instr);
-  void DecodeType7(Instr* instr);
-  void DecodeUnconditional(Instr* instr);
+  // Type 7 includes special Debugger instructions.
+  int DecodeType7(Instr* instr);
   // For VFP support.
   void DecodeTypeVFP(Instr* instr);
   void DecodeType6CoprocessorIns(Instr* instr);
@@ -290,8 +290,8 @@
 
 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
 // the FormatOption method.
-void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
-  switch (swi) {
+void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
+  switch (svc) {
     case call_rt_redirected:
       Print("call_rt_redirected");
       return;
@@ -299,9 +299,16 @@
       Print("break_point");
       return;
     default:
-      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
-                                           "%d",
-                                           swi);
+      if (svc >= stop) {
+        out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                             "%d - 0x%x",
+                                             svc & kStopCodeMask,
+                                             svc & kStopCodeMask);
+      } else {
+        out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                             "%d",
+                                             svc);
+      }
       return;
   }
 }
@@ -553,9 +560,9 @@
           PrintShiftRm(instr);
           return 8;
         }
-      } else if (format[1] == 'w') {  // 'swi
-        ASSERT(STRING_STARTS_WITH(format, "swi"));
-        PrintSoftwareInterrupt(instr->SwiField());
+      } else if (format[1] == 'v') {  // 'svc
+        ASSERT(STRING_STARTS_WITH(format, "svc"));
+        PrintSoftwareInterrupt(instr->SvcField());
         return 3;
       } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
         ASSERT(STRING_STARTS_WITH(format, "sign"));
@@ -1004,72 +1011,27 @@
 }
 
 
-void Decoder::DecodeType7(Instr* instr) {
+int Decoder::DecodeType7(Instr* instr) {
   if (instr->Bit(24) == 1) {
-    Format(instr, "swi'cond 'swi");
+    if (instr->SvcField() >= stop) {
+      Format(instr, "stop'cond 'svc");
+      // Also print the stop message. Its address is encoded
+      // in the following 4 bytes.
+      out_buffer_pos_ +=
+        v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                          "\n  %p  %08x       stop message: %s",
+                          reinterpret_cast<int32_t*>(instr + Instr::kInstrSize),
+                          *reinterpret_cast<char**>(instr + Instr::kInstrSize),
+                          *reinterpret_cast<char**>(instr + Instr::kInstrSize));
+      // We have decoded 2 * Instr::kInstrSize bytes.
+      return 2 * Instr::kInstrSize;
+    } else {
+      Format(instr, "svc'cond 'svc");
+    }
   } else {
     DecodeTypeVFP(instr);
   }
-}
-
-void Decoder::DecodeUnconditional(Instr* instr) {
-  if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 && instr->HasL()) {
-    Format(instr, "'memop'h'pu 'rd, ");
-    bool immediate = instr->HasB();
-    switch (instr->PUField()) {
-      case 0: {
-        // Post index, negative.
-        if (instr->HasW()) {
-          Unknown(instr);
-          break;
-        }
-        if (immediate) {
-          Format(instr, "['rn], #-'imm12");
-        } else {
-          Format(instr, "['rn], -'rm");
-        }
-        break;
-      }
-      case 1: {
-        // Post index, positive.
-        if (instr->HasW()) {
-          Unknown(instr);
-          break;
-        }
-        if (immediate) {
-          Format(instr, "['rn], #+'imm12");
-        } else {
-          Format(instr, "['rn], +'rm");
-        }
-        break;
-      }
-      case 2: {
-        // Pre index or offset, negative.
-        if (immediate) {
-          Format(instr, "['rn, #-'imm12]'w");
-        } else {
-          Format(instr, "['rn, -'rm]'w");
-        }
-        break;
-      }
-      case 3: {
-        // Pre index or offset, positive.
-        if (immediate) {
-          Format(instr, "['rn, #+'imm12]'w");
-        } else {
-          Format(instr, "['rn, +'rm]'w");
-        }
-        break;
-      }
-      default: {
-        // The PU field is a 2-bit field.
-        UNREACHABLE();
-        break;
-      }
-    }
-    return;
-  }
-  Format(instr, "break 'msg");
+  return Instr::kInstrSize;
 }
 
 
@@ -1332,7 +1294,7 @@
                                        "%08x       ",
                                        instr->InstructionBits());
   if (instr->ConditionField() == special_condition) {
-    DecodeUnconditional(instr);
+    UNIMPLEMENTED();
     return Instr::kInstrSize;
   }
   switch (instr->TypeField()) {
@@ -1362,8 +1324,7 @@
       break;
     }
     case 7: {
-      DecodeType7(instr);
-      break;
+      return DecodeType7(instr);
     }
     default: {
       // The type field is 3-bits in the ARM encoding.
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 2855ca4..9935e03 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1169,6 +1169,11 @@
   // result_saved is false the result is in r0.
   bool result_saved = false;
 
+  // Mark all computed expressions that are bound to a key that
+  // is shadowed by a later occurrence of the same key. For the
+  // marked expressions, no store code is emitted.
+  expr->CalculateEmitStore();
+
   for (int i = 0; i < expr->properties()->length(); i++) {
     ObjectLiteral::Property* property = expr->properties()->at(i);
     if (property->IsCompileTimeValue()) continue;
@@ -1190,8 +1195,10 @@
           VisitForAccumulatorValue(value);
           __ mov(r2, Operand(key->handle()));
           __ ldr(r1, MemOperand(sp));
-          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
-          EmitCallIC(ic, RelocInfo::CODE_TARGET);
+          if (property->emit_store()) {
+            Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+            EmitCallIC(ic, RelocInfo::CODE_TARGET);
+          }
           break;
         }
         // Fall through.
@@ -1201,7 +1208,11 @@
         __ push(r0);
         VisitForStackValue(key);
         VisitForStackValue(value);
-        __ CallRuntime(Runtime::kSetProperty, 3);
+        if (property->emit_store()) {
+          __ CallRuntime(Runtime::kSetProperty, 3);
+        } else {
+          __ Drop(3);
+        }
         break;
       case ObjectLiteral::Property::GETTER:
       case ObjectLiteral::Property::SETTER:
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index c460f9c..a09afdf 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -544,7 +544,7 @@
   // Probe the stub cache.
   Code::Flags flags =
       Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
-  StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg);
+  StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5);
 
   // If the stub cache probing failed, the receiver might be a value.
   // For value objects, we use the map of the prototype objects for
@@ -583,7 +583,7 @@
 
   // Probe the stub cache for the value object.
   __ bind(&probe);
-  StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg);
+  StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5);
 
   __ bind(&miss);
 }
@@ -858,7 +858,7 @@
   Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC);
-  StubCache::GenerateProbe(masm, flags, r0, r2, r3, no_reg);
+  StubCache::GenerateProbe(masm, flags, r0, r2, r3, r4, r5);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -2163,7 +2163,7 @@
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC);
-  StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg);
+  StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5);
 
   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 534e394..cb91520 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -112,15 +112,29 @@
 
 
 void Debugger::Stop(Instr* instr) {
-  char* str = reinterpret_cast<char*>(instr->InstructionBits() & 0x0fffffff);
-  if (strlen(str) > 0) {
+  // Get the stop code.
+  uint32_t code = instr->SvcField() & kStopCodeMask;
+  // Retrieve the encoded address, which comes just after this stop.
+  char** msg_address =
+    reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize);
+  char* msg = *msg_address;
+  ASSERT(msg != NULL);
+
+  // Update this stop description.
+  if (isWatchedStop(code) && !watched_stops[code].desc) {
+    watched_stops[code].desc = msg;
+  }
+
+  if (strlen(msg) > 0) {
     if (coverage_log != NULL) {
-      fprintf(coverage_log, "%s\n", str);
+      fprintf(coverage_log, "%s\n", msg);
       fflush(coverage_log);
     }
-    instr->SetInstructionBits(0xe1a00000);  // Overwrite with nop.
+    // Overwrite the instruction and address with nops.
+    instr->SetInstructionBits(kNopInstr);
+    reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr);
   }
-  sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
+  sim_->set_pc(sim_->get_pc() + 2 * Instr::kInstrSize);
 }
 
 #else  // ndef GENERATED_CODE_COVERAGE
@@ -130,9 +144,16 @@
 
 
 void Debugger::Stop(Instr* instr) {
-  const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff);
-  PrintF("Simulator hit %s\n", str);
-  sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
+  // Get the stop code.
+  uint32_t code = instr->SvcField() & kStopCodeMask;
+  // Retrieve the encoded address, which comes just after this stop.
+  char* msg = *reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize);
+  // Update this stop description.
+  if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) {
+    sim_->watched_stops[code].desc = msg;
+  }
+  PrintF("Simulator hit %s\n", msg);
+  sim_->set_pc(sim_->get_pc() + 2 * Instr::kInstrSize);
   Debug();
 }
 #endif
@@ -359,6 +380,7 @@
         // use a reasonably large buffer
         v8::internal::EmbeddedVector<char, 256> buffer;
 
+        byte* prev = NULL;
         byte* cur = NULL;
         byte* end = NULL;
 
@@ -368,9 +390,9 @@
         } else if (argc == 2) {
           int32_t value;
           if (GetValue(arg1, &value)) {
-            cur = reinterpret_cast<byte*>(value);
-            // no length parameter passed, assume 10 instructions
-            end = cur + (10 * Instr::kInstrSize);
+            cur = reinterpret_cast<byte*>(sim_->get_pc());
+            // Disassemble <arg1> instructions.
+            end = cur + (value * Instr::kInstrSize);
           }
         } else {
           int32_t value1;
@@ -382,10 +404,10 @@
         }
 
         while (cur < end) {
-          dasm.InstructionDecode(buffer, cur);
+          prev = cur;
+          cur += dasm.InstructionDecode(buffer, cur);
           PrintF("  0x%08x  %s\n",
-                 reinterpret_cast<intptr_t>(cur), buffer.start());
-          cur += Instr::kInstrSize;
+                 reinterpret_cast<intptr_t>(prev), buffer.start());
         }
       } else if (strcmp(cmd, "gdb") == 0) {
         PrintF("relinquishing control to gdb\n");
@@ -418,13 +440,58 @@
         PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
         PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
         PrintF("INEXACT flag: %d; ", sim_->inexact_vfp_flag_);
-      } else if (strcmp(cmd, "unstop") == 0) {
-        intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
+      } else if (strcmp(cmd, "stop") == 0) {
+        int32_t value;
+        intptr_t stop_pc = sim_->get_pc() - 2 * Instr::kInstrSize;
         Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
-        if (stop_instr->ConditionField() == special_condition) {
-          stop_instr->SetInstructionBits(kNopInstr);
+        Instr* msg_address =
+          reinterpret_cast<Instr*>(stop_pc + Instr::kInstrSize);
+        if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
+          // Remove the current stop.
+          if (sim_->isStopInstruction(stop_instr)) {
+            stop_instr->SetInstructionBits(kNopInstr);
+            msg_address->SetInstructionBits(kNopInstr);
+          } else {
+            PrintF("Not at debugger stop.\n");
+          }
+        } else if (argc == 3) {
+          // Print information about all/the specified breakpoint(s).
+          if (strcmp(arg1, "info") == 0) {
+            if (strcmp(arg2, "all") == 0) {
+              PrintF("Stop information:\n");
+              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
+                sim_->PrintStopInfo(i);
+              }
+            } else if (GetValue(arg2, &value)) {
+              sim_->PrintStopInfo(value);
+            } else {
+              PrintF("Unrecognized argument.\n");
+            }
+          } else if (strcmp(arg1, "enable") == 0) {
+            // Enable all/the specified breakpoint(s).
+            if (strcmp(arg2, "all") == 0) {
+              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
+                sim_->EnableStop(i);
+              }
+            } else if (GetValue(arg2, &value)) {
+              sim_->EnableStop(value);
+            } else {
+              PrintF("Unrecognized argument.\n");
+            }
+          } else if (strcmp(arg1, "disable") == 0) {
+            // Disable all/the specified breakpoint(s).
+            if (strcmp(arg2, "all") == 0) {
+              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
+                sim_->DisableStop(i);
+              }
+            } else if (GetValue(arg2, &value)) {
+              sim_->DisableStop(value);
+            } else {
+              PrintF("Unrecognized argument.\n");
+            }
+          }
         } else {
-          PrintF("Not at debugger stop.");
+          PrintF("Wrong usage. Use help command for more information.\n");
         }
       } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
         ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
@@ -455,11 +522,29 @@
         PrintF("  set a break point on the address\n");
         PrintF("del\n");
         PrintF("  delete the breakpoint\n");
-        PrintF("unstop\n");
-        PrintF("  ignore the stop instruction at the current location");
-        PrintF("  from now on\n");
         PrintF("trace (alias 't')\n");
         PrintF("  toogle the tracing of all executed statements\n");
+        PrintF("stop feature:\n");
+        PrintF("  Description:\n");
+        PrintF("    Stops are debug instructions inserted by\n");
+        PrintF("    the Assembler::stop() function.\n");
+        PrintF("    When hitting a stop, the Simulator will\n");
+        PrintF("    stop and and give control to the Debugger.\n");
+        PrintF("    The first %d stop codes are watched:\n",
+               Simulator::kNumOfWatchedStops);
+        PrintF("    - They can be enabled / disabled: the Simulator\n");
+        PrintF("       will / won't stop when hitting them.\n");
+        PrintF("    - The Simulator keeps track of how many times they \n");
+        PrintF("      are met. (See the info command.) Going over a\n");
+        PrintF("      disabled stop still increases its counter. \n");
+        PrintF("  Commands:\n");
+        PrintF("    stop info all/<code> : print infos about number <code>\n");
+        PrintF("      or all stop(s).\n");
+        PrintF("    stop enable/disable all/<code> : enables / disables\n");
+        PrintF("      all or number <code> stop(s)\n");
+        PrintF("    stop unstop\n");
+        PrintF("      ignore the stop instruction at the current location\n");
+        PrintF("      from now on\n");
       } else {
         PrintF("Unknown command: %s\n", cmd);
       }
@@ -643,9 +728,9 @@
 // the simulator.  The external reference will be a function compiled for the
 // host architecture.  We need to call that function instead of trying to
 // execute it with the simulator.  We do that by redirecting the external
-// reference to a swi (software-interrupt) instruction that is handled by
+// reference to a svc (Supervisor Call) instruction that is handled by
 // the simulator.  We write the original destination of the jump just at a known
-// offset from the swi instruction so the simulator knows what to call.
+// offset from the svc instruction so the simulator knows what to call.
 class Redirection {
  public:
   Redirection(void* external_function, bool fp_return)
@@ -1434,8 +1519,8 @@
 // Software interrupt instructions are used by the simulator to call into the
 // C-based V8 runtime.
 void Simulator::SoftwareInterrupt(Instr* instr) {
-  int swi = instr->SwiField();
-  switch (swi) {
+  int svc = instr->SvcField();
+  switch (svc) {
     case call_rt_redirected: {
       // Check if stack is aligned. Error if not aligned is reported below to
       // include information on the function called.
@@ -1505,9 +1590,98 @@
       dbg.Debug();
       break;
     }
+    // stop uses all codes greater than 1 << 23.
     default: {
-      UNREACHABLE();
-      break;
+      if (svc >= (1 << 23)) {
+        uint32_t code = svc & kStopCodeMask;
+        if (isWatchedStop(code)) {
+          IncreaseStopCounter(code);
+        }
+        // Stop if it is enabled, otherwise go on jumping over the stop
+        // and the message address.
+        if (isEnabledStop(code)) {
+          Debugger dbg(this);
+          dbg.Stop(instr);
+        } else {
+          set_pc(get_pc() + 2 * Instr::kInstrSize);
+        }
+      } else {
+        // This is not a valid svc code.
+        UNREACHABLE();
+        break;
+      }
+    }
+  }
+}
+
+
+// Stop helper functions.
+bool Simulator::isStopInstruction(Instr* instr) {
+  return (instr->Bits(27, 24) == 0xF) && (instr->SvcField() >= stop);
+}
+
+
+bool Simulator::isWatchedStop(uint32_t code) {
+  ASSERT(code <= kMaxStopCode);
+  return code < kNumOfWatchedStops;
+}
+
+
+bool Simulator::isEnabledStop(uint32_t code) {
+  ASSERT(code <= kMaxStopCode);
+  // Unwatched stops are always enabled.
+  return !isWatchedStop(code) ||
+    !(watched_stops[code].count & kStopDisabledBit);
+}
+
+
+void Simulator::EnableStop(uint32_t code) {
+  ASSERT(isWatchedStop(code));
+  if (!isEnabledStop(code)) {
+    watched_stops[code].count &= ~kStopDisabledBit;
+  }
+}
+
+
+void Simulator::DisableStop(uint32_t code) {
+  ASSERT(isWatchedStop(code));
+  if (isEnabledStop(code)) {
+    watched_stops[code].count |= kStopDisabledBit;
+  }
+}
+
+
+void Simulator::IncreaseStopCounter(uint32_t code) {
+  ASSERT(code <= kMaxStopCode);
+  ASSERT(isWatchedStop(code));
+  if ((watched_stops[code].count & ~(1 << 31)) == 0x7fffffff) {
+    PrintF("Stop counter for code %i has overflowed.\n"
+           "Enabling this code and reseting the counter to 0.\n", code);
+    watched_stops[code].count = 0;
+    EnableStop(code);
+  } else {
+    watched_stops[code].count++;
+  }
+}
+
+
+// Print a stop status.
+void Simulator::PrintStopInfo(uint32_t code) {
+  ASSERT(code <= kMaxStopCode);
+  if (!isWatchedStop(code)) {
+    PrintF("Stop not watched.");
+  } else {
+    const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
+    int32_t count = watched_stops[code].count & ~kStopDisabledBit;
+    // Don't print the state of unused breakpoints.
+    if (count != 0) {
+      if (watched_stops[code].desc) {
+        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
+               code, code, state, count, watched_stops[code].desc);
+      } else {
+        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
+               code, code, state, count);
+      }
     }
   }
 }
@@ -2216,73 +2390,6 @@
 }
 
 
-void Simulator::DecodeUnconditional(Instr* instr) {
-  if (instr->Bits(7, 4) == 0x0B && instr->Bits(27, 25) == 0 && instr->HasL()) {
-    // Load halfword instruction, either register or immediate offset.
-    int rd = instr->RdField();
-    int rn = instr->RnField();
-    int32_t rn_val = get_register(rn);
-    int32_t addr = 0;
-    int32_t offset;
-    if (instr->Bit(22) == 0) {
-      // Register offset.
-      int rm = instr->RmField();
-      offset = get_register(rm);
-    } else {
-      // Immediate offset
-      offset = instr->Bits(3, 0) + (instr->Bits(11, 8) << 4);
-    }
-    switch (instr->PUField()) {
-      case 0: {
-        // Post index, negative.
-        ASSERT(!instr->HasW());
-        addr = rn_val;
-        rn_val -= offset;
-        set_register(rn, rn_val);
-        break;
-      }
-      case 1: {
-        // Post index, positive.
-        ASSERT(!instr->HasW());
-        addr = rn_val;
-        rn_val += offset;
-        set_register(rn, rn_val);
-        break;
-      }
-      case 2: {
-        // Pre index or offset, negative.
-        rn_val -= offset;
-        addr = rn_val;
-        if (instr->HasW()) {
-          set_register(rn, rn_val);
-        }
-        break;
-      }
-      case 3: {
-        // Pre index or offset, positive.
-        rn_val += offset;
-        addr = rn_val;
-        if (instr->HasW()) {
-          set_register(rn, rn_val);
-        }
-        break;
-      }
-      default: {
-        // The PU field is a 2-bit field.
-        UNREACHABLE();
-        break;
-      }
-    }
-    // Not sign extending, so load as unsigned.
-    uint16_t halfword = ReadH(addr, instr);
-    set_register(rd, halfword);
-  } else {
-    Debugger dbg(this);
-    dbg.Stop(instr);
-  }
-}
-
-
 // void Simulator::DecodeTypeVFP(Instr* instr)
 // The Following ARMv7 VFPv instructions are currently supported.
 // vmov :Sn = Rt
@@ -2655,7 +2762,7 @@
     PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr), buffer.start());
   }
   if (instr->ConditionField() == special_condition) {
-    DecodeUnconditional(instr);
+    UNIMPLEMENTED();
   } else if (ConditionallyExecute(instr)) {
     switch (instr->TypeField()) {
       case 0:
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index e0658fc..3e02348 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -226,6 +226,15 @@
   void HandleRList(Instr* instr, bool load);
   void SoftwareInterrupt(Instr* instr);
 
+  // Stop helper functions.
+  inline bool isStopInstruction(Instr* instr);
+  inline bool isWatchedStop(uint32_t bkpt_code);
+  inline bool isEnabledStop(uint32_t bkpt_code);
+  inline void EnableStop(uint32_t bkpt_code);
+  inline void DisableStop(uint32_t bkpt_code);
+  inline void IncreaseStopCounter(uint32_t bkpt_code);
+  void PrintStopInfo(uint32_t code);
+
   // Read and write memory.
   inline uint8_t ReadBU(int32_t addr);
   inline int8_t ReadB(int32_t addr);
@@ -252,7 +261,6 @@
   void DecodeType5(Instr* instr);
   void DecodeType6(Instr* instr);
   void DecodeType7(Instr* instr);
-  void DecodeUnconditional(Instr* instr);
 
   // Support for VFP.
   void DecodeTypeVFP(Instr* instr);
@@ -317,6 +325,23 @@
   // Registered breakpoints.
   Instr* break_pc_;
   instr_t break_instr_;
+
+  // A stop is watched if its code is less than kNumOfWatchedStops.
+  // Only watched stops support enabling/disabling and the counter feature.
+  static const uint32_t kNumOfWatchedStops = 256;
+
+  // Breakpoint is disabled if bit 31 is set.
+  static const uint32_t kStopDisabledBit = 1 << 31;
+
+  // A stop is enabled, meaning the simulator will stop when meeting the
+  // instruction, if bit 31 of watched_stops[code].count is unset.
+  // The value watched_stops[code].count & ~(1 << 31) indicates how many times
+  // the breakpoint was hit or gone through.
+  struct StopCoundAndDesc {
+    uint32_t count;
+    char* desc;
+  };
+  StopCoundAndDesc watched_stops[kNumOfWatchedStops];
 };
 
 } }  // namespace assembler::arm
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index fbad669..5e29c2e 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -43,43 +43,49 @@
                        Code::Flags flags,
                        StubCache::Table table,
                        Register name,
-                       Register offset) {
+                       Register offset,
+                       Register scratch,
+                       Register scratch2) {
   ExternalReference key_offset(SCTableReference::keyReference(table));
   ExternalReference value_offset(SCTableReference::valueReference(table));
 
-  Label miss;
+  uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
+  uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address());
 
-  // Save the offset on the stack.
-  __ push(offset);
+  // Check the relative positions of the address fields.
+  ASSERT(value_off_addr > key_off_addr);
+  ASSERT((value_off_addr - key_off_addr) % 4 == 0);
+  ASSERT((value_off_addr - key_off_addr) < (256 * 4));
+
+  Label miss;
+  Register offsets_base_addr = scratch;
 
   // Check that the key in the entry matches the name.
-  __ mov(ip, Operand(key_offset));
-  __ ldr(ip, MemOperand(ip, offset, LSL, 1));
+  __ mov(offsets_base_addr, Operand(key_offset));
+  __ ldr(ip, MemOperand(offsets_base_addr, offset, LSL, 1));
   __ cmp(name, ip);
   __ b(ne, &miss);
 
   // Get the code entry from the cache.
-  __ mov(ip, Operand(value_offset));
-  __ ldr(offset, MemOperand(ip, offset, LSL, 1));
+  __ add(offsets_base_addr, offsets_base_addr,
+         Operand(value_off_addr - key_off_addr));
+  __ ldr(scratch2, MemOperand(offsets_base_addr, offset, LSL, 1));
 
   // Check that the flags match what we're looking for.
-  __ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
-  __ and_(offset, offset, Operand(~Code::kFlagsNotUsedInLookup));
-  __ cmp(offset, Operand(flags));
+  __ ldr(scratch2, FieldMemOperand(scratch2, Code::kFlagsOffset));
+  __ bic(scratch2, scratch2, Operand(Code::kFlagsNotUsedInLookup));
+  __ cmp(scratch2, Operand(flags));
   __ b(ne, &miss);
 
-  // Restore offset and re-load code entry from cache.
-  __ pop(offset);
-  __ mov(ip, Operand(value_offset));
-  __ ldr(offset, MemOperand(ip, offset, LSL, 1));
+  // Re-load code entry from cache.
+  __ ldr(offset, MemOperand(offsets_base_addr, offset, LSL, 1));
 
   // Jump to the first instruction in the code stub.
   __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(offset);
 
-  // Miss: Restore offset and fall through.
+  // Miss: fall through.
   __ bind(&miss);
-  __ pop(offset);
 }
 
 
@@ -201,7 +207,8 @@
                               Register receiver,
                               Register name,
                               Register scratch,
-                              Register extra) {
+                              Register extra,
+                              Register extra2) {
   Label miss;
 
   // Make sure that code is valid. The shifting code relies on the
@@ -214,6 +221,18 @@
   // Make sure that there are no register conflicts.
   ASSERT(!scratch.is(receiver));
   ASSERT(!scratch.is(name));
+  ASSERT(!extra.is(receiver));
+  ASSERT(!extra.is(name));
+  ASSERT(!extra.is(scratch));
+  ASSERT(!extra2.is(receiver));
+  ASSERT(!extra2.is(name));
+  ASSERT(!extra2.is(scratch));
+  ASSERT(!extra2.is(extra));
+
+  // Check scratch, extra and extra2 registers are valid.
+  ASSERT(!scratch.is(no_reg));
+  ASSERT(!extra.is(no_reg));
+  ASSERT(!extra2.is(no_reg));
 
   // Check that the receiver isn't a smi.
   __ tst(receiver, Operand(kSmiTagMask));
@@ -229,7 +248,7 @@
           Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
 
   // Probe the primary table.
-  ProbeTable(masm, flags, kPrimary, name, scratch);
+  ProbeTable(masm, flags, kPrimary, name, scratch, extra, extra2);
 
   // Primary miss: Compute hash for secondary probe.
   __ sub(scratch, scratch, Operand(name));
@@ -239,7 +258,7 @@
           Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
 
   // Probe the secondary table.
-  ProbeTable(masm, flags, kSecondary, name, scratch);
+  ProbeTable(masm, flags, kSecondary, name, scratch, extra, extra2);
 
   // Cache miss: Fall-through and let caller handle the miss by
   // entering the runtime system.
diff --git a/src/ast.cc b/src/ast.cc
index 92f1496..bb445c4 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -140,6 +140,7 @@
 
 
 ObjectLiteral::Property::Property(Literal* key, Expression* value) {
+  emit_store_ = true;
   key_ = key;
   value_ = value;
   Object* k = *key->handle();
@@ -156,6 +157,7 @@
 
 
 ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
+  emit_store_ = true;
   key_ = new Literal(value->name());
   value_ = value;
   kind_ = is_getter ? GETTER : SETTER;
@@ -169,6 +171,78 @@
 }
 
 
+void ObjectLiteral::Property::set_emit_store(bool emit_store) {
+  emit_store_ = emit_store;
+}
+
+
+bool ObjectLiteral::Property::emit_store() {
+  return emit_store_;
+}
+
+
+bool IsEqualString(void* first, void* second) {
+  Handle<String> h1(reinterpret_cast<String**>(first));
+  Handle<String> h2(reinterpret_cast<String**>(second));
+  return (*h1)->Equals(*h2);
+}
+
+bool IsEqualSmi(void* first, void* second) {
+  Handle<Smi> h1(reinterpret_cast<Smi**>(first));
+  Handle<Smi> h2(reinterpret_cast<Smi**>(second));
+  return (*h1)->value() == (*h2)->value();
+}
+
+void ObjectLiteral::CalculateEmitStore() {
+  HashMap properties(&IsEqualString);
+  HashMap elements(&IsEqualSmi);
+  for (int i = this->properties()->length() - 1; i >= 0; i--) {
+    ObjectLiteral::Property* property = this->properties()->at(i);
+    Literal* literal = property->key();
+    Handle<Object> handle = literal->handle();
+
+    if (handle->IsNull()) {
+      continue;
+    }
+
+    uint32_t hash;
+    HashMap* table;
+    void* key;
+    uint32_t index;
+    if (handle->IsSymbol()) {
+      Handle<String> name(String::cast(*handle));
+      ASSERT(!name->AsArrayIndex(&index));
+      key = name.location();
+      hash = name->Hash();
+      table = &properties;
+    } else if (handle->ToArrayIndex(&index)) {
+      key = handle.location();
+      hash = index;
+      table = &elements;
+    } else {
+      ASSERT(handle->IsNumber());
+      double num = handle->Number();
+      char arr[100];
+      Vector<char> buffer(arr, ARRAY_SIZE(arr));
+      const char* str = DoubleToCString(num, buffer);
+      Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
+      key = name.location();
+      hash = name->Hash();
+      table = &properties;
+    }
+    // If the key of a computed property is in the table, do not emit
+    // a store for the property later.
+    if (property->kind() == ObjectLiteral::Property::COMPUTED) {
+      if (table->Lookup(literal, hash, false) != NULL) {
+        property->set_emit_store(false);
+      }
+    }
+    // Add key to the table.
+    table->Lookup(literal, hash, true);
+  }
+}
+
+
 void TargetCollector::AddTarget(BreakTarget* target) {
   // Add the label to the collector, but discard duplicates.
   int length = targets_->length();
diff --git a/src/ast.h b/src/ast.h
index a01e48d..04c2977 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -832,10 +832,14 @@
 
     bool IsCompileTimeValue();
 
+    void set_emit_store(bool emit_store);
+    bool emit_store();
+
    private:
     Literal* key_;
     Expression* value_;
     Kind kind_;
+    bool emit_store_;
   };
 
   ObjectLiteral(Handle<FixedArray> constant_properties,
@@ -858,6 +862,12 @@
 
   bool fast_elements() const { return fast_elements_; }
 
+
+  // Mark all computed expressions that are bound to a key that
+  // is shadowed by a later occurrence of the same key. For the
+  // marked expressions, no store code is emitted.
+  void CalculateEmitStore();
+
  private:
   Handle<FixedArray> constant_properties_;
   ZoneList<Property*>* properties_;
diff --git a/src/builtins.cc b/src/builtins.cc
index 52d5530..aede302 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -1014,20 +1014,18 @@
     Object* data_obj = call_data->data();
     Object* result;
 
-    Handle<Object> data_handle(data_obj);
-    v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
-    ASSERT(raw_holder->IsJSObject());
-    v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
-    Handle<JSObject> holder_handle(JSObject::cast(raw_holder));
-    v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle);
     LOG(ApiObjectAccess("call", JSObject::cast(*args.receiver())));
+    ASSERT(raw_holder->IsJSObject());
+
+    CustomArguments custom;
+    v8::ImplementationUtilities::PrepareArgumentsData(custom.end(),
+        data_obj, *function, raw_holder);
+
     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
-        data,
-        holder,
-        callee,
-        is_construct,
-        reinterpret_cast<void**>(&args[0] - 1),
-        args.length() - 1);
+        custom.end(),
+        &args[0] - 1,
+        args.length() - 1,
+        is_construct);
 
     v8::Handle<v8::Value> value;
     {
@@ -1089,26 +1087,22 @@
 
   Handle<JSFunction> function = args.at<JSFunction>(args_length);
   Object* callback_obj = args[args_length + 1];
-  Handle<Object> data_handle = args.at<Object>(args_length + 2);
+  Handle<Object> data = args.at<Object>(args_length + 2);
   Handle<JSObject> checked_holder = args.at<JSObject>(args_length + 3);
 
 #ifdef DEBUG
   VerifyTypeCheck(checked_holder, function);
 #endif
 
-  v8::Local<v8::Object> holder = v8::Utils::ToLocal(checked_holder);
-  v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
-  v8::InvocationCallback callback =
-      v8::ToCData<v8::InvocationCallback>(callback_obj);
-  v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
+  CustomArguments custom;
+  v8::ImplementationUtilities::PrepareArgumentsData(custom.end(),
+      *data, *function, *checked_holder);
 
   v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
-      data,
-      holder,
-      callee,
-      is_construct,
-      reinterpret_cast<void**>(&args[0] - 1),
-      args_length - 1);
+      custom.end(),
+      &args[0] - 1,
+      args_length - 1,
+      is_construct);
 
   HandleScope scope;
   Object* result;
@@ -1119,6 +1113,9 @@
 #ifdef ENABLE_LOGGING_AND_PROFILING
     state.set_external_callback(v8::ToCData<Address>(callback_obj));
 #endif
+    v8::InvocationCallback callback =
+        v8::ToCData<v8::InvocationCallback>(callback_obj);
+
     value = callback(new_args);
   }
   if (value.IsEmpty()) {
@@ -1161,23 +1158,20 @@
       v8::ToCData<v8::InvocationCallback>(callback_obj);
 
   // Get the data for the call and perform the callback.
-  Object* data_obj = call_data->data();
   Object* result;
-  { HandleScope scope;
-    v8::Local<v8::Object> self =
-        v8::Utils::ToLocal(Handle<JSObject>::cast(args.receiver()));
-    Handle<Object> data_handle(data_obj);
-    v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
-    Handle<JSFunction> callee_handle(constructor);
-    v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle);
-    LOG(ApiObjectAccess("call non-function", JSObject::cast(*args.receiver())));
+  {
+    HandleScope scope;
+
+    LOG(ApiObjectAccess("call non-function", obj));
+
+    CustomArguments custom;
+    v8::ImplementationUtilities::PrepareArgumentsData(custom.end(),
+        call_data->data(), constructor, obj);
     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
-        data,
-        self,
-        callee,
-        is_construct_call,
-        reinterpret_cast<void**>(&args[0] - 1),
-        args.length() - 1);
+        custom.end(),
+        &args[0] - 1,
+        args.length() - 1,
+        is_construct_call);
     v8::Handle<v8::Value> value;
     {
       // Leaving JavaScript.
diff --git a/src/compiler.cc b/src/compiler.cc
index 6cc0971..6f02960 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -152,10 +152,8 @@
   script->set_context_data((*i::Top::global_context())->data());
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  if (info->is_eval() || info->is_json()) {
-    Script::CompilationType compilation_type = info->is_json()
-        ? Script::COMPILATION_TYPE_JSON
-        : Script::COMPILATION_TYPE_EVAL;
+  if (info->is_eval()) {
+    Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL;
     script->set_compilation_type(Smi::FromInt(compilation_type));
     // For eval scripts add information on the function from which eval was
     // called.
@@ -178,7 +176,7 @@
   // Only allow non-global compiles for eval.
   ASSERT(info->is_eval() || info->is_global());
 
-  if (!Parser::Parse(info)) return Handle<SharedFunctionInfo>::null();
+  if (!ParserApi::Parse(info)) return Handle<SharedFunctionInfo>::null();
 
   // Measure how long it takes to do the compilation; only take the
   // rest of the function into account to avoid overlap with the
@@ -283,7 +281,7 @@
     if (pre_data == NULL
         && FLAG_lazy
         && source_length >= FLAG_min_preparse_length) {
-      pre_data = Parser::PartialPreParse(source, NULL, extension);
+      pre_data = ParserApi::PartialPreParse(source, NULL, extension);
     }
 
     // Create a script object describing the script to be compiled.
@@ -323,13 +321,7 @@
 
 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
                                                  Handle<Context> context,
-                                                 bool is_global,
-                                                 ValidationState validate) {
-  // Note that if validation is required then no path through this function
-  // is allowed to return a value without validating that the input is legal
-  // json.
-  bool is_json = (validate == VALIDATE_JSON);
-
+                                                 bool is_global) {
   int source_length = source->length();
   Counters::total_eval_size.Increment(source_length);
   Counters::total_compile_size.Increment(source_length);
@@ -338,13 +330,9 @@
   VMState state(COMPILER);
 
   // Do a lookup in the compilation cache; if the entry is not there, invoke
-  // the compiler and add the result to the cache.  If we're evaluating json
-  // we bypass the cache since we can't be sure a potential value in the
-  // cache has been validated.
+  // the compiler and add the result to the cache.
   Handle<SharedFunctionInfo> result;
-  if (!is_json) {
-    result = CompilationCache::LookupEval(source, context, is_global);
-  }
+  result = CompilationCache::LookupEval(source, context, is_global);
 
   if (result.is_null()) {
     // Create a script object describing the script to be compiled.
@@ -352,12 +340,9 @@
     CompilationInfo info(script);
     info.MarkAsEval();
     if (is_global) info.MarkAsGlobal();
-    if (is_json) info.MarkAsJson();
     info.SetCallingContext(context);
     result = MakeFunctionInfo(&info);
-    if (!result.is_null() && !is_json) {
-      // For json it's unlikely that we'll ever see exactly the same string
-      // again so we don't use the compilation cache.
+    if (!result.is_null()) {
       CompilationCache::PutEval(source, context, is_global, result);
     }
   }
@@ -379,7 +364,7 @@
   Counters::total_compile_size.Increment(compiled_size);
 
   // Generate the AST for the lazily compiled function.
-  if (Parser::Parse(info)) {
+  if (ParserApi::Parse(info)) {
     // Measure how long it takes to do the lazy compilation; only take the
     // rest of the function into account to avoid overlap with the lazy
     // parsing statistics.
diff --git a/src/compiler.h b/src/compiler.h
index d6f4e69..20868e5 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -49,7 +49,6 @@
   bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
   bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
   bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
-  bool is_json() const { return (flags_ & IsJson::mask()) != 0; }
   bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
   FunctionLiteral* function() const { return function_; }
   Scope* scope() const { return scope_; }
@@ -69,10 +68,6 @@
     ASSERT(!is_lazy());
     flags_ |= IsGlobal::encode(true);
   }
-  void MarkAsJson() {
-    ASSERT(!is_lazy());
-    flags_ |= IsJson::encode(true);
-  }
   void MarkAsInLoop() {
     ASSERT(is_lazy());
     flags_ |= IsInLoop::encode(true);
@@ -108,16 +103,15 @@
   // Flags that can be set for eager compilation.
   class IsEval:   public BitField<bool, 1, 1> {};
   class IsGlobal: public BitField<bool, 2, 1> {};
-  class IsJson:   public BitField<bool, 3, 1> {};
   // Flags that can be set for lazy compilation.
-  class IsInLoop: public BitField<bool, 4, 1> {};
+  class IsInLoop: public BitField<bool, 3, 1> {};
 
   unsigned flags_;
 
   // Fields filled in by the compilation pipeline.
   // AST filled in by the parser.
   FunctionLiteral* function_;
-  // The scope of the function literal as a convenience.  Set to indidicate
+  // The scope of the function literal as a convenience.  Set to indicate
   // that scopes have been analyzed.
   Scope* scope_;
   // The compiled code.
@@ -153,8 +147,6 @@
 
 class Compiler : public AllStatic {
  public:
-  enum ValidationState { DONT_VALIDATE_JSON, VALIDATE_JSON };
-
   // All routines return a JSFunction.
   // If an error occurs an exception is raised and
   // the return handle contains NULL.
@@ -172,8 +164,7 @@
   // Compile a String source within a context for Eval.
   static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
                                                 Handle<Context> context,
-                                                bool is_global,
-                                                ValidationState validation);
+                                                bool is_global);
 
   // Compile from function info (used for lazy compilation). Returns true on
   // success and false if the compilation resulted in a stack overflow.
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index a0c6808..0eab8d1 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -1301,7 +1301,7 @@
   try {
     try {
       // Convert the JSON string to an object.
-      request = %CompileString('(' + json_request + ')', false)();
+      request = %CompileString('(' + json_request + ')')();
 
       // Create an initial response.
       response = this.createResponse(request);
diff --git a/src/debug.cc b/src/debug.cc
index 5c6ddbe..24f0409 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1464,8 +1464,7 @@
 // location.
 bool Debug::IsBreakStub(Code* code) {
   CodeStub::Major major_key = CodeStub::GetMajorKey(code);
-  return major_key == CodeStub::CallFunction ||
-         major_key == CodeStub::StackCheck;
+  return major_key == CodeStub::CallFunction;
 }
 
 
@@ -1503,8 +1502,7 @@
     return result;
   }
   if (code->kind() == Code::STUB) {
-    ASSERT(code->major_key() == CodeStub::CallFunction ||
-           code->major_key() == CodeStub::StackCheck);
+    ASSERT(code->major_key() == CodeStub::CallFunction);
     Handle<Code> result =
         Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
     return result;
diff --git a/src/execution.cc b/src/execution.cc
index 3bbac0f..885bf63 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -797,6 +797,7 @@
     if (result && !string->IsSymbol()) {
       i::ExternalStringTable::AddString(*string);
     }
+    if (!result) delete resource;
   } else {
     uc16* data = new uc16[string->length()];
     String::WriteToFlat(*string, data, 0, string->length());
@@ -806,6 +807,7 @@
     if (result && !string->IsSymbol()) {
       i::ExternalStringTable::AddString(*string);
     }
+    if (!result) delete resource;
   }
   if (!result) {
     return v8::ThrowException(v8::String::New("externalizeString() failed."));
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 2474c62..54501ec 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -140,6 +140,9 @@
 // codegen-ia32.cc / codegen-arm.cc
 DEFINE_bool(trace, false, "trace function calls")
 DEFINE_bool(defer_negation, true, "defer negation operation")
+DEFINE_bool(mask_constants_with_cookie,
+            true,
+            "use random jit cookie to mask large constants")
 
 // codegen.cc
 DEFINE_bool(lazy, true, "use lazy compilation")
diff --git a/src/heap.cc b/src/heap.cc
index fc90866..b037efd 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -581,25 +581,22 @@
 }
 
 
-class ClearThreadJSFunctionResultCachesVisitor: public ThreadVisitor  {
-  virtual void VisitThread(ThreadLocalTop* top) {
-    Context* context = top->context_;
-    if (context == NULL) return;
+void Heap::ClearJSFunctionResultCaches() {
+  if (Bootstrapper::IsActive()) return;
 
+  Object* context = global_contexts_list_;
+  while (!context->IsUndefined()) {
+    // Get the caches for this context:
     FixedArray* caches =
-      context->global()->global_context()->jsfunction_result_caches();
+      Context::cast(context)->jsfunction_result_caches();
+    // Clear the caches:
     int length = caches->length();
     for (int i = 0; i < length; i++) {
       JSFunctionResultCache::cast(caches->get(i))->Clear();
     }
+    // Get the next context:
+    context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
   }
-};
-
-
-void Heap::ClearJSFunctionResultCaches() {
-  if (Bootstrapper::IsActive()) return;
-  ClearThreadJSFunctionResultCachesVisitor visitor;
-  ThreadManager::IterateArchivedThreads(&visitor);
 }
 
 
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index f2ac7f7..6d23dd7 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -153,7 +153,8 @@
       in_safe_int32_mode_(false),
       safe_int32_mode_enabled_(true),
       function_return_is_shadowed_(false),
-      in_spilled_code_(false) {
+      in_spilled_code_(false),
+      jit_cookie_((FLAG_mask_constants_with_cookie) ? V8::Random() : 0) {
 }
 
 
@@ -5363,16 +5364,16 @@
 void CodeGenerator::PushUnsafeSmi(Handle<Object> value) {
   ASSERT(value->IsSmi());
   int bits = reinterpret_cast<int>(*value);
-  __ push(Immediate(bits & 0x0000FFFF));
-  __ or_(Operand(esp, 0), Immediate(bits & 0xFFFF0000));
+  __ push(Immediate(bits ^ jit_cookie_));
+  __ xor_(Operand(esp, 0), Immediate(jit_cookie_));
 }
 
 
 void CodeGenerator::StoreUnsafeSmiToLocal(int offset, Handle<Object> value) {
   ASSERT(value->IsSmi());
   int bits = reinterpret_cast<int>(*value);
-  __ mov(Operand(ebp, offset), Immediate(bits & 0x0000FFFF));
-  __ or_(Operand(ebp, offset), Immediate(bits & 0xFFFF0000));
+  __ mov(Operand(ebp, offset), Immediate(bits ^ jit_cookie_));
+  __ xor_(Operand(ebp, offset), Immediate(jit_cookie_));
 }
 
 
@@ -5380,8 +5381,8 @@
   ASSERT(target.is_valid());
   ASSERT(value->IsSmi());
   int bits = reinterpret_cast<int>(*value);
-  __ Set(target, Immediate(bits & 0x0000FFFF));
-  __ or_(target, bits & 0xFFFF0000);
+  __ Set(target, Immediate(bits ^ jit_cookie_));
+  __ xor_(target, jit_cookie_);
 }
 
 
@@ -5559,6 +5560,11 @@
   }
   frame_->Push(&clone);
 
+  // Mark all computed expressions that are bound to a key that
+  // is shadowed by a later occurrence of the same key. For the
+  // marked expressions, no store code is emitted.
+  node->CalculateEmitStore();
+
   for (int i = 0; i < node->properties()->length(); i++) {
     ObjectLiteral::Property* property = node->properties()->at(i);
     switch (property->kind()) {
@@ -5573,24 +5579,32 @@
           // Duplicate the object as the IC receiver.
           frame_->Dup();
           Load(property->value());
-          Result ignored =
-              frame_->CallStoreIC(Handle<String>::cast(key), false);
-          // A test eax instruction following the store IC call would
-          // indicate the presence of an inlined version of the
-          // store. Add a nop to indicate that there is no such
-          // inlined version.
-          __ nop();
+          if (property->emit_store()) {
+            Result ignored =
+                frame_->CallStoreIC(Handle<String>::cast(key), false);
+            // A test eax instruction following the store IC call would
+            // indicate the presence of an inlined version of the
+            // store. Add a nop to indicate that there is no such
+            // inlined version.
+            __ nop();
+          } else {
+            frame_->Drop(2);
+          }
           break;
         }
         // Fall through
       }
       case ObjectLiteral::Property::PROTOTYPE: {
-        // Duplicate the object as an argument to the runtime call.
-        frame_->Dup();
-        Load(property->key());
-        Load(property->value());
-        Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
-        // Ignore the result.
+          // Duplicate the object as an argument to the runtime call.
+          frame_->Dup();
+          Load(property->key());
+          Load(property->value());
+          if (property->emit_store()) {
+            // Ignore the result.
+            Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
+          } else {
+            frame_->Drop(3);
+          }
         break;
       }
       case ObjectLiteral::Property::SETTER: {
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index b072409..4594b19 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -785,6 +785,11 @@
   // in a spilled state.
   bool in_spilled_code_;
 
+  // A cookie that is used for JIT IMM32 Encoding.  Initialized to a
+  // random number when the command-line
+  // FLAG_mask_constants_with_cookie is true, zero otherwise.
+  int jit_cookie_;
+
   friend class VirtualFrame;
   friend class JumpTarget;
   friend class Reference;
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 150df99..ee4e645 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1202,6 +1202,11 @@
   // result_saved is false the result is in eax.
   bool result_saved = false;
 
+  // Mark all computed expressions that are bound to a key that
+  // is shadowed by a later occurrence of the same key. For the
+  // marked expressions, no store code is emitted.
+  expr->CalculateEmitStore();
+
   for (int i = 0; i < expr->properties()->length(); i++) {
     ObjectLiteral::Property* property = expr->properties()->at(i);
     if (property->IsCompileTimeValue()) continue;
@@ -1221,8 +1226,10 @@
           VisitForAccumulatorValue(value);
           __ mov(ecx, Immediate(key->handle()));
           __ mov(edx, Operand(esp, 0));
-          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
-          EmitCallIC(ic,  RelocInfo::CODE_TARGET);
+          if (property->emit_store()) {
+            Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+            EmitCallIC(ic, RelocInfo::CODE_TARGET);
+          }
           break;
         }
         // Fall through.
@@ -1230,7 +1237,11 @@
         __ push(Operand(esp, 0));  // Duplicate receiver.
         VisitForStackValue(key);
         VisitForStackValue(value);
-        __ CallRuntime(Runtime::kSetProperty, 3);
+        if (property->emit_store()) {
+          __ CallRuntime(Runtime::kSetProperty, 3);
+        } else {
+          __ Drop(3);
+        }
         break;
       case ObjectLiteral::Property::SETTER:
       case ObjectLiteral::Property::GETTER:
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 90dabed..e387088 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -206,8 +206,10 @@
                               Register receiver,
                               Register name,
                               Register scratch,
-                              Register extra) {
+                              Register extra,
+                              Register extra2) {
   Label miss;
+  USE(extra2);  // The register extra2 is not used on the ia32 platform.
 
   // Make sure that code is valid. The shifting code relies on the
   // entry size being 8.
@@ -223,6 +225,10 @@
   ASSERT(!extra.is(name));
   ASSERT(!extra.is(scratch));
 
+  // Check scratch and extra registers are valid, and extra2 is unused.
+  ASSERT(!scratch.is(no_reg));
+  ASSERT(extra2.is(no_reg));
+
   // Check that the receiver isn't a smi.
   __ test(receiver, Immediate(kSmiTagMask));
   __ j(zero, &miss, not_taken);
diff --git a/src/json.js b/src/json.js
index a39d7c4..5993100 100644
--- a/src/json.js
+++ b/src/json.js
@@ -29,8 +29,7 @@
 
 function ParseJSONUnfiltered(text) {
   var s = $String(text);
-  var f = %CompileString(s, true);
-  return f();
+  return %ParseJson(s);
 }
 
 function Revive(holder, name, reviver) {
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 3c5ddfb..8cd13bc 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -125,7 +125,8 @@
   PostponeInterruptsScope postpone;
   RegExpCompileData parse_result;
   FlatStringReader reader(pattern);
-  if (!Parser::ParseRegExp(&reader, flags.is_multiline(), &parse_result)) {
+  if (!RegExpParser::ParseRegExp(&reader, flags.is_multiline(),
+                                 &parse_result)) {
     // Throw an exception if we fail to parse the pattern.
     ThrowRegExpException(re,
                          pattern,
@@ -267,7 +268,8 @@
 
   RegExpCompileData compile_data;
   FlatStringReader reader(pattern);
-  if (!Parser::ParseRegExp(&reader, flags.is_multiline(), &compile_data)) {
+  if (!RegExpParser::ParseRegExp(&reader, flags.is_multiline(),
+                                 &compile_data)) {
     // Throw an exception if we fail to parse the pattern.
     // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once.
     ThrowRegExpException(re,
diff --git a/src/liveedit.cc b/src/liveedit.cc
index 49f221a..642b3e6 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -404,7 +404,7 @@
   // Build AST.
   CompilationInfo info(script);
   info.MarkAsGlobal();
-  if (Parser::Parse(&info)) {
+  if (ParserApi::Parse(&info)) {
     // Compile the code.
     LiveEditFunctionTracker tracker(info.function());
     if (Compiler::MakeCodeForLiveEdit(&info)) {
diff --git a/src/log.cc b/src/log.cc
index 2cc2b8f..d12aafb 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -164,7 +164,10 @@
 
   int i = 0;
   const Address callback = VMState::external_callback();
-  if (callback != NULL) {
+  // Surprisingly, PC can point _exactly_ to callback start, with good
+  // probability, and this will result in reporting fake nested
+  // callback call.
+  if (callback != NULL && callback != sample->pc) {
     sample->stack[i++] = callback;
   }
 
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index faaacbc..91dec17 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -44,7 +44,8 @@
                               Register receiver,
                               Register name,
                               Register scratch,
-                              Register extra) {
+                              Register extra,
+                              Register extra2) {
   UNIMPLEMENTED_MIPS();
 }
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 4d21017..1852b54 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1952,7 +1952,9 @@
 void JSFunctionResultCache::Clear() {
   int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
   Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
-  MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
+  MemsetPointer(entries_start,
+                Heap::the_hole_value(),
+                cache_size - kEntriesIndex);
   MakeZeroSize();
 }
 
diff --git a/src/objects.h b/src/objects.h
index 87234ea..6029ad5 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -3409,8 +3409,7 @@
   // Script compilation types.
   enum CompilationType {
     COMPILATION_TYPE_HOST = 0,
-    COMPILATION_TYPE_EVAL = 1,
-    COMPILATION_TYPE_JSON = 2
+    COMPILATION_TYPE_EVAL = 1
   };
 
   // [source]: the script source.
diff --git a/src/parser.cc b/src/parser.cc
index 180d0d2..aad7a61 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -87,112 +87,6 @@
 };
 
 
-template <typename T, int initial_size>
-class BufferedZoneList {
- public:
-  BufferedZoneList() : list_(NULL), last_(NULL) {}
-
-  // Adds element at end of list. This element is buffered and can
-  // be read using last() or removed using RemoveLast until a new Add or until
-  // RemoveLast or GetList has been called.
-  void Add(T* value) {
-    if (last_ != NULL) {
-      if (list_ == NULL) {
-        list_ = new ZoneList<T*>(initial_size);
-      }
-      list_->Add(last_);
-    }
-    last_ = value;
-  }
-
-  T* last() {
-    ASSERT(last_ != NULL);
-    return last_;
-  }
-
-  T* RemoveLast() {
-    ASSERT(last_ != NULL);
-    T* result = last_;
-    if (list_ != NULL && list_->length() > 0)
-      last_ = list_->RemoveLast();
-    else
-      last_ = NULL;
-    return result;
-  }
-
-  T* Get(int i) {
-    ASSERT(0 <= i && i < length());
-    if (list_ == NULL) {
-      ASSERT_EQ(0, i);
-      return last_;
-    } else {
-      if (i == list_->length()) {
-        ASSERT(last_ != NULL);
-        return last_;
-      } else {
-        return list_->at(i);
-      }
-    }
-  }
-
-  void Clear() {
-    list_ = NULL;
-    last_ = NULL;
-  }
-
-  int length() {
-    int length = (list_ == NULL) ? 0 : list_->length();
-    return length + ((last_ == NULL) ? 0 : 1);
-  }
-
-  ZoneList<T*>* GetList() {
-    if (list_ == NULL) {
-      list_ = new ZoneList<T*>(initial_size);
-    }
-    if (last_ != NULL) {
-      list_->Add(last_);
-      last_ = NULL;
-    }
-    return list_;
-  }
-
- private:
-  ZoneList<T*>* list_;
-  T* last_;
-};
-
-
-// Accumulates RegExp atoms and assertions into lists of terms and alternatives.
-class RegExpBuilder: public ZoneObject {
- public:
-  RegExpBuilder();
-  void AddCharacter(uc16 character);
-  // "Adds" an empty expression. Does nothing except consume a
-  // following quantifier
-  void AddEmpty();
-  void AddAtom(RegExpTree* tree);
-  void AddAssertion(RegExpTree* tree);
-  void NewAlternative();  // '|'
-  void AddQuantifierToAtom(int min, int max, RegExpQuantifier::Type type);
-  RegExpTree* ToRegExp();
- private:
-  void FlushCharacters();
-  void FlushText();
-  void FlushTerms();
-  bool pending_empty_;
-  ZoneList<uc16>* characters_;
-  BufferedZoneList<RegExpTree, 2> terms_;
-  BufferedZoneList<RegExpTree, 2> text_;
-  BufferedZoneList<RegExpTree, 2> alternatives_;
-#ifdef DEBUG
-  enum {ADD_NONE, ADD_CHAR, ADD_TERM, ADD_ASSERT, ADD_ATOM} last_added_;
-#define LAST(x) last_added_ = x;
-#else
-#define LAST(x)
-#endif
-};
-
-
 RegExpBuilder::RegExpBuilder()
   : pending_empty_(false),
     characters_(NULL),
@@ -352,124 +246,13 @@
 }
 
 
-class RegExpParser {
- public:
-  RegExpParser(FlatStringReader* in,
-               Handle<String>* error,
-               bool multiline_mode);
-  RegExpTree* ParsePattern();
-  RegExpTree* ParseDisjunction();
-  RegExpTree* ParseGroup();
-  RegExpTree* ParseCharacterClass();
-
-  // Parses a {...,...} quantifier and stores the range in the given
-  // out parameters.
-  bool ParseIntervalQuantifier(int* min_out, int* max_out);
-
-  // Parses and returns a single escaped character.  The character
-  // must not be 'b' or 'B' since they are usually handle specially.
-  uc32 ParseClassCharacterEscape();
-
-  // Checks whether the following is a length-digit hexadecimal number,
-  // and sets the value if it is.
-  bool ParseHexEscape(int length, uc32* value);
-
-  uc32 ParseControlLetterEscape();
-  uc32 ParseOctalLiteral();
-
-  // Tries to parse the input as a back reference.  If successful it
-  // stores the result in the output parameter and returns true.  If
-  // it fails it will push back the characters read so the same characters
-  // can be reparsed.
-  bool ParseBackReferenceIndex(int* index_out);
-
-  CharacterRange ParseClassAtom(uc16* char_class);
-  RegExpTree* ReportError(Vector<const char> message);
-  void Advance();
-  void Advance(int dist);
-  void Reset(int pos);
-
-  // Reports whether the pattern might be used as a literal search string.
-  // Only use if the result of the parse is a single atom node.
-  bool simple();
-  bool contains_anchor() { return contains_anchor_; }
-  void set_contains_anchor() { contains_anchor_ = true; }
-  int captures_started() { return captures_ == NULL ? 0 : captures_->length(); }
-  int position() { return next_pos_ - 1; }
-  bool failed() { return failed_; }
-
-  static const int kMaxCaptures = 1 << 16;
-  static const uc32 kEndMarker = (1 << 21);
-
- private:
-  enum SubexpressionType {
-    INITIAL,
-    CAPTURE,  // All positive values represent captures.
-    POSITIVE_LOOKAHEAD,
-    NEGATIVE_LOOKAHEAD,
-    GROUPING
-  };
-
-  class RegExpParserState : public ZoneObject {
-   public:
-    RegExpParserState(RegExpParserState* previous_state,
-                      SubexpressionType group_type,
-                      int disjunction_capture_index)
-        : previous_state_(previous_state),
-          builder_(new RegExpBuilder()),
-          group_type_(group_type),
-          disjunction_capture_index_(disjunction_capture_index) {}
-    // Parser state of containing expression, if any.
-    RegExpParserState* previous_state() { return previous_state_; }
-    bool IsSubexpression() { return previous_state_ != NULL; }
-    // RegExpBuilder building this regexp's AST.
-    RegExpBuilder* builder() { return builder_; }
-    // Type of regexp being parsed (parenthesized group or entire regexp).
-    SubexpressionType group_type() { return group_type_; }
-    // Index in captures array of first capture in this sub-expression, if any.
-    // Also the capture index of this sub-expression itself, if group_type
-    // is CAPTURE.
-    int capture_index() { return disjunction_capture_index_; }
-   private:
-    // Linked list implementation of stack of states.
-    RegExpParserState* previous_state_;
-    // Builder for the stored disjunction.
-    RegExpBuilder* builder_;
-    // Stored disjunction type (capture, look-ahead or grouping), if any.
-    SubexpressionType group_type_;
-    // Stored disjunction's capture index (if any).
-    int disjunction_capture_index_;
-  };
-
-  uc32 current() { return current_; }
-  bool has_more() { return has_more_; }
-  bool has_next() { return next_pos_ < in()->length(); }
-  uc32 Next();
-  FlatStringReader* in() { return in_; }
-  void ScanForCaptures();
-  uc32 current_;
-  bool has_more_;
-  bool multiline_;
-  int next_pos_;
-  FlatStringReader* in_;
-  Handle<String>* error_;
-  bool simple_;
-  bool contains_anchor_;
-  ZoneList<RegExpCapture*>* captures_;
-  bool is_scanned_for_captures_;
-  // The capture count is only valid after we have scanned for captures.
-  int capture_count_;
-  bool failed_;
-};
-
-
 // A temporary scope stores information during parsing, just like
 // a plain scope.  However, temporary scopes are not kept around
 // after parsing or referenced by syntax trees so they can be stack-
 // allocated and hence used by the pre-parser.
 class TemporaryScope BASE_EMBEDDED {
  public:
-  explicit TemporaryScope(Parser* parser);
+  explicit TemporaryScope(TemporaryScope** variable);
   ~TemporaryScope();
 
   int NextMaterializedLiteralIndex() {
@@ -518,27 +301,25 @@
   int loop_count_;
 
   // Bookkeeping
-  Parser* parser_;
+  TemporaryScope** variable_;
   TemporaryScope* parent_;
-
-  friend class Parser;
 };
 
 
-TemporaryScope::TemporaryScope(Parser* parser)
+TemporaryScope::TemporaryScope(TemporaryScope** variable)
   : materialized_literal_count_(0),
     expected_property_count_(0),
     only_simple_this_property_assignments_(false),
     this_property_assignments_(Factory::empty_fixed_array()),
     loop_count_(0),
-    parser_(parser),
-    parent_(parser->temp_scope_) {
-  parser->temp_scope_ = this;
+    variable_(variable),
+    parent_(*variable) {
+  *variable = this;
 }
 
 
 TemporaryScope::~TemporaryScope() {
-  parser_->temp_scope_ = parent_;
+  *variable_ = parent_;
 }
 
 
@@ -1141,20 +922,20 @@
 
 class Target BASE_EMBEDDED {
  public:
-  Target(Parser* parser, AstNode* node)
-      : parser_(parser), node_(node), previous_(parser_->target_stack_) {
-    parser_->target_stack_ = this;
+  Target(Target** variable, AstNode* node)
+      : variable_(variable), node_(node), previous_(*variable) {
+    *variable = this;
   }
 
   ~Target() {
-    parser_->target_stack_ = previous_;
+    *variable_ = previous_;
   }
 
   Target* previous() { return previous_; }
   AstNode* node() { return node_; }
 
  private:
-  Parser* parser_;
+  Target** variable_;
   AstNode* node_;
   Target* previous_;
 };
@@ -1162,17 +943,17 @@
 
 class TargetScope BASE_EMBEDDED {
  public:
-  explicit TargetScope(Parser* parser)
-      : parser_(parser), previous_(parser->target_stack_) {
-    parser->target_stack_ = NULL;
+  explicit TargetScope(Target** variable)
+      : variable_(variable), previous_(*variable) {
+    *variable = NULL;
   }
 
   ~TargetScope() {
-    parser_->target_stack_ = previous_;
+    *variable_ = previous_;
   }
 
  private:
-  Parser* parser_;
+  Target** variable_;
   Target* previous_;
 };
 
@@ -1184,22 +965,26 @@
 
 class LexicalScope BASE_EMBEDDED {
  public:
-  LexicalScope(Parser* parser, Scope* scope)
-    : parser_(parser),
-      prev_scope_(parser->top_scope_),
-      prev_level_(parser->with_nesting_level_) {
-    parser_->top_scope_ = scope;
-    parser_->with_nesting_level_ = 0;
+  LexicalScope(Scope** scope_variable,
+               int* with_nesting_level_variable,
+               Scope* scope)
+    : scope_variable_(scope_variable),
+      with_nesting_level_variable_(with_nesting_level_variable),
+      prev_scope_(*scope_variable),
+      prev_level_(*with_nesting_level_variable) {
+    *scope_variable = scope;
+    *with_nesting_level_variable = 0;
   }
 
   ~LexicalScope() {
-    parser_->top_scope_->Leave();
-    parser_->top_scope_ = prev_scope_;
-    parser_->with_nesting_level_ = prev_level_;
+    (*scope_variable_)->Leave();
+    *scope_variable_ = prev_scope_;
+    *with_nesting_level_variable_ = prev_level_;
   }
 
  private:
-  Parser* parser_;
+  Scope** scope_variable_;
+  int* with_nesting_level_variable_;
   Scope* prev_scope_;
   int prev_level_;
 };
@@ -1262,8 +1047,8 @@
   mode_ = FLAG_lazy ? PARSE_LAZILY : PARSE_EAGERLY;
   if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
   DummyScope top_scope;
-  LexicalScope scope(this, &top_scope);
-  TemporaryScope temp_scope(this);
+  LexicalScope scope(&this->top_scope_, &this->with_nesting_level_, &top_scope);
+  TemporaryScope temp_scope(&this->temp_scope_);
   ZoneListWrapper<Statement> processor;
   bool ok = true;
   ParseSourceElements(&processor, Token::EOS, &ok);
@@ -1297,8 +1082,9 @@
 
   FunctionLiteral* result = NULL;
   { Scope* scope = factory()->NewScope(top_scope_, type, inside_with());
-    LexicalScope lexical_scope(this, scope);
-    TemporaryScope temp_scope(this);
+    LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
+                               scope);
+    TemporaryScope temp_scope(&this->temp_scope_);
     ZoneListWrapper<Statement> body(16);
     bool ok = true;
     ParseSourceElements(&body, Token::EOS, &ok);
@@ -1356,8 +1142,9 @@
     Handle<String> no_name = factory()->EmptySymbol();
     Scope* scope =
         factory()->NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
-    LexicalScope lexical_scope(this, scope);
-    TemporaryScope temp_scope(this);
+    LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
+                               scope);
+    TemporaryScope temp_scope(&this->temp_scope_);
 
     FunctionLiteralType type =
         info->is_expression() ? EXPRESSION : DECLARATION;
@@ -1382,56 +1169,6 @@
 }
 
 
-FunctionLiteral* Parser::ParseJson(Handle<String> source) {
-  CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);
-
-  HistogramTimerScope timer(&Counters::parse);
-  Counters::total_parse_size.Increment(source->length());
-
-  // Initialize parser state.
-  source->TryFlatten(TENURED);
-  scanner_.Initialize(source, JSON);
-  ASSERT(target_stack_ == NULL);
-
-  FunctionLiteral* result = NULL;
-  Handle<String> no_name = factory()->EmptySymbol();
-
-  {
-    Scope* scope = factory()->NewScope(top_scope_, Scope::GLOBAL_SCOPE, false);
-    LexicalScope lexical_scope(this, scope);
-    TemporaryScope temp_scope(this);
-    bool ok = true;
-    Expression* expression = ParseJson(&ok);
-    if (ok) {
-      ZoneListWrapper<Statement> statement = factory()->NewList<Statement>(1);
-      statement.Add(new ExpressionStatement(expression));
-      result = NEW(FunctionLiteral(
-          no_name,
-          top_scope_,
-          statement.elements(),
-          temp_scope.materialized_literal_count(),
-          temp_scope.expected_property_count(),
-          temp_scope.only_simple_this_property_assignments(),
-          temp_scope.this_property_assignments(),
-          0,
-          0,
-          source->length(),
-          false,
-          temp_scope.ContainsLoops()));
-    } else if (scanner().stack_overflow()) {
-      Top::StackOverflow();
-    }
-  }
-
-  // Make sure the target stack is empty.
-  ASSERT(target_stack_ == NULL);
-
-  // If there was a syntax error we have to get rid of the AST
-  // and it is not safe to do so before the scope has been deleted.
-  if (result == NULL) zone_scope.DeleteOnExit();
-  return result;
-}
-
 void Parser::ReportMessage(const char* type, Vector<const char*> args) {
   Scanner::Location source_location = scanner_.location();
   ReportMessageAt(source_location, type, args);
@@ -1733,7 +1470,7 @@
   // elements. This way, all scripts and functions get their own
   // target stack thus avoiding illegal breaks and continues across
   // functions.
-  TargetScope scope(this);
+  TargetScope scope(&this->target_stack_);
 
   ASSERT(processor != NULL);
   InitializationBlockFinder block_finder;
@@ -1857,7 +1594,7 @@
       // fall-through. It is much easier just to wrap the entire
       // try-statement in a statement block and put the labels there
       Block* result = NEW(Block(labels, 1, false));
-      Target target(this, result);
+      Target target(&this->target_stack_, result);
       TryStatement* statement = ParseTryStatement(CHECK_OK);
       if (statement) {
         statement->set_statement_pos(statement_pos);
@@ -2073,7 +1810,7 @@
   //
   // Construct block expecting 16 statements.
   Block* result = NEW(Block(labels, 16, false));
-  Target target(this, result);
+  Target target(&this->target_stack_, result);
   Expect(Token::LBRACE, CHECK_OK);
   while (peek() != Token::RBRACE) {
     Statement* stat = ParseStatement(NULL, CHECK_OK);
@@ -2468,7 +2205,7 @@
   ZoneList<BreakTarget*>* target_list = NEW(ZoneList<BreakTarget*>(0));
   TargetCollector collector(target_list);
   Statement* stat;
-  { Target target(this, &collector);
+  { Target target(&this->target_stack_, &collector);
     with_nesting_level_++;
     top_scope_->RecordWithStatement();
     stat = ParseStatement(labels, CHECK_OK);
@@ -2551,7 +2288,7 @@
   //   'switch' '(' Expression ')' '{' CaseClause* '}'
 
   SwitchStatement* statement = NEW(SwitchStatement(labels));
-  Target target(this, statement);
+  Target target(&this->target_stack_, statement);
 
   Expect(Token::SWITCH, CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
@@ -2608,7 +2345,7 @@
   TargetCollector collector(target_list);
   Block* try_block;
 
-  { Target target(this, &collector);
+  { Target target(&this->target_stack_, &collector);
     try_block = ParseBlock(NULL, CHECK_OK);
   }
 
@@ -2644,7 +2381,7 @@
       catch_var = top_scope_->NewTemporary(Factory::catch_var_symbol());
       Literal* name_literal = NEW(Literal(name));
       Expression* obj = NEW(CatchExtensionObject(name_literal, catch_var));
-      { Target target(this, &catch_collector);
+      { Target target(&this->target_stack_, &catch_collector);
         catch_block = WithHelper(obj, NULL, true, CHECK_OK);
       }
     } else {
@@ -2703,7 +2440,7 @@
 
   temp_scope_->AddLoop();
   DoWhileStatement* loop = NEW(DoWhileStatement(labels));
-  Target target(this, loop);
+  Target target(&this->target_stack_, loop);
 
   Expect(Token::DO, CHECK_OK);
   Statement* body = ParseStatement(NULL, CHECK_OK);
@@ -2736,7 +2473,7 @@
 
   temp_scope_->AddLoop();
   WhileStatement* loop = NEW(WhileStatement(labels));
-  Target target(this, loop);
+  Target target(&this->target_stack_, loop);
 
   Expect(Token::WHILE, CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
@@ -2766,7 +2503,7 @@
           ParseVariableDeclarations(false, &each, CHECK_OK);
       if (peek() == Token::IN && each != NULL) {
         ForInStatement* loop = NEW(ForInStatement(labels));
-        Target target(this, loop);
+        Target target(&this->target_stack_, loop);
 
         Expect(Token::IN, CHECK_OK);
         Expression* enumerable = ParseExpression(true, CHECK_OK);
@@ -2800,7 +2537,7 @@
           expression = NewThrowReferenceError(type);
         }
         ForInStatement* loop = NEW(ForInStatement(labels));
-        Target target(this, loop);
+        Target target(&this->target_stack_, loop);
 
         Expect(Token::IN, CHECK_OK);
         Expression* enumerable = ParseExpression(true, CHECK_OK);
@@ -2819,7 +2556,7 @@
 
   // Standard 'for' loop
   ForStatement* loop = NEW(ForStatement(labels));
-  Target target(this, loop);
+  Target target(&this->target_stack_, loop);
 
   // Parsed initializer at this point.
   Expect(Token::SEMICOLON, CHECK_OK);
@@ -3909,8 +3646,9 @@
   // Parse function body.
   { Scope* scope =
         factory()->NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
-    LexicalScope lexical_scope(this, scope);
-    TemporaryScope temp_scope(this);
+    LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
+                               scope);
+    TemporaryScope temp_scope(&this->temp_scope_);
     top_scope_->SetScopeName(name);
 
     //  FormalParameterList ::
@@ -4281,145 +4019,165 @@
 // ----------------------------------------------------------------------------
 // JSON
 
-Expression* Parser::ParseJson(bool* ok) {
-  Expression* result = ParseJsonValue(CHECK_OK);
-  Expect(Token::EOS, CHECK_OK);
+Handle<Object> JsonParser::ParseJson(Handle<String> source) {
+  source->TryFlatten();
+  scanner_.Initialize(source, JSON);
+  Handle<Object> result = ParseJsonValue();
+  if (result.is_null() || scanner_.Next() != Token::EOS) {
+    if (scanner_.stack_overflow()) {
+      // Scanner failed.
+      Top::StackOverflow();
+    } else {
+      // Parse failed. Scanner's current token is the unexpected token.
+      Token::Value token = scanner_.current_token();
+
+      const char* message;
+      const char* name_opt = NULL;
+
+      switch (token) {
+        case Token::EOS:
+          message = "unexpected_eos";
+          break;
+        case Token::NUMBER:
+          message = "unexpected_token_number";
+          break;
+        case Token::STRING:
+          message = "unexpected_token_string";
+          break;
+        case Token::IDENTIFIER:
+          message = "unexpected_token_identifier";
+          break;
+        default:
+          message = "unexpected_token";
+          name_opt = Token::String(token);
+          ASSERT(name_opt != NULL);
+          break;
+      }
+
+      Scanner::Location source_location = scanner_.location();
+      MessageLocation location(Factory::NewScript(source),
+                               source_location.beg_pos,
+                               source_location.end_pos);
+      int argc = (name_opt == NULL) ? 0 : 1;
+      Handle<JSArray> array = Factory::NewJSArray(argc);
+      if (name_opt != NULL) {
+        SetElement(array,
+                   0,
+                   Factory::NewStringFromUtf8(CStrVector(name_opt)));
+      }
+      Handle<Object> result = Factory::NewSyntaxError(message, array);
+      Top::Throw(*result, &location);
+      return Handle<Object>::null();
+    }
+  }
   return result;
 }
 
 
+Handle<String> JsonParser::GetString() {
+  int literal_length = scanner_.literal_length();
+  if (literal_length == 0) {
+    return Factory::empty_string();
+  }
+  const char* literal_string = scanner_.literal_string();
+  Vector<const char> literal(literal_string, literal_length);
+  return Factory::NewStringFromUtf8(literal);
+}
+
+
 // Parse any JSON value.
-Expression* Parser::ParseJsonValue(bool* ok) {
-  Token::Value token = peek();
+Handle<Object> JsonParser::ParseJsonValue() {
+  Token::Value token = scanner_.Next();
   switch (token) {
     case Token::STRING: {
-      Consume(Token::STRING);
-      int literal_length = scanner_.literal_length();
-      const char* literal_string = scanner_.literal_string();
-      if (literal_length == 0) {
-        return NEW(Literal(Factory::empty_string()));
-      }
-      Vector<const char> literal(literal_string, literal_length);
-      return NEW(Literal(Factory::NewStringFromUtf8(literal, TENURED)));
+      return GetString();
     }
     case Token::NUMBER: {
-      Consume(Token::NUMBER);
-      ASSERT(scanner_.literal_length() > 0);
       double value = StringToDouble(scanner_.literal(),
                                     NO_FLAGS,  // Hex, octal or trailing junk.
                                     OS::nan_value());
-      return NewNumberLiteral(value);
+      return Factory::NewNumber(value);
     }
     case Token::FALSE_LITERAL:
-      Consume(Token::FALSE_LITERAL);
-      return NEW(Literal(Factory::false_value()));
+      return Factory::false_value();
     case Token::TRUE_LITERAL:
-      Consume(Token::TRUE_LITERAL);
-      return NEW(Literal(Factory::true_value()));
+      return Factory::true_value();
     case Token::NULL_LITERAL:
-      Consume(Token::NULL_LITERAL);
-      return NEW(Literal(Factory::null_value()));
-    case Token::LBRACE: {
-      Expression* result = ParseJsonObject(CHECK_OK);
-      return result;
-    }
-    case Token::LBRACK: {
-      Expression* result = ParseJsonArray(CHECK_OK);
-      return result;
-    }
+      return Factory::null_value();
+    case Token::LBRACE:
+      return ParseJsonObject();
+    case Token::LBRACK:
+      return ParseJsonArray();
     default:
-      *ok = false;
-      ReportUnexpectedToken(token);
-      return NULL;
+      return ReportUnexpectedToken();
   }
 }
 
 
 // Parse a JSON object. Scanner must be right after '{' token.
-Expression* Parser::ParseJsonObject(bool* ok) {
-  Consume(Token::LBRACE);
-  ZoneListWrapper<ObjectLiteral::Property> properties =
-      factory()->NewList<ObjectLiteral::Property>(4);
-  int boilerplate_properties = 0;
-  if (peek() != Token::RBRACE) {
+Handle<Object> JsonParser::ParseJsonObject() {
+  Handle<JSFunction> object_constructor(
+      Top::global_context()->object_function());
+  Handle<JSObject> json_object = Factory::NewJSObject(object_constructor);
+  if (scanner_.peek() == Token::RBRACE) {
+    scanner_.Next();
+  } else {
     do {
-      Expect(Token::STRING, CHECK_OK);
-      Handle<String> key = GetSymbol(CHECK_OK);
-      Expect(Token::COLON, CHECK_OK);
-      Expression* value = ParseJsonValue(CHECK_OK);
-      Literal* key_literal;
+      if (scanner_.Next() != Token::STRING) {
+        return ReportUnexpectedToken();
+      }
+      Handle<String> key = GetString();
+      if (scanner_.Next() != Token::COLON) {
+        return ReportUnexpectedToken();
+      }
+      Handle<Object> value = ParseJsonValue();
+      if (value.is_null()) return Handle<Object>::null();
       uint32_t index;
       if (key->AsArrayIndex(&index)) {
-        key_literal = NewNumberLiteral(index);
+        SetElement(json_object, index, value);
       } else {
-        key_literal = NEW(Literal(key));
+        SetProperty(json_object, key, value, NONE);
       }
-      ObjectLiteral::Property* property =
-          NEW(ObjectLiteral::Property(key_literal, value));
-      properties.Add(property);
-
-      if (IsBoilerplateProperty(property)) {
-        boilerplate_properties++;
-      }
-    } while (Check(Token::COMMA));
+    } while (scanner_.Next() == Token::COMMA);
+    if (scanner_.current_token() != Token::RBRACE) {
+      return ReportUnexpectedToken();
+    }
   }
-  Expect(Token::RBRACE, CHECK_OK);
-
-  int literal_index = temp_scope_->NextMaterializedLiteralIndex();
-  if (is_pre_parsing_) return NULL;
-
-  Handle<FixedArray> constant_properties =
-        Factory::NewFixedArray(boilerplate_properties * 2, TENURED);
-  bool is_simple = true;
-  bool fast_elements = true;
-  int depth = 1;
-  BuildObjectLiteralConstantProperties(properties.elements(),
-                                       constant_properties,
-                                       &is_simple,
-                                       &fast_elements,
-                                       &depth);
-  return new ObjectLiteral(constant_properties,
-                           properties.elements(),
-                           literal_index,
-                           is_simple,
-                           fast_elements,
-                           depth);
+  return json_object;
 }
 
 
 // Parse a JSON array. Scanner must be right after '[' token.
-Expression* Parser::ParseJsonArray(bool* ok) {
-  Consume(Token::LBRACK);
+Handle<Object> JsonParser::ParseJsonArray() {
+  ZoneScope zone_scope(DELETE_ON_EXIT);
+  ZoneList<Handle<Object> > elements(4);
 
-  ZoneListWrapper<Expression> values = factory()->NewList<Expression>(4);
-  if (peek() != Token::RBRACK) {
+  Token::Value token = scanner_.peek();
+  if (token == Token::RBRACK) {
+    scanner_.Next();
+  } else {
     do {
-      Expression* exp = ParseJsonValue(CHECK_OK);
-      values.Add(exp);
-    } while (Check(Token::COMMA));
+      Handle<Object> element = ParseJsonValue();
+      if (element.is_null()) return Handle<Object>::null();
+      elements.Add(element);
+      token = scanner_.Next();
+    } while (token == Token::COMMA);
+    if (token != Token::RBRACK) {
+      return ReportUnexpectedToken();
+    }
   }
-  Expect(Token::RBRACK, CHECK_OK);
 
-  // Update the scope information before the pre-parsing bailout.
-  int literal_index = temp_scope_->NextMaterializedLiteralIndex();
+  // Allocate a fixed array with all the elements.
+  Handle<FixedArray> fast_elements =
+      Factory::NewFixedArray(elements.length());
 
-  if (is_pre_parsing_) return NULL;
+  for (int i = 0, n = elements.length(); i < n; i++) {
+    fast_elements->set(i, *elements[i]);
+  }
 
-  // Allocate a fixed array with all the literals.
-  Handle<FixedArray> literals =
-      Factory::NewFixedArray(values.length(), TENURED);
-
-  bool is_simple;
-  int depth;
-  BuildArrayLiteralBoilerplateLiterals(values.elements(),
-                                       literals,
-                                       &is_simple,
-                                       &depth);
-  return NEW(ArrayLiteral(literals, values.elements(),
-                          literal_index, is_simple, depth));
+  return Factory::NewJSArrayWithElements(fast_elements);
 }
 
-
 // ----------------------------------------------------------------------------
 // Regular expressions
 
@@ -5247,9 +5005,9 @@
 
 // Preparse, but only collect data that is immediately useful,
 // even if the preparser data is only used once.
-ScriptDataImpl* Parser::PartialPreParse(Handle<String> source,
-                                        unibrow::CharacterStream* stream,
-                                        v8::Extension* extension) {
+ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
+                                           unibrow::CharacterStream* stream,
+                                           v8::Extension* extension) {
   Handle<Script> no_script;
   bool allow_natives_syntax =
       FLAG_allow_natives_syntax || Bootstrapper::IsActive();
@@ -5305,9 +5063,9 @@
 }
 
 
-ScriptDataImpl* Parser::PreParse(Handle<String> source,
-                                 unibrow::CharacterStream* stream,
-                                 v8::Extension* extension) {
+ScriptDataImpl* ParserApi::PreParse(Handle<String> source,
+                                    unibrow::CharacterStream* stream,
+                                    v8::Extension* extension) {
   Handle<Script> no_script;
   bool allow_natives_syntax =
       FLAG_allow_natives_syntax || Bootstrapper::IsActive();
@@ -5320,9 +5078,9 @@
 }
 
 
-bool Parser::ParseRegExp(FlatStringReader* input,
-                         bool multiline,
-                         RegExpCompileData* result) {
+bool RegExpParser::ParseRegExp(FlatStringReader* input,
+                               bool multiline,
+                               RegExpCompileData* result) {
   ASSERT(result != NULL);
   RegExpParser parser(input, &result->error, multiline);
   RegExpTree* tree = parser.ParsePattern();
@@ -5342,7 +5100,7 @@
 }
 
 
-bool Parser::Parse(CompilationInfo* info) {
+bool ParserApi::Parse(CompilationInfo* info) {
   ASSERT(info->function() == NULL);
   FunctionLiteral* result = NULL;
   Handle<Script> script = info->script();
@@ -5368,11 +5126,7 @@
       ASSERT(Top::has_pending_exception());
     } else {
       Handle<String> source = Handle<String>(String::cast(script->source()));
-      // JSON is always global.
-      ASSERT(!info->is_json() || info->is_global());
-      result = info->is_json()
-          ? parser.ParseJson(source)
-          : parser.ParseProgram(source, info->is_global());
+      result = parser.ParseProgram(source, info->is_global());
     }
   }
 
diff --git a/src/parser.h b/src/parser.h
index 7142551..19b382e 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -177,13 +177,8 @@
 };
 
 
-class Parser {
+class ParserApi {
  public:
-  Parser(Handle<Script> script, bool allow_natives_syntax,
-         v8::Extension* extension, ParserMode is_pre_parsing,
-         ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
-  virtual ~Parser() { }
-
   // Parses the source code represented by the compilation info and sets its
   // function literal.  Returns false (and deallocates any allocated AST
   // nodes) if parsing failed.
@@ -199,11 +194,246 @@
   static ScriptDataImpl* PartialPreParse(Handle<String> source,
                                          unibrow::CharacterStream* stream,
                                          v8::Extension* extension);
+};
+
+
+// A BuffferedZoneList is an automatically growing list, just like (and backed
+// by) a ZoneList, that is optimized for the case of adding and removing
+// a single element. The last element added is stored outside the backing list,
+// and if no more than one element is ever added, the ZoneList isn't even
+// allocated.
+// Elements must not be NULL pointers.
+template <typename T, int initial_size>
+class BufferedZoneList {
+ public:
+  BufferedZoneList() : list_(NULL), last_(NULL) {}
+
+  // Adds element at end of list. This element is buffered and can
+  // be read using last() or removed using RemoveLast until a new Add or until
+  // RemoveLast or GetList has been called.
+  void Add(T* value) {
+    if (last_ != NULL) {
+      if (list_ == NULL) {
+        list_ = new ZoneList<T*>(initial_size);
+      }
+      list_->Add(last_);
+    }
+    last_ = value;
+  }
+
+  T* last() {
+    ASSERT(last_ != NULL);
+    return last_;
+  }
+
+  T* RemoveLast() {
+    ASSERT(last_ != NULL);
+    T* result = last_;
+    if ((list_ != NULL) && (list_->length() > 0))
+      last_ = list_->RemoveLast();
+    else
+      last_ = NULL;
+    return result;
+  }
+
+  T* Get(int i) {
+    ASSERT((0 <= i) && (i < length()));
+    if (list_ == NULL) {
+      ASSERT_EQ(0, i);
+      return last_;
+    } else {
+      if (i == list_->length()) {
+        ASSERT(last_ != NULL);
+        return last_;
+      } else {
+        return list_->at(i);
+      }
+    }
+  }
+
+  void Clear() {
+    list_ = NULL;
+    last_ = NULL;
+  }
+
+  int length() {
+    int length = (list_ == NULL) ? 0 : list_->length();
+    return length + ((last_ == NULL) ? 0 : 1);
+  }
+
+  ZoneList<T*>* GetList() {
+    if (list_ == NULL) {
+      list_ = new ZoneList<T*>(initial_size);
+    }
+    if (last_ != NULL) {
+      list_->Add(last_);
+      last_ = NULL;
+    }
+    return list_;
+  }
+
+ private:
+  ZoneList<T*>* list_;
+  T* last_;
+};
+
+
+// Accumulates RegExp atoms and assertions into lists of terms and alternatives.
+class RegExpBuilder: public ZoneObject {
+ public:
+  RegExpBuilder();
+  void AddCharacter(uc16 character);
+  // "Adds" an empty expression. Does nothing except consume a
+  // following quantifier
+  void AddEmpty();
+  void AddAtom(RegExpTree* tree);
+  void AddAssertion(RegExpTree* tree);
+  void NewAlternative();  // '|'
+  void AddQuantifierToAtom(int min, int max, RegExpQuantifier::Type type);
+  RegExpTree* ToRegExp();
+
+ private:
+  void FlushCharacters();
+  void FlushText();
+  void FlushTerms();
+  bool pending_empty_;
+  ZoneList<uc16>* characters_;
+  BufferedZoneList<RegExpTree, 2> terms_;
+  BufferedZoneList<RegExpTree, 2> text_;
+  BufferedZoneList<RegExpTree, 2> alternatives_;
+#ifdef DEBUG
+  enum {ADD_NONE, ADD_CHAR, ADD_TERM, ADD_ASSERT, ADD_ATOM} last_added_;
+#define LAST(x) last_added_ = x;
+#else
+#define LAST(x)
+#endif
+};
+
+
+class RegExpParser {
+ public:
+  RegExpParser(FlatStringReader* in,
+               Handle<String>* error,
+               bool multiline_mode);
 
   static bool ParseRegExp(FlatStringReader* input,
                           bool multiline,
                           RegExpCompileData* result);
 
+  RegExpTree* ParsePattern();
+  RegExpTree* ParseDisjunction();
+  RegExpTree* ParseGroup();
+  RegExpTree* ParseCharacterClass();
+
+  // Parses a {...,...} quantifier and stores the range in the given
+  // out parameters.
+  bool ParseIntervalQuantifier(int* min_out, int* max_out);
+
+  // Parses and returns a single escaped character.  The character
+  // must not be 'b' or 'B' since they are usually handle specially.
+  uc32 ParseClassCharacterEscape();
+
+  // Checks whether the following is a length-digit hexadecimal number,
+  // and sets the value if it is.
+  bool ParseHexEscape(int length, uc32* value);
+
+  uc32 ParseControlLetterEscape();
+  uc32 ParseOctalLiteral();
+
+  // Tries to parse the input as a back reference.  If successful it
+  // stores the result in the output parameter and returns true.  If
+  // it fails it will push back the characters read so the same characters
+  // can be reparsed.
+  bool ParseBackReferenceIndex(int* index_out);
+
+  CharacterRange ParseClassAtom(uc16* char_class);
+  RegExpTree* ReportError(Vector<const char> message);
+  void Advance();
+  void Advance(int dist);
+  void Reset(int pos);
+
+  // Reports whether the pattern might be used as a literal search string.
+  // Only use if the result of the parse is a single atom node.
+  bool simple();
+  bool contains_anchor() { return contains_anchor_; }
+  void set_contains_anchor() { contains_anchor_ = true; }
+  int captures_started() { return captures_ == NULL ? 0 : captures_->length(); }
+  int position() { return next_pos_ - 1; }
+  bool failed() { return failed_; }
+
+  static const int kMaxCaptures = 1 << 16;
+  static const uc32 kEndMarker = (1 << 21);
+
+ private:
+  enum SubexpressionType {
+    INITIAL,
+    CAPTURE,  // All positive values represent captures.
+    POSITIVE_LOOKAHEAD,
+    NEGATIVE_LOOKAHEAD,
+    GROUPING
+  };
+
+  class RegExpParserState : public ZoneObject {
+   public:
+    RegExpParserState(RegExpParserState* previous_state,
+                      SubexpressionType group_type,
+                      int disjunction_capture_index)
+        : previous_state_(previous_state),
+          builder_(new RegExpBuilder()),
+          group_type_(group_type),
+          disjunction_capture_index_(disjunction_capture_index) {}
+    // Parser state of containing expression, if any.
+    RegExpParserState* previous_state() { return previous_state_; }
+    bool IsSubexpression() { return previous_state_ != NULL; }
+    // RegExpBuilder building this regexp's AST.
+    RegExpBuilder* builder() { return builder_; }
+    // Type of regexp being parsed (parenthesized group or entire regexp).
+    SubexpressionType group_type() { return group_type_; }
+    // Index in captures array of first capture in this sub-expression, if any.
+    // Also the capture index of this sub-expression itself, if group_type
+    // is CAPTURE.
+    int capture_index() { return disjunction_capture_index_; }
+
+   private:
+    // Linked list implementation of stack of states.
+    RegExpParserState* previous_state_;
+    // Builder for the stored disjunction.
+    RegExpBuilder* builder_;
+    // Stored disjunction type (capture, look-ahead or grouping), if any.
+    SubexpressionType group_type_;
+    // Stored disjunction's capture index (if any).
+    int disjunction_capture_index_;
+  };
+
+  uc32 current() { return current_; }
+  bool has_more() { return has_more_; }
+  bool has_next() { return next_pos_ < in()->length(); }
+  uc32 Next();
+  FlatStringReader* in() { return in_; }
+  void ScanForCaptures();
+  uc32 current_;
+  bool has_more_;
+  bool multiline_;
+  int next_pos_;
+  FlatStringReader* in_;
+  Handle<String>* error_;
+  bool simple_;
+  bool contains_anchor_;
+  ZoneList<RegExpCapture*>* captures_;
+  bool is_scanned_for_captures_;
+  // The capture count is only valid after we have scanned for captures.
+  int capture_count_;
+  bool failed_;
+};
+
+
+class Parser {
+ public:
+  Parser(Handle<Script> script, bool allow_natives_syntax,
+         v8::Extension* extension, ParserMode is_pre_parsing,
+         ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
+  virtual ~Parser() { }
+
   // Pre-parse the program from the character stream; returns true on
   // success, false if a stack-overflow happened during parsing.
   bool PreParseProgram(Handle<String> source, unibrow::CharacterStream* stream);
@@ -218,7 +448,6 @@
   FunctionLiteral* ParseProgram(Handle<String> source,
                                 bool in_global_context);
   FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);
-  FunctionLiteral* ParseJson(Handle<String> source);
 
   // The minimum number of contiguous assignment that will
   // be treated as an initialization block. Benchmarks show that
@@ -410,34 +639,6 @@
   Expression* NewThrowError(Handle<String> constructor,
                             Handle<String> type,
                             Vector< Handle<Object> > arguments);
-
-  // JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5
-  // specification section 15.12.1 (and appendix A.8).
-  // The grammar is given section 15.12.1.2 (and appendix A.8.2).
-
-  // Parse JSON input as a single JSON value.
-  Expression* ParseJson(bool* ok);
-
-  // Parse a single JSON value from input (grammar production JSONValue).
-  // A JSON value is either a (double-quoted) string literal, a number literal,
-  // one of "true", "false", or "null", or an object or array literal.
-  Expression* ParseJsonValue(bool* ok);
-  // Parse a JSON object literal (grammar production JSONObject).
-  // An object literal is a squiggly-braced and comma separated sequence
-  // (possibly empty) of key/value pairs, where the key is a JSON string
-  // literal, the value is a JSON value, and the two are spearated by a colon.
-  // A JavaScript object also allows numbers and identifiers as keys.
-  Expression* ParseJsonObject(bool* ok);
-  // Parses a JSON array literal (grammar production JSONArray). An array
-  // literal is a square-bracketed and comma separated sequence (possibly empty)
-  // of JSON values.
-  // A JavaScript array allows leaving out values from the sequence.
-  Expression* ParseJsonArray(bool* ok);
-
-  friend class Target;
-  friend class TargetScope;
-  friend class LexicalScope;
-  friend class TemporaryScope;
 };
 
 
@@ -472,6 +673,49 @@
 };
 
 
+// JSON is a subset of JavaScript, as specified in, e.g., the ECMAScript 5
+// specification section 15.12.1 (and appendix A.8).
+// The grammar is given section 15.12.1.2 (and appendix A.8.2).
+class JsonParser BASE_EMBEDDED {
+ public:
+  // Parse JSON input as a single JSON value.
+  // Returns null handle and sets exception if parsing failed.
+  static Handle<Object> Parse(Handle<String> source) {
+    return JsonParser().ParseJson(source);
+  }
+
+ private:
+  JsonParser() { }
+  ~JsonParser() { }
+
+  // Parse a string containing a single JSON value.
+  Handle<Object> ParseJson(Handle<String>);
+  // Parse a single JSON value from input (grammar production JSONValue).
+  // A JSON value is either a (double-quoted) string literal, a number literal,
+  // one of "true", "false", or "null", or an object or array literal.
+  Handle<Object> ParseJsonValue();
+  // Parse a JSON object literal (grammar production JSONObject).
+  // An object literal is a squiggly-braced and comma separated sequence
+  // (possibly empty) of key/value pairs, where the key is a JSON string
+  // literal, the value is a JSON value, and the two are separated by a colon.
+  // A JSON array dosn't allow numbers and identifiers as keys, like a
+  // JavaScript array.
+  Handle<Object> ParseJsonObject();
+  // Parses a JSON array literal (grammar production JSONArray). An array
+  // literal is a square-bracketed and comma separated sequence (possibly empty)
+  // of JSON values.
+  // A JSON array doesn't allow leaving out values from the sequence, nor does
+  // it allow a terminal comma, like a JavaScript array does.
+  Handle<Object> ParseJsonArray();
+
+  // Mark that a parsing error has happened at the current token, and
+  // return a null handle. Primarily for readability.
+  Handle<Object> ReportUnexpectedToken() { return Handle<Object>::null(); }
+  // Converts the currently parsed literal to a JavaScript String.
+  Handle<String> GetString();
+
+  Scanner scanner_;
+};
 } }  // namespace v8::internal
 
 #endif  // V8_PARSER_H_
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index eefaec9..c0eb213 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -856,7 +856,7 @@
   struct sigaction sa;
   sa.sa_sigaction = ProfilerSignalHandler;
   sigemptyset(&sa.sa_mask);
-  sa.sa_flags = SA_SIGINFO;
+  sa.sa_flags = SA_RESTART | SA_SIGINFO;
   if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
   data_->signal_handler_installed_ = true;
 
diff --git a/src/runtime.cc b/src/runtime.cc
index f701c03..fc1a023 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -7129,20 +7129,31 @@
 }
 
 
+static MaybeObject* Runtime_ParseJson(Arguments args) {
+  HandleScope scope;
+  ASSERT_EQ(1, args.length());
+  CONVERT_ARG_CHECKED(String, source, 0);
+
+  Handle<Object> result = JsonParser::Parse(source);
+  if (result.is_null()) {
+    // Syntax error or stack overflow in scanner.
+    ASSERT(Top::has_pending_exception());
+    return Failure::Exception();
+  }
+  return *result;
+}
+
+
 static MaybeObject* Runtime_CompileString(Arguments args) {
   HandleScope scope;
-  ASSERT_EQ(2, args.length());
+  ASSERT_EQ(1, args.length());
   CONVERT_ARG_CHECKED(String, source, 0);
-  CONVERT_ARG_CHECKED(Oddball, is_json, 1)
 
   // Compile source string in the global context.
   Handle<Context> context(Top::context()->global_context());
-  Compiler::ValidationState validate = (is_json->IsTrue())
-    ? Compiler::VALIDATE_JSON : Compiler::DONT_VALIDATE_JSON;
   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
                                                             context,
-                                                            true,
-                                                            validate);
+                                                            true);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> fun =
       Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED);
@@ -7157,8 +7168,7 @@
   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
       source,
       Handle<Context>(Top::context()),
-      Top::context()->IsGlobalContext(),
-      Compiler::DONT_VALIDATE_JSON);
+      Top::context()->IsGlobalContext());
   if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
   Handle<JSFunction> compiled = Factory::NewFunctionFromSharedFunctionInfo(
       shared,
@@ -9370,8 +9380,7 @@
   Handle<SharedFunctionInfo> shared =
       Compiler::CompileEval(function_source,
                             context,
-                            context->IsGlobalContext(),
-                            Compiler::DONT_VALIDATE_JSON);
+                            context->IsGlobalContext());
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
       Factory::NewFunctionFromSharedFunctionInfo(shared, context);
@@ -9442,8 +9451,7 @@
   Handle<SharedFunctionInfo> shared =
       Compiler::CompileEval(source,
                             context,
-                            true,
-                            Compiler::DONT_VALIDATE_JSON);
+                            true);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
       Handle<JSFunction>(Factory::NewFunctionFromSharedFunctionInfo(shared,
diff --git a/src/runtime.h b/src/runtime.h
index 8057d8b..72a8037 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -164,6 +164,9 @@
   F(RegExpConstructResult, 3, 1) \
   F(RegExpCloneResult, 1, 1) \
   \
+  /* JSON */ \
+  F(ParseJson, 1, 1) \
+  \
   /* Strings */ \
   F(StringCharCodeAt, 2, 1) \
   F(StringIndexOf, 3, 1) \
@@ -222,7 +225,7 @@
   /* Numbers */ \
   \
   /* Globals */ \
-  F(CompileString, 2, 1) \
+  F(CompileString, 1, 1) \
   F(GlobalPrint, 1, 1) \
   \
   /* Eval */ \
diff --git a/src/scanner.h b/src/scanner.h
index 6e5333b..dab3d67 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -296,6 +296,9 @@
   // Returns the next token.
   Token::Value Next();
 
+  // Returns the current token again.
+  Token::Value current_token() { return current_.token; }
+
   // One token look-ahead (past the token returned by Next()).
   Token::Value peek() const { return next_.token; }
 
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 07d2197..9d947e4 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -241,13 +241,15 @@
   static void Clear();
 
   // Generate code for probing the stub cache table.
-  // If extra != no_reg it might be used as am extra scratch register.
+  // Arguments extra and extra2 may be used to pass additional scratch
+  // registers. Set to no_reg if not needed.
   static void GenerateProbe(MacroAssembler* masm,
                             Code::Flags flags,
                             Register receiver,
                             Register name,
                             Register scratch,
-                            Register extra);
+                            Register extra,
+                            Register extra2 = no_reg);
 
   enum Table {
     kPrimary,
diff --git a/src/top.h b/src/top.h
index e97289f..bc3a85e 100644
--- a/src/top.h
+++ b/src/top.h
@@ -105,7 +105,11 @@
   Address handler_;   // try-blocks are chained through the stack
 
 #ifdef USE_SIMULATOR
+#ifdef V8_TARGET_ARCH_ARM
   assembler::arm::Simulator* simulator_;
+#elif V8_TARGET_ARCH_MIPS
+  assembler::mips::Simulator* simulator_;
+#endif
 #endif  // USE_SIMULATOR
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
diff --git a/src/v8natives.js b/src/v8natives.js
index 88aea9c..50a2774 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -140,7 +140,7 @@
                          'be the global object from which eval originated');
   }
 
-  var f = %CompileString(x, false);
+  var f = %CompileString(x);
   if (!IS_FUNCTION(f)) return f;
 
   return f.call(this);
@@ -151,7 +151,7 @@
 function GlobalExecScript(expr, lang) {
   // NOTE: We don't care about the character casing.
   if (!lang || /javascript/i.test(lang)) {
-    var f = %CompileString(ToString(expr), false);
+    var f = %CompileString(ToString(expr));
     f.call(%GlobalReceiver(global));
   }
   return null;
@@ -1177,7 +1177,7 @@
 
   // The call to SetNewFunctionAttributes will ensure the prototype
   // property of the resulting function is enumerable (ECMA262, 15.3.5.2).
-  var f = %CompileString(source, false)();
+  var f = %CompileString(source)();
   %FunctionSetName(f, "anonymous");
   return %SetNewFunctionAttributes(f);
 }
diff --git a/src/version.cc b/src/version.cc
index 4017ae5..e27b915 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     2
 #define MINOR_VERSION     5
-#define BUILD_NUMBER      2
+#define BUILD_NUMBER      3
 #define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index 9e6ef3b..0faf775 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -4866,6 +4866,11 @@
   }
   frame_->Push(&clone);
 
+  // Mark all computed expressions that are bound to a key that
+  // is shadowed by a later occurrence of the same key. For the
+  // marked expressions, no store code is emitted.
+  node->CalculateEmitStore();
+
   for (int i = 0; i < node->properties()->length(); i++) {
     ObjectLiteral::Property* property = node->properties()->at(i);
     switch (property->kind()) {
@@ -4880,13 +4885,17 @@
           // Duplicate the object as the IC receiver.
           frame_->Dup();
           Load(property->value());
-          Result ignored =
-              frame_->CallStoreIC(Handle<String>::cast(key), false);
-          // A test rax instruction following the store IC call would
-          // indicate the presence of an inlined version of the
-          // store. Add a nop to indicate that there is no such
-          // inlined version.
-          __ nop();
+          if (property->emit_store()) {
+            Result ignored =
+                frame_->CallStoreIC(Handle<String>::cast(key), false);
+            // A test rax instruction following the store IC call would
+            // indicate the presence of an inlined version of the
+            // store. Add a nop to indicate that there is no such
+            // inlined version.
+            __ nop();
+          } else {
+            frame_->Drop(2);
+          }
           break;
         }
         // Fall through
@@ -4896,8 +4905,12 @@
         frame_->Dup();
         Load(property->key());
         Load(property->value());
-        Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
-        // Ignore the result.
+        if (property->emit_store()) {
+          // Ignore the result.
+          Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
+        } else {
+          frame_->Drop(3);
+        }
         break;
       }
       case ObjectLiteral::Property::SETTER: {
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 32d6242..4e0f6d4 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1158,6 +1158,11 @@
   // result_saved is false the result is in rax.
   bool result_saved = false;
 
+  // Mark all computed expressions that are bound to a key that
+  // is shadowed by a later occurrence of the same key. For the
+  // marked expressions, no store code is emitted.
+  expr->CalculateEmitStore();
+
   for (int i = 0; i < expr->properties()->length(); i++) {
     ObjectLiteral::Property* property = expr->properties()->at(i);
     if (property->IsCompileTimeValue()) continue;
@@ -1179,8 +1184,10 @@
           VisitForAccumulatorValue(value);
           __ Move(rcx, key->handle());
           __ movq(rdx, Operand(rsp, 0));
-          Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
-          EmitCallIC(ic, RelocInfo::CODE_TARGET);
+          if (property->emit_store()) {
+            Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+            EmitCallIC(ic, RelocInfo::CODE_TARGET);
+          }
           break;
         }
         // Fall through.
@@ -1188,7 +1195,11 @@
         __ push(Operand(rsp, 0));  // Duplicate receiver.
         VisitForStackValue(key);
         VisitForStackValue(value);
-        __ CallRuntime(Runtime::kSetProperty, 3);
+        if (property->emit_store()) {
+          __ CallRuntime(Runtime::kSetProperty, 3);
+        } else {
+          __ Drop(3);
+        }
         break;
       case ObjectLiteral::Property::SETTER:
       case ObjectLiteral::Property::GETTER:
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 3891e1d..24609bf 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -273,9 +273,11 @@
                               Register receiver,
                               Register name,
                               Register scratch,
-                              Register extra) {
+                              Register extra,
+                              Register extra2) {
   Label miss;
-  USE(extra);  // The register extra is not used on the X64 platform.
+  USE(extra);   // The register extra is not used on the X64 platform.
+  USE(extra2);  // The register extra2 is not used on the X64 platform.
   // Make sure that code is valid. The shifting code relies on the
   // entry size being 16.
   ASSERT(sizeof(Entry) == 16);
@@ -287,6 +289,10 @@
   ASSERT(!scratch.is(receiver));
   ASSERT(!scratch.is(name));
 
+  // Check scratch register is valid, extra and extra2 are unused.
+  ASSERT(!scratch.is(no_reg));
+  ASSERT(extra2.is(no_reg));
+
   // Check that the receiver isn't a smi.
   __ JumpIfSmi(receiver, &miss);