Push version 2.4.2 to trunk.

Fixed GC crash bug.

Fixed stack corruption bug.

Fixed compilation for newer C++ compilers that found Operand(0) ambiguous.


git-svn-id: http://v8.googlecode.com/svn/trunk@5425 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index cdf1b0f..95a3640 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,41 +1,51 @@
+2010-09-08: Version 2.4.2
+
+        Fixed GC crash bug.
+
+        Fixed stack corruption bug.
+
+        Fixed compilation for newer C++ compilers that found Operand(0)
+        ambiguous.
+
+
 2010-09-06: Version 2.4.1
 
-      Added the ability for an embedding application to receive a callback
-      when V8 allocates (V8::AddMemoryAllocationCallback) or deallocates
-      (V8::RemoveMemoryAllocationCallback) from the OS.
+        Added the ability for an embedding application to receive a callback
+        when V8 allocates (V8::AddMemoryAllocationCallback) or deallocates
+        (V8::RemoveMemoryAllocationCallback) from the OS.
 
-      Fixed several JSON bugs (including issue 855).
+        Fixed several JSON bugs (including issue 855).
 
-      Fixed memory overrun crash bug triggered during V8's tick-based
-      profiling.
+        Fixed memory overrun crash bug triggered during V8's tick-based
+        profiling.
 
-      Performance improvements on all platforms.
+        Performance improvements on all platforms.
 
 
 2010-09-01: Version 2.4.0
 
-      Fix bug in Object.freeze and Object.seal when Array.prototype or
-      Object.prototype is changed (issue 842).
+        Fix bug in Object.freeze and Object.seal when Array.prototype or
+        Object.prototype is changed (issue 842).
 
-      Update Array.splice to follow Safari and Firefox when called
-      with zero arguments.
+        Update Array.splice to follow Safari and Firefox when called
+        with zero arguments.
 
-      Fix a missing live register when breaking at keyed loads on ARM.
+        Fix a missing live register when breaking at keyed loads on ARM.
 
-      Performance improvements on all platforms.
+        Performance improvements on all platforms.
 
 
 2010-08-25: Version 2.3.11
 
-       Fix bug in RegExp related to copy-on-write arrays.
+        Fix bug in RegExp related to copy-on-write arrays.
 
-       Refactoring of tools/test.py script, including the introduction of
-       VARIANT_FLAGS that allows specification of sets of flags with which
-       all tests should be run.
+        Refactoring of tools/test.py script, including the introduction of
+        VARIANT_FLAGS that allows specification of sets of flags with which
+        all tests should be run.
 
-       Fix a bug in the handling of debug breaks in CallIC.
+        Fix a bug in the handling of debug breaks in CallIC.
 
-       Performance improvements on all platforms.
+        Performance improvements on all platforms.
 
 
 2010-08-23: Version 2.3.10
diff --git a/src/api.cc b/src/api.cc
index 4710557..0d01fcc 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1136,13 +1136,18 @@
 ScriptData* ScriptData::New(const char* data, int length) {
   // Return an empty ScriptData if the length is obviously invalid.
   if (length % sizeof(unsigned) != 0) {
-    return new i::ScriptDataImpl(i::Vector<unsigned>());
+    return new i::ScriptDataImpl();
   }
 
   // Copy the data to ensure it is properly aligned.
   int deserialized_data_length = length / sizeof(unsigned);
+  // If aligned, don't create a copy of the data.
+  if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
+    return new i::ScriptDataImpl(data, length);
+  }
+  // Copy the data to align it.
   unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
-  memcpy(deserialized_data, data, length);
+  i::MemCopy(deserialized_data, data, length);
 
   return new i::ScriptDataImpl(
       i::Vector<unsigned>(deserialized_data, deserialized_data_length));
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index a902fc2..8b21558 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -125,7 +125,7 @@
   __ LoadRoot(scratch1, Heap::kEmptyFixedArrayRootIndex);
   __ str(scratch1, FieldMemOperand(result, JSArray::kPropertiesOffset));
   // Field JSArray::kElementsOffset is initialized later.
-  __ mov(scratch3,  Operand(0));
+  __ mov(scratch3,  Operand(0, RelocInfo::NONE));
   __ str(scratch3, FieldMemOperand(result, JSArray::kLengthOffset));
 
   // Calculate the location of the elements array and set elements array member
@@ -311,7 +311,7 @@
   Label argc_one_or_more, argc_two_or_more;
 
   // Check for array construction with zero arguments or one.
-  __ cmp(r0, Operand(0));
+  __ cmp(r0, Operand(0, RelocInfo::NONE));
   __ b(ne, &argc_one_or_more);
 
   // Handle construction of an empty array.
@@ -513,7 +513,7 @@
   // r1: called object
   __ bind(&non_function_call);
   // Set expected number of arguments to zero (not changing r0).
-  __ mov(r2, Operand(0));
+  __ mov(r2, Operand(0, RelocInfo::NONE));
   __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
   __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
           RelocInfo::CODE_TARGET);
@@ -843,7 +843,7 @@
   // r5-r7, cp may be clobbered
 
   // Clear the context before we push it when entering the JS frame.
-  __ mov(cp, Operand(0));
+  __ mov(cp, Operand(0, RelocInfo::NONE));
 
   // Enter an internal frame.
   __ EnterInternalFrame();
@@ -1030,7 +1030,7 @@
   __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
   __ str(r1, MemOperand(r2, -kPointerSize));
   // Clear r1 to indicate a non-function being called.
-  __ mov(r1, Operand(0));
+  __ mov(r1, Operand(0, RelocInfo::NONE));
 
   // 4. Shift arguments and return address one slot down on the stack
   //    (overwriting the original receiver).  Adjust argument count to make
@@ -1060,7 +1060,8 @@
   { Label function;
     __ tst(r1, r1);
     __ b(ne, &function);
-    __ mov(r2, Operand(0));  // expected arguments is 0 for CALL_NON_FUNCTION
+    // Expected number of arguments is 0 for CALL_NON_FUNCTION.
+    __ mov(r2, Operand(0, RelocInfo::NONE));
     __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
     __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
                          RelocInfo::CODE_TARGET);
@@ -1123,7 +1124,7 @@
   // Push current limit and index.
   __ bind(&okay);
   __ push(r0);  // limit
-  __ mov(r1, Operand(0));  // initial index
+  __ mov(r1, Operand(0, RelocInfo::NONE));  // initial index
   __ push(r1);
 
   // Change context eagerly to get the right global object if necessary.
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 0e479e2..fa93030 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -296,7 +296,7 @@
   STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
   __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC);
   // Subtract from 0 if source was negative.
-  __ rsb(source_, source_, Operand(0), LeaveCC, ne);
+  __ rsb(source_, source_, Operand(0, RelocInfo::NONE), LeaveCC, ne);
 
   // We have -1, 0 or 1, which we treat specially. Register source_ contains
   // absolute value: it is either equal to 1 (special case of -1 and 1),
@@ -309,7 +309,7 @@
       HeapNumber::kExponentBias << HeapNumber::kExponentShift;
   __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, eq);
   // 1, 0 and -1 all have 0 for the second word.
-  __ mov(mantissa, Operand(0));
+  __ mov(mantissa, Operand(0, RelocInfo::NONE));
   __ Ret();
 
   __ bind(&not_special);
@@ -357,7 +357,7 @@
   // Set the sign bit in scratch_ if the value was negative.
   __ orr(scratch_, scratch_, Operand(HeapNumber::kSignMask), LeaveCC, cs);
   // Subtract from 0 if the value was negative.
-  __ rsb(the_int_, the_int_, Operand(0), LeaveCC, cs);
+  __ rsb(the_int_, the_int_, Operand(0, RelocInfo::NONE), LeaveCC, cs);
   // We should be masking the implict first digit of the mantissa away here,
   // but it just ends up combining harmlessly with the last digit of the
   // exponent that happens to be 1.  The sign bit is 0 so we shift 10 to get
@@ -380,7 +380,7 @@
   non_smi_exponent += 1 << HeapNumber::kExponentShift;
   __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent));
   __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset));
-  __ mov(ip, Operand(0));
+  __ mov(ip, Operand(0, RelocInfo::NONE));
   __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset));
   __ Ret();
 }
@@ -604,7 +604,7 @@
          Operand(lhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
          SetCC);
   __ b(ne, &one_is_nan);
-  __ cmp(lhs_mantissa, Operand(0));
+  __ cmp(lhs_mantissa, Operand(0, RelocInfo::NONE));
   __ b(ne, &one_is_nan);
 
   __ bind(lhs_not_nan);
@@ -619,7 +619,7 @@
          Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
          SetCC);
   __ b(ne, &one_is_nan);
-  __ cmp(rhs_mantissa, Operand(0));
+  __ cmp(rhs_mantissa, Operand(0, RelocInfo::NONE));
   __ b(eq, &neither_is_nan);
 
   __ bind(&one_is_nan);
@@ -1085,8 +1085,8 @@
   // "tos_" is a register, and contains a non zero value by default.
   // Hence we only need to overwrite "tos_" with zero to return false for
   // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true.
-  __ mov(tos_, Operand(0), LeaveCC, eq);  // for FP_ZERO
-  __ mov(tos_, Operand(0), LeaveCC, vs);  // for FP_NAN
+  __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq);  // for FP_ZERO
+  __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs);  // for FP_NAN
   __ Ret();
 
   __ bind(&not_heap_number);
@@ -1131,7 +1131,7 @@
 
   // Return 0 in "tos_" for false .
   __ bind(&false_result);
-  __ mov(tos_, Operand(0));
+  __ mov(tos_, Operand(0, RelocInfo::NONE));
   __ Ret();
 }
 
@@ -2231,7 +2231,7 @@
     __ ldr(r0, MemOperand(r0, type_ * sizeof(TranscendentalCache::caches_[0])));
     // r0 points to the cache for the type type_.
     // If NULL, the cache hasn't been initialized yet, so go through runtime.
-    __ cmp(r0, Operand(0));
+    __ cmp(r0, Operand(0, RelocInfo::NONE));
     __ b(eq, &runtime_call);
 
 #ifdef DEBUG
@@ -2311,12 +2311,12 @@
       // smi while we are at it.
       __ bic(ip, r0, Operand(0x80000000), SetCC);
       __ b(eq, &slow);
-      __ rsb(r0, r0, Operand(0));
+      __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
       __ StubReturn(1);
     } else {
       // The value of the expression is a smi and 0 is OK for -0.  Try
       // optimistic subtraction '0 - value'.
-      __ rsb(r0, r0, Operand(0), SetCC);
+      __ rsb(r0, r0, Operand(0, RelocInfo::NONE), SetCC);
       __ StubReturn(1, vc);
       // We don't have to reverse the optimistic neg since the only case
       // where we fall through is the minimum negative Smi, which is the case
@@ -2429,9 +2429,9 @@
   // Before returning we restore the context from the frame pointer if
   // not NULL.  The frame pointer is NULL in the exception handler of a
   // JS entry frame.
-  __ cmp(fp, Operand(0));
+  __ cmp(fp, Operand(0, RelocInfo::NONE));
   // Set cp to NULL if fp is NULL.
-  __ mov(cp, Operand(0), LeaveCC, eq);
+  __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
   // Restore cp otherwise.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
 #ifdef DEBUG
@@ -2497,9 +2497,9 @@
   // Before returning we restore the context from the frame pointer if
   // not NULL.  The frame pointer is NULL in the exception handler of a
   // JS entry frame.
-  __ cmp(fp, Operand(0));
+  __ cmp(fp, Operand(0, RelocInfo::NONE));
   // Set cp to NULL if fp is NULL.
-  __ mov(cp, Operand(0), LeaveCC, eq);
+  __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
   // Restore cp otherwise.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
 #ifdef DEBUG
@@ -2567,7 +2567,7 @@
       (frame_alignment_skew + kPointerSize) & frame_alignment_mask;
   if (alignment_before_call > 0) {
     // Push until the alignment before the call is met.
-    __ mov(r2, Operand(0));
+    __ mov(r2, Operand(0, RelocInfo::NONE));
     for (int i = alignment_before_call;
         (i & frame_alignment_mask) != 0;
         i += kPointerSize) {
@@ -2991,7 +2991,7 @@
   // of the arguments object and the elements array in words.
   Label add_arguments_object;
   __ bind(&try_allocate);
-  __ cmp(r1, Operand(0));
+  __ cmp(r1, Operand(0, RelocInfo::NONE));
   __ b(eq, &add_arguments_object);
   __ mov(r1, Operand(r1, LSR, kSmiTagSize));
   __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize));
@@ -3028,7 +3028,7 @@
 
   // If there are no actual arguments, we're done.
   Label done;
-  __ cmp(r1, Operand(0));
+  __ cmp(r1, Operand(0, RelocInfo::NONE));
   __ b(eq, &done);
 
   // Get the parameters pointer from the stack.
@@ -3054,7 +3054,7 @@
   // Post-increment r4 with kPointerSize on each iteration.
   __ str(r3, MemOperand(r4, kPointerSize, PostIndex));
   __ sub(r1, r1, Operand(1));
-  __ cmp(r1, Operand(0));
+  __ cmp(r1, Operand(0, RelocInfo::NONE));
   __ b(ne, &loop);
 
   // Return and remove the on-stack parameters.
@@ -3452,7 +3452,7 @@
   // of the original receiver from the call site).
   __ str(r1, MemOperand(sp, argc_ * kPointerSize));
   __ mov(r0, Operand(argc_));  // Setup the number of arguments.
-  __ mov(r2, Operand(0));
+  __ mov(r2, Operand(0, RelocInfo::NONE));
   __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
   __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
           RelocInfo::CODE_TARGET);
@@ -3794,7 +3794,7 @@
   if (!ascii) {
     __ add(count, count, Operand(count), SetCC);
   } else {
-    __ cmp(count, Operand(0));
+    __ cmp(count, Operand(0, RelocInfo::NONE));
   }
   __ b(eq, &done);
 
@@ -3849,7 +3849,7 @@
   if (!ascii) {
     __ add(count, count, Operand(count), SetCC);
   } else {
-    __ cmp(count, Operand(0));
+    __ cmp(count, Operand(0, RelocInfo::NONE));
   }
   __ b(eq, &done);
 
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 698d0c8..f985fb4 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -770,7 +770,7 @@
       ToBooleanStub stub(tos);
       frame_->CallStub(&stub, 0);
       // Convert the result in "tos" to a condition code.
-      __ cmp(tos, Operand(0));
+      __ cmp(tos, Operand(0, RelocInfo::NONE));
     } else {
       // Implements slow case by calling the runtime.
       frame_->EmitPush(tos);
@@ -1129,7 +1129,7 @@
         __ mov(int32, Operand(int32, LSR, shift_value), SetCC);
       } else {
         // SHR is special because it is required to produce a positive answer.
-        __ cmp(int32, Operand(0));
+        __ cmp(int32, Operand(0, RelocInfo::NONE));
       }
       if (CpuFeatures::IsSupported(VFP3)) {
         __ b(mi, &result_not_a_smi);
@@ -1513,7 +1513,7 @@
             }
             __ mov(tos, Operand(tos, LSL, kSmiTagSize));
           } else {
-            __ cmp(tos, Operand(0));
+            __ cmp(tos, Operand(0, RelocInfo::NONE));
             deferred->JumpToAnswerOutOfRange(mi);
           }
           break;
@@ -1653,7 +1653,7 @@
     // We call with 0 args because there are 0 on the stack.
     CompareStub stub(cc, strict, kBothCouldBeNaN, true, lhs, rhs);
     frame_->CallStub(&stub, 0);
-    __ cmp(r0, Operand(0));
+    __ cmp(r0, Operand(0, RelocInfo::NONE));
     exit.Jump();
 
     smi.Bind();
@@ -1817,7 +1817,7 @@
   // frame.
   Label loop;
   // r3 is a small non-negative integer, due to the test above.
-  __ cmp(r3, Operand(0));
+  __ cmp(r3, Operand(0, RelocInfo::NONE));
   __ b(eq, &invoke);
   // Compute the address of the first argument.
   __ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2));
@@ -1975,7 +1975,7 @@
     } else if (node->fun() != NULL) {
       Load(node->fun());
     } else {
-      frame_->EmitPush(Operand(0));
+      frame_->EmitPush(Operand(0, RelocInfo::NONE));
     }
 
     frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
@@ -4612,7 +4612,8 @@
     // Get the absolute untagged value of the exponent and use that for the
     // calculation.
     __ mov(scratch1, Operand(exponent, ASR, kSmiTagSize), SetCC);
-    __ rsb(scratch1, scratch1, Operand(0), LeaveCC, mi);  // Negate if negative.
+    // Negate if negative.
+    __ rsb(scratch1, scratch1, Operand(0, RelocInfo::NONE), LeaveCC, mi);
     __ vmov(d2, d0, mi);  // 1.0 needed in d2 later if exponent is negative.
 
     // Run through all the bits in the exponent. The result is calculated in d0
@@ -4625,14 +4626,14 @@
     __ b(ne, &more_bits);
 
     // If exponent is positive we are done.
-    __ cmp(exponent, Operand(0));
+    __ cmp(exponent, Operand(0, RelocInfo::NONE));
     __ b(ge, &allocate_return);
 
     // If exponent is negative result is 1/result (d2 already holds 1.0 in that
     // case). However if d0 has reached infinity this will not provide the
     // correct result, so call runtime if that is the case.
     __ mov(scratch2, Operand(0x7FF00000));
-    __ mov(scratch1, Operand(0));
+    __ mov(scratch1, Operand(0, RelocInfo::NONE));
     __ vmov(d1, scratch1, scratch2);  // Load infinity into d1.
     __ vcmp(d0, d1);
     __ vmrs(pc);
@@ -5135,7 +5136,7 @@
     __ jmp(exit_label());
     __ bind(&false_result);
     // Set false result.
-    __ mov(map_result_, Operand(0));
+    __ mov(map_result_, Operand(0, RelocInfo::NONE));
   }
 
  private:
@@ -5309,7 +5310,7 @@
     // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
     __ vmov(d7, r0, r1);
     // Move 0x4130000000000000 to VFP.
-    __ mov(r0, Operand(0));
+    __ mov(r0, Operand(0, RelocInfo::NONE));
     __ vmov(d8, r0, r1);
     // Subtract and store the result in the heap number.
     __ vsub(d7, d7, d8);
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index 82f93b6..8128f7d 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -158,7 +158,7 @@
 #ifdef DEBUG
   __ RecordComment("// Calling from debug break to runtime - come in - over");
 #endif
-  __ mov(r0, Operand(0));  // no arguments
+  __ mov(r0, Operand(0, RelocInfo::NONE));  // no arguments
   __ mov(r1, Operand(ExternalReference::debug_break()));
 
   CEntryStub ceb(1);
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 912fefc..f32da6d 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -688,7 +688,7 @@
 
     CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0);
     __ CallStub(&stub);
-    __ cmp(r0, Operand(0));
+    __ cmp(r0, Operand(0, RelocInfo::NONE));
     __ b(ne, &next_test);
     __ Drop(1);  // Switch value is no longer needed.
     __ b(clause->body_target()->entry_label());
@@ -2132,7 +2132,7 @@
     // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
     __ vmov(d7, r0, r1);
     // Move 0x4130000000000000 to VFP.
-    __ mov(r0, Operand(0));
+    __ mov(r0, Operand(0, RelocInfo::NONE));
     __ vmov(d8, r0, r1);
     // Subtract and store the result in the heap number.
     __ vsub(d7, d7, d8);
@@ -3125,7 +3125,7 @@
 
       CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0);
       __ CallStub(&stub);
-      __ cmp(r0, Operand(0));
+      __ cmp(r0, Operand(0, RelocInfo::NONE));
       Split(cc, if_true, if_false, fall_through);
     }
   }
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 49d7b2d..1a76db2 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -1292,7 +1292,7 @@
     __ mov(loword, Operand(hiword, LSL, mantissa_shift_for_lo_word));
     __ orr(hiword, scratch, Operand(hiword, LSR, mantissa_shift_for_hi_word));
   } else {
-    __ mov(loword, Operand(0));
+    __ mov(loword, Operand(0, RelocInfo::NONE));
     __ orr(hiword, scratch, Operand(hiword, LSL, mantissa_shift_for_hi_word));
   }
 
@@ -1790,7 +1790,7 @@
 
     __ and_(fval, ival, Operand(kBinary32SignMask), SetCC);
     // Negate value if it is negative.
-    __ rsb(ival, ival, Operand(0), LeaveCC, ne);
+    __ rsb(ival, ival, Operand(0, RelocInfo::NONE), LeaveCC, ne);
 
     // We have -1, 0 or 1, which we treat specially. Register ival contains
     // absolute value: it is either equal to 1 (special case of -1 and 1),
@@ -2075,18 +2075,18 @@
       // and infinities. All these should be converted to 0.
       __ mov(r7, Operand(HeapNumber::kExponentMask));
       __ and_(r9, r5, Operand(r7), SetCC);
-      __ mov(r5, Operand(0), LeaveCC, eq);
+      __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
       __ b(eq, &done);
 
       __ teq(r9, Operand(r7));
-      __ mov(r5, Operand(0), LeaveCC, eq);
+      __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
       __ b(eq, &done);
 
       // Unbias exponent.
       __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
       __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC);
       // If exponent is negative than result is 0.
-      __ mov(r5, Operand(0), LeaveCC, mi);
+      __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi);
       __ b(mi, &done);
 
       // If exponent is too big than result is minimal value.
@@ -2102,14 +2102,14 @@
       __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl);
       __ b(pl, &sign);
 
-      __ rsb(r9, r9, Operand(0));
+      __ rsb(r9, r9, Operand(0, RelocInfo::NONE));
       __ mov(r5, Operand(r5, LSL, r9));
       __ rsb(r9, r9, Operand(meaningfull_bits));
       __ orr(r5, r5, Operand(r6, LSR, r9));
 
       __ bind(&sign);
-      __ teq(r7, Operand(0));
-      __ rsb(r5, r5, Operand(0), LeaveCC, ne);
+      __ teq(r7, Operand(0, RelocInfo::NONE));
+      __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
 
       __ bind(&done);
       switch (array_type) {
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 36a36be..3554431 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -226,7 +226,7 @@
   }
   int32_t immediate = src2.immediate();
   if (immediate == 0) {
-    mov(dst, Operand(0), LeaveCC, cond);
+    mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, cond);
     return;
   }
   if (IsPowerOf2(immediate + 1) && ((immediate & 1) != 0)) {
@@ -305,7 +305,7 @@
     }
     tst(dst, Operand(~satval));
     b(eq, &done);
-    mov(dst, Operand(0), LeaveCC, mi);  // 0 if negative.
+    mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, mi);  // 0 if negative.
     mov(dst, Operand(satval), LeaveCC, pl);  // satval if positive.
     bind(&done);
   } else {
@@ -594,7 +594,7 @@
 
 void MacroAssembler::LeaveExitFrame() {
   // Clear top frame.
-  mov(r3, Operand(0));
+  mov(r3, Operand(0, RelocInfo::NONE));
   mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
   str(r3, MemOperand(ip));
 
@@ -763,7 +763,7 @@
 #ifdef ENABLE_DEBUGGER_SUPPORT
 void MacroAssembler::DebugBreak() {
   ASSERT(allow_stub_calls());
-  mov(r0, Operand(0));
+  mov(r0, Operand(0, RelocInfo::NONE));
   mov(r1, Operand(ExternalReference(Runtime::kDebugBreak)));
   CEntryStub ces(1);
   Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
@@ -799,7 +799,7 @@
     // The frame pointer does not point to a JS frame so we save NULL
     // for fp. We expect the code throwing an exception to check fp
     // before dereferencing it to restore the context.
-    mov(ip, Operand(0));  // To save a NULL frame pointer.
+    mov(ip, Operand(0, RelocInfo::NONE));  // To save a NULL frame pointer.
     mov(r6, Operand(StackHandler::ENTRY));
     ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize
            && StackHandlerConstants::kFPOffset == 2 * kPointerSize
@@ -838,7 +838,7 @@
   ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
   // In debug mode, make sure the lexical context is set.
 #ifdef DEBUG
-  cmp(scratch, Operand(0));
+  cmp(scratch, Operand(0, RelocInfo::NONE));
   Check(ne, "we should not have an empty lexical context");
 #endif
 
@@ -1373,7 +1373,7 @@
             HeapNumber::kExponentBits);
     // Load dest with zero.  We use this either for the final shift or
     // for the answer.
-    mov(dest, Operand(0));
+    mov(dest, Operand(0, RelocInfo::NONE));
     // Check whether the exponent matches a 32 bit signed int that is not a Smi.
     // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). This is
     // the exponent that we are fastest at and also the highest exponent we can
@@ -1427,7 +1427,7 @@
     // Move down according to the exponent.
     mov(dest, Operand(scratch, LSR, dest));
     // Fix sign if sign bit was set.
-    rsb(dest, dest, Operand(0), LeaveCC, ne);
+    rsb(dest, dest, Operand(0, RelocInfo::NONE), LeaveCC, ne);
     bind(&done);
   }
 }
@@ -1818,7 +1818,7 @@
 #ifdef CAN_USE_ARMV5_INSTRUCTIONS
   clz(zeros, source);  // This instruction is only supported after ARM5.
 #else
-  mov(zeros, Operand(0));
+  mov(zeros, Operand(0, RelocInfo::NONE));
   Move(scratch, source);
   // Top 16.
   tst(scratch, Operand(0xffff0000));
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index 72b635f..8f45886 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -189,7 +189,7 @@
   Label not_at_start;
   // Did we start the match at the start of the string at all?
   __ ldr(r0, MemOperand(frame_pointer(), kAtStart));
-  __ cmp(r0, Operand(0));
+  __ cmp(r0, Operand(0, RelocInfo::NONE));
   BranchOrBacktrack(eq, &not_at_start);
 
   // If we did, are we still at the start of the input?
@@ -204,7 +204,7 @@
 void RegExpMacroAssemblerARM::CheckNotAtStart(Label* on_not_at_start) {
   // Did we start the match at the start of the string at all?
   __ ldr(r0, MemOperand(frame_pointer(), kAtStart));
-  __ cmp(r0, Operand(0));
+  __ cmp(r0, Operand(0, RelocInfo::NONE));
   BranchOrBacktrack(eq, on_not_at_start);
   // If we did, are we still at the start of the input?
   __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
@@ -364,7 +364,7 @@
     __ CallCFunction(function, argument_count);
 
     // Check if function returned non-zero for success or zero for failure.
-    __ cmp(r0, Operand(0));
+    __ cmp(r0, Operand(0, RelocInfo::NONE));
     BranchOrBacktrack(eq, on_no_match);
     // On success, increment position by length of capture.
     __ add(current_input_offset(), current_input_offset(), Operand(r4));
@@ -634,7 +634,7 @@
 
   __ bind(&stack_limit_hit);
   CallCheckStackGuardState(r0);
-  __ cmp(r0, Operand(0));
+  __ cmp(r0, Operand(0, RelocInfo::NONE));
   // If returned value is non-zero, we exit with the returned value as result.
   __ b(ne, &exit_label_);
 
@@ -661,7 +661,7 @@
   // string, and store that value in a local variable.
   __ tst(r1, Operand(r1));
   __ mov(r1, Operand(1), LeaveCC, eq);
-  __ mov(r1, Operand(0), LeaveCC, ne);
+  __ mov(r1, Operand(0, RelocInfo::NONE), LeaveCC, ne);
   __ str(r1, MemOperand(frame_pointer(), kAtStart));
 
   if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
@@ -684,7 +684,7 @@
   // Load previous char as initial value of current character register.
   Label at_start;
   __ ldr(r0, MemOperand(frame_pointer(), kAtStart));
-  __ cmp(r0, Operand(0));
+  __ cmp(r0, Operand(0, RelocInfo::NONE));
   __ b(ne, &at_start);
   LoadCurrentCharacterUnchecked(-1, 1);  // Load previous char.
   __ jmp(&start_label_);
@@ -751,7 +751,7 @@
     SafeCallTarget(&check_preempt_label_);
 
     CallCheckStackGuardState(r0);
-    __ cmp(r0, Operand(0));
+    __ cmp(r0, Operand(0, RelocInfo::NONE));
     // If returning non-zero, we should end execution with the given
     // result as return value.
     __ b(ne, &exit_label_);
@@ -778,7 +778,7 @@
     __ CallCFunction(grow_stack, num_arguments);
     // If return NULL, we have failed to grow the stack, and
     // must exit with a stack-overflow exception.
-    __ cmp(r0, Operand(0));
+    __ cmp(r0, Operand(0, RelocInfo::NONE));
     __ b(eq, &exit_with_exception);
     // Otherwise use return value as new stack pointer.
     __ mov(backtrack_stackpointer(), r0);
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 59cbad9..5ffebfb 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -825,7 +825,7 @@
 
 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
   Comment cmnt(masm_, "[ WhileStatement");
-  Label body, stack_limit_hit, stack_check_success;
+  Label body, stack_limit_hit, stack_check_success, done;
 
   Iteration loop_statement(this, stmt);
   increment_loop_depth();
@@ -833,11 +833,6 @@
   // Emit the test at the bottom of the loop.
   __ jmp(loop_statement.continue_target());
 
-  __ bind(&stack_limit_hit);
-  StackCheckStub stack_stub;
-  __ CallStub(&stack_stub);
-  __ jmp(&stack_check_success);
-
   __ bind(&body);
   Visit(stmt->body());
   __ bind(loop_statement.continue_target());
@@ -856,6 +851,14 @@
                   loop_statement.break_target());
 
   __ bind(loop_statement.break_target());
+  __ jmp(&done);
+
+  __ bind(&stack_limit_hit);
+  StackCheckStub stack_stub;
+  __ CallStub(&stack_stub);
+  __ jmp(&stack_check_success);
+
+  __ bind(&done);
   decrement_loop_depth();
 }
 
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index bfd2650..366b91e 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -1001,15 +1001,16 @@
     }
   }
 
+  // If all else fails, use the runtime system to get the correct
+  // result. If arguments was passed in registers now place them on the
+  // stack in the correct order below the return address.
+
   // Avoid hitting the string ADD code below when allocation fails in
   // the floating point code above.
   if (op_ != Token::ADD) {
     __ bind(&call_runtime);
   }
 
-  // If all else fails, use the runtime system to get the correct
-  // result. If arguments was passed in registers now place them on the
-  // stack in the correct order below the return address.
   if (HasArgsInRegisters()) {
     GenerateRegisterArgsPush(masm);
   }
@@ -1044,12 +1045,13 @@
       StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB);
       __ TailCallStub(&string_add_left_stub);
 
+      Label call_runtime_with_args;
       // Left operand is not a string, test right.
       __ bind(&lhs_not_string);
       __ test(rhs, Immediate(kSmiTagMask));
-      __ j(zero, &call_runtime);
+      __ j(zero, &call_runtime_with_args);
       __ CmpObjectType(rhs, FIRST_NONSTRING_TYPE, ecx);
-      __ j(above_equal, &call_runtime);
+      __ j(above_equal, &call_runtime_with_args);
 
       StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
       __ TailCallStub(&string_add_right_stub);
@@ -1059,6 +1061,7 @@
       if (HasArgsInRegisters()) {
         GenerateRegisterArgsPush(masm);
       }
+      __ bind(&call_runtime_with_args);
       __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
       break;
     }
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 162b3d6..a9e852e 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -643,9 +643,13 @@
 #endif
   StaticMarkingVisitor::EnableCodeFlushing(true);
 
+  // Ensure that empty descriptor array is marked. Method MarkDescriptorArray
+  // relies on it being marked before any other descriptor array.
+  MarkObject(Heap::raw_unchecked_empty_descriptor_array());
+
   // Make sure we are not referencing the code from the stack.
   for (StackFrameIterator it; !it.done(); it.Advance()) {
-    MarkCompactCollector::MarkObject(it.frame()->unchecked_code());
+    MarkObject(it.frame()->unchecked_code());
   }
 
   // Iterate the archived stacks in all threads to check if
@@ -656,7 +660,7 @@
   SharedFunctionInfoMarkingVisitor visitor;
   CompilationCache::IterateFunctions(&visitor);
 
-  MarkCompactCollector::ProcessMarkingStack();
+  ProcessMarkingStack();
 }
 
 
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 26fea25..9532938 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -94,7 +94,7 @@
   // args
 
   // Clear the context before we push it when entering the JS frame.
-  __ li(cp, Operand(0));
+  __ li(cp, Operand(0, RelocInfo::NONE));
 
   // Enter an internal frame.
   __ EnterInternalFrame();
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 2a54062..bac224f 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2109,7 +2109,16 @@
 }
 
 
-INT_ACCESSORS(Map, visitor_id, kScavengerCallbackOffset)
+int Map::visitor_id() {
+  return READ_BYTE_FIELD(this, kVisitorIdOffset);
+}
+
+
+void Map::set_visitor_id(int id) {
+  ASSERT(0 <= id && id < 256);
+  WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
+}
+
 
 int Map::instance_size() {
   return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index 95dc66c..a6d6b12 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -106,6 +106,9 @@
     kMinObjectSizeInWords = 2
   };
 
+  // Visitor ID should fit in one byte.
+  STATIC_ASSERT(kVisitorIdCount <= 256);
+
   // Determine which specialized visitor should be used for given instance type
   // and instance type.
   static VisitorId GetVisitorId(int instance_type, int instance_size);
diff --git a/src/objects.cc b/src/objects.cc
index 9b43d24..ef51851 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2126,9 +2126,6 @@
         // The cached map should match newly created normalized map bit-by-bit.
         Object* fresh = fast->CopyNormalized(mode);
         if (!fresh->IsFailure()) {
-          // Copy the unused byte so that the assertion below works.
-          Map::cast(fresh)->address()[Map::kUnusedOffset] =
-              Map::cast(result)->address()[Map::kUnusedOffset];
           ASSERT(memcmp(Map::cast(fresh)->address(),
                         Map::cast(result)->address(),
                         Map::kSize) == 0);
@@ -4991,17 +4988,20 @@
 }
 
 
-uint32_t StringHasher::MakeCachedArrayIndex(uint32_t value, int length) {
-  value <<= String::kHashShift;
+uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
   // For array indexes mix the length into the hash as an array index could
   // be zero.
   ASSERT(length > 0);
   ASSERT(length <= String::kMaxArrayIndexSize);
   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
          (1 << String::kArrayIndexValueBits));
-  ASSERT(String::kMaxArrayIndexSize < (1 << String::kArrayIndexValueBits));
-  value &= ~String::kIsNotArrayIndexMask;
+
+  value <<= String::kHashShift;
   value |= length << String::kArrayIndexHashLengthShift;
+
+  ASSERT((value & String::kIsNotArrayIndexMask) == 0);
+  ASSERT((length > String::kMaxCachedArrayIndexLength) ||
+         (value & String::kContainsCachedArrayIndexMask) == 0);
   return value;
 }
 
@@ -5010,7 +5010,7 @@
   ASSERT(is_valid());
   if (length_ <= String::kMaxHashCalcLength) {
     if (is_array_index()) {
-      return MakeCachedArrayIndex(array_index(), length_);
+      return MakeArrayIndexHash(array_index(), length_);
     }
     return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask;
   } else {
diff --git a/src/objects.h b/src/objects.h
index 11d65ef..7f6538c 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -3245,8 +3245,7 @@
   static const int kInstanceDescriptorsOffset =
       kConstructorOffset + kPointerSize;
   static const int kCodeCacheOffset = kInstanceDescriptorsOffset + kPointerSize;
-  static const int kScavengerCallbackOffset = kCodeCacheOffset + kPointerSize;
-  static const int kPadStart = kScavengerCallbackOffset + kPointerSize;
+  static const int kPadStart = kCodeCacheOffset + kPointerSize;
   static const int kSize = MAP_POINTER_ALIGN(kPadStart);
 
   // Layout of pointer fields. Heap iteration code relies on them
@@ -3263,9 +3262,8 @@
   static const int kPreAllocatedPropertyFieldsByte = 2;
   static const int kPreAllocatedPropertyFieldsOffset =
       kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
-  // The byte at position 3 is not in use at the moment.
-  static const int kUnusedByte = 3;
-  static const int kUnusedOffset = kInstanceSizesOffset + kUnusedByte;
+  static const int kVisitorIdByte = 3;
+  static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
 
   // Byte offsets within kInstanceAttributesOffset attributes.
   static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
@@ -4225,7 +4223,7 @@
   // Calculated hash value for a string consisting of 1 to
   // String::kMaxArrayIndexSize digits with no leading zeros (except "0").
   // value is represented decimal value.
-  static uint32_t MakeCachedArrayIndex(uint32_t value, int length);
+  static uint32_t MakeArrayIndexHash(uint32_t value, int length);
 
  private:
 
@@ -4469,6 +4467,7 @@
       kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
 
   STATIC_CHECK((kArrayIndexLengthBits > 0));
+  STATIC_CHECK(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
 
   static const int kArrayIndexHashLengthShift =
       kArrayIndexValueBits + kNofHashBitFields;
diff --git a/src/parser.cc b/src/parser.cc
index b689eb8..7667e89 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -266,6 +266,8 @@
   bool Check(Token::Value token);
   void ExpectSemicolon(bool* ok);
 
+  Handle<String> GetSymbol(bool* ok);
+
   // Get odd-ball literals.
   Literal* GetLiteralUndefined();
   Literal* GetLiteralTheHole();
@@ -828,7 +830,7 @@
 
   virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);
 
-  virtual Handle<String> LookupSymbol(const char* string, int length) {
+  virtual Handle<String> LookupSymbol(int index, Vector<const char> string) {
     return Handle<String>();
   }
 
@@ -869,20 +871,46 @@
 
   // Records the occurrence of a function.
   virtual FunctionEntry LogFunction(int start) { return FunctionEntry(); }
+  virtual void LogSymbol(int start, Vector<const char> symbol) {}
   // Return the current position in the function entry log.
-  virtual int position() { return 0; }
+  virtual int function_position() { return 0; }
+  virtual int symbol_position() { return 0; }
+  virtual int symbol_ids() { return 0; }
   virtual void LogError() { }
 };
 
 
 class AstBuildingParserFactory : public ParserFactory {
  public:
-  AstBuildingParserFactory() : ParserFactory(false) { }
+  explicit AstBuildingParserFactory(int expected_symbols)
+      : ParserFactory(false), symbol_cache_(expected_symbols) { }
 
   virtual Scope* NewScope(Scope* parent, Scope::Type type, bool inside_with);
 
-  virtual Handle<String> LookupSymbol(const char* string, int length) {
-    return Factory::LookupSymbol(Vector<const char>(string, length));
+  virtual Handle<String> LookupSymbol(int symbol_id,
+                                      Vector<const char> string) {
+    // If there is no preparse data, we have no simpler way to identify similar
+    // symbols.
+    if (symbol_id < 0) return Factory::LookupSymbol(string);
+    return LookupCachedSymbol(symbol_id, string);
+  }
+
+  Handle<String> LookupCachedSymbol(int symbol_id,
+                                    Vector<const char> string) {
+    // Make sure the cache is large enough to hold the symbol identifier.
+    if (symbol_cache_.length() <= symbol_id) {
+      // Increase length to index + 1.
+      symbol_cache_.AddBlock(Handle<String>::null(),
+                             symbol_id + 1 - symbol_cache_.length());
+    }
+    Handle<String> result = symbol_cache_.at(symbol_id);
+    if (result.is_null()) {
+      result = Factory::LookupSymbol(string);
+      symbol_cache_.at(symbol_id) = result;
+      return result;
+    }
+    Counters::total_preparse_symbols_skipped.Increment();
+    return result;
   }
 
   virtual Handle<String> EmptySymbol() {
@@ -900,6 +928,8 @@
   }
 
   virtual Statement* EmptyStatement();
+ private:
+  List<Handle<String> > symbol_cache_;
 };
 
 
@@ -907,22 +937,74 @@
  public:
   ParserRecorder();
   virtual FunctionEntry LogFunction(int start);
+  virtual void LogSymbol(int start, Vector<const char> literal) {
+    int hash = vector_hash(literal);
+    HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
+    int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
+    if (id == 0) {
+      // Put (symbol_id_ + 1) into entry and increment it.
+      symbol_id_++;
+      entry->value = reinterpret_cast<void*>(symbol_id_);
+      Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
+      entry->key = &symbol[0];
+    } else {
+      // Log a reuse of an earlier seen symbol.
+      symbol_store_.Add(start);
+      symbol_store_.Add(id - 1);
+    }
+  }
   virtual void LogError() { }
   virtual void LogMessage(Scanner::Location loc,
                           const char* message,
                           Vector<const char*> args);
   Vector<unsigned> ExtractData() {
-    int total_size = ScriptDataImpl::kHeaderSize + store_.size();
+    int function_size = function_store_.size();
+    int symbol_size = symbol_store_.size();
+    int total_size = ScriptDataImpl::kHeaderSize + function_size + symbol_size;
     Vector<unsigned> data = Vector<unsigned>::New(total_size);
+    preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size;
+    preamble_[ScriptDataImpl::kSymbolCountOffset] = symbol_id_;
     memcpy(data.start(), preamble_, sizeof(preamble_));
-    if (ScriptDataImpl::kHeaderSize < total_size) {
-      store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize, total_size));
+    int symbol_start = ScriptDataImpl::kHeaderSize + function_size;
+    if (function_size > 0) {
+      function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize,
+                                             symbol_start));
+    }
+    if (symbol_size > 0) {
+      symbol_store_.WriteTo(data.SubVector(symbol_start, total_size));
     }
     return data;
   }
-  virtual int position() { return store_.size(); }
+
+  virtual int function_position() { return function_store_.size(); }
+  virtual int symbol_position() { return symbol_store_.size(); }
+  virtual int symbol_ids() { return symbol_id_; }
  private:
-  Collector<unsigned> store_;
+  Collector<unsigned> function_store_;
+  Collector<unsigned> symbol_store_;
+  Collector<Vector<const char> > symbol_entries_;
+  HashMap symbol_table_;
+  int symbol_id_;
+
+  static int vector_hash(Vector<const char> string) {
+    int hash = 0;
+    for (int i = 0; i < string.length(); i++) {
+      int c = string[i];
+      hash += c;
+      hash += (hash << 10);
+      hash ^= (hash >> 6);
+    }
+    return hash;
+  }
+
+  static bool vector_compare(void* a, void* b) {
+    Vector<const char>* string1 = reinterpret_cast<Vector<const char>* >(a);
+    Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(b);
+    int length = string1->length();
+    if (string2->length() != length) return false;
+    return memcmp(string1->start(), string2->start(), length) == 0;
+  }
+
   unsigned preamble_[ScriptDataImpl::kHeaderSize];
 #ifdef DEBUG
   int prev_start;
@@ -936,19 +1018,19 @@
 
 
 void ScriptDataImpl::SkipFunctionEntry(int start) {
-  ASSERT(index_ + FunctionEntry::kSize <= store_.length());
-  ASSERT(static_cast<int>(store_[index_]) == start);
-  index_ += FunctionEntry::kSize;
+  ASSERT(function_index_ + FunctionEntry::kSize <= store_.length());
+  ASSERT(static_cast<int>(store_[function_index_]) == start);
+  function_index_ += FunctionEntry::kSize;
 }
 
 
 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
   // The current pre-data entry must be a FunctionEntry with the given
   // start position.
-    if ((index_ + FunctionEntry::kSize <= store_.length())
-        && (static_cast<int>(store_[index_]) == start)) {
-    int index = index_;
-    index_ += FunctionEntry::kSize;
+  if ((function_index_ + FunctionEntry::kSize <= store_.length())
+      && (static_cast<int>(store_[function_index_]) == start)) {
+    int index = function_index_;
+    function_index_ += FunctionEntry::kSize;
     return FunctionEntry(store_.SubVector(index,
                                           index + FunctionEntry::kSize));
   }
@@ -956,33 +1038,79 @@
 }
 
 
-bool ScriptDataImpl::SanityCheck() {
-  if (store_.length() < static_cast<int>(ScriptDataImpl::kHeaderSize)) {
-    return false;
+int ScriptDataImpl::GetSymbolIdentifier(int start) {
+  int next = symbol_index_ + 2;
+  if (next <= store_.length()
+      && static_cast<int>(store_[symbol_index_]) == start) {
+    symbol_index_ = next;
+    return store_[next - 1];
   }
+  return symbol_id_++;
+}
+
+
+
+bool ScriptDataImpl::SanityCheck() {
+  // Check that the header data is valid and doesn't specify
+  // point to positions outside the store.
+  if (store_.length() < ScriptDataImpl::kHeaderSize) return false;
   if (magic() != ScriptDataImpl::kMagicNumber) return false;
   if (version() != ScriptDataImpl::kCurrentVersion) return false;
+  if (has_error()) {
+    // Extra sane sanity check for error message encoding.
+    if (store_.length() <= kHeaderSize + kMessageTextPos) return false;
+    if (Read(kMessageStartPos) > Read(kMessageEndPos)) return false;
+    unsigned arg_count = Read(kMessageArgCountPos);
+    int pos = kMessageTextPos;
+    for (unsigned int i = 0; i <= arg_count; i++) {
+      if (store_.length() <= kHeaderSize + pos) return false;
+      int length = static_cast<int>(Read(pos));
+      if (length < 0) return false;
+      pos += 1 + length;
+    }
+    if (store_.length() < kHeaderSize + pos) return false;
+    return true;
+  }
+  // Check that the space allocated for function entries is sane.
+  int functions_size =
+      static_cast<int>(store_[ScriptDataImpl::kFunctionsSizeOffset]);
+  if (functions_size < 0) return false;
+  if (functions_size % FunctionEntry::kSize != 0) return false;
+  // Check that the count of symbols is non-negative.
+  int symbol_count =
+      static_cast<int>(store_[ScriptDataImpl::kSymbolCountOffset]);
+  if (symbol_count < 0) return false;
+  // Check that the total size has room both function entries.
+  int minimum_size =
+      ScriptDataImpl::kHeaderSize + functions_size;
+  if (store_.length() < minimum_size) return false;
   return true;
 }
 
 
 ParserRecorder::ParserRecorder()
-  : store_(0) {
+  : function_store_(0),
+    symbol_store_(0),
+    symbol_entries_(0),
+    symbol_table_(vector_compare),
+    symbol_id_(0) {
 #ifdef DEBUG
   prev_start = -1;
 #endif
   preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
   preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
   preamble_[ScriptDataImpl::kHasErrorOffset] = false;
+  preamble_[ScriptDataImpl::kFunctionsSizeOffset] = 0;
+  preamble_[ScriptDataImpl::kSymbolCountOffset] = 0;
   preamble_[ScriptDataImpl::kSizeOffset] = 0;
-  ASSERT_EQ(4, ScriptDataImpl::kHeaderSize);
+  ASSERT_EQ(6, ScriptDataImpl::kHeaderSize);
 }
 
 
 void ParserRecorder::WriteString(Vector<const char> str) {
-  store_.Add(str.length());
+  function_store_.Add(str.length());
   for (int i = 0; i < str.length(); i++) {
-    store_.Add(str[i]);
+    function_store_.Add(str[i]);
   }
 }
 
@@ -1003,10 +1131,14 @@
                                 Vector<const char*> args) {
   if (has_error()) return;
   preamble_[ScriptDataImpl::kHasErrorOffset] = true;
-  store_.Reset();
-  store_.Add(loc.beg_pos);
-  store_.Add(loc.end_pos);
-  store_.Add(args.length());
+  function_store_.Reset();
+  STATIC_ASSERT(ScriptDataImpl::kMessageStartPos == 0);
+  function_store_.Add(loc.beg_pos);
+  STATIC_ASSERT(ScriptDataImpl::kMessageEndPos == 1);
+  function_store_.Add(loc.end_pos);
+  STATIC_ASSERT(ScriptDataImpl::kMessageArgCountPos == 2);
+  function_store_.Add(args.length());
+  STATIC_ASSERT(ScriptDataImpl::kMessageTextPos == 3);
   WriteString(CStrVector(message));
   for (int i = 0; i < args.length(); i++) {
     WriteString(CStrVector(args[i]));
@@ -1015,22 +1147,23 @@
 
 
 Scanner::Location ScriptDataImpl::MessageLocation() {
-  int beg_pos = Read(0);
-  int end_pos = Read(1);
+  int beg_pos = Read(kMessageStartPos);
+  int end_pos = Read(kMessageEndPos);
   return Scanner::Location(beg_pos, end_pos);
 }
 
 
 const char* ScriptDataImpl::BuildMessage() {
-  unsigned* start = ReadAddress(3);
+  unsigned* start = ReadAddress(kMessageTextPos);
   return ReadString(start, NULL);
 }
 
 
 Vector<const char*> ScriptDataImpl::BuildArgs() {
-  int arg_count = Read(2);
+  int arg_count = Read(kMessageArgCountPos);
   const char** array = NewArray<const char*>(arg_count);
-  int pos = ScriptDataImpl::kHeaderSize + Read(3);
+  // Position after the string starting at position 3.
+  int pos = kMessageTextPos + 1 + Read(kMessageTextPos);
   for (int i = 0; i < arg_count; i++) {
     int count = 0;
     array[i] = ReadString(ReadAddress(pos), &count);
@@ -1049,14 +1182,6 @@
   return &store_[ScriptDataImpl::kHeaderSize + position];
 }
 
-void ScriptDataImpl::FindStart(int position) {
-  // Only search forwards, and linearly for now.
-  while ((index_ < store_.length())
-      && (static_cast<int>(store_[index_])) < position) {
-    index_ += FunctionEntry::kSize;
-  }
-}
-
 
 FunctionEntry ParserRecorder::LogFunction(int start) {
 #ifdef DEBUG
@@ -1064,7 +1189,7 @@
   prev_start = start;
 #endif
   if (has_error()) return FunctionEntry();
-  FunctionEntry result(store_.AddBlock(FunctionEntry::kSize, 0));
+  FunctionEntry result(function_store_.AddBlock(FunctionEntry::kSize, 0));
   result.set_start_pos(start);
   return result;
 }
@@ -1074,8 +1199,14 @@
  public:
   AstBuildingParser(Handle<Script> script, bool allow_natives_syntax,
                     v8::Extension* extension, ScriptDataImpl* pre_data)
-      : Parser(script, allow_natives_syntax, extension, PARSE,
-               factory(), log(), pre_data) { }
+      : Parser(script,
+               allow_natives_syntax,
+               extension,
+               PARSE,
+               factory(),
+               log(),
+               pre_data),
+        factory_(pre_data ? pre_data->symbol_count() : 16) { }
   virtual void ReportMessageAt(Scanner::Location loc, const char* message,
                                Vector<const char*> args);
   virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
@@ -1442,6 +1573,21 @@
 }
 
 
+Handle<String> Parser::GetSymbol(bool* ok) {
+  if (pre_data() != NULL) {
+    int symbol_id =
+        pre_data()->GetSymbolIdentifier(scanner_.location().beg_pos);
+    if (symbol_id < 0) {
+      ReportInvalidPreparseData(Factory::empty_symbol(), ok);
+      return Handle<String>::null();
+    }
+    return factory()->LookupSymbol(symbol_id, scanner_.literal());
+  }
+  log()->LogSymbol(scanner_.location().beg_pos, scanner_.literal());
+  return factory()->LookupSymbol(-1, scanner_.literal());
+}
+
+
 void AstBuildingParser::ReportMessageAt(Scanner::Location source_location,
                                         const char* type,
                                         Vector<const char*> args) {
@@ -3419,9 +3565,7 @@
 
     case Token::STRING: {
       Consume(Token::STRING);
-      Handle<String> symbol =
-          factory()->LookupSymbol(scanner_.literal_string(),
-                                  scanner_.literal_length());
+      Handle<String> symbol = GetSymbol(CHECK_OK);
       result = NEW(Literal(symbol));
       if (fni_ != NULL) fni_->PushLiteralName(symbol);
       break;
@@ -3689,9 +3833,7 @@
   Token::Value next = Next();
   // TODO(820): Allow NUMBER and STRING as well (and handle array indices).
   if (next == Token::IDENTIFIER || Token::IsKeyword(next)) {
-    Handle<String> name =
-        factory()->LookupSymbol(scanner_.literal_string(),
-                                scanner_.literal_length());
+    Handle<String> name = GetSymbol(CHECK_OK);
     FunctionLiteral* value =
         ParseFunctionLiteral(name,
                              RelocInfo::kNoPosition,
@@ -3755,9 +3897,7 @@
       }
       case Token::STRING: {
         Consume(Token::STRING);
-        Handle<String> string =
-            factory()->LookupSymbol(scanner_.literal_string(),
-                                    scanner_.literal_length());
+        Handle<String> string = GetSymbol(CHECK_OK);
         if (fni_ != NULL) fni_->PushLiteralName(string);
         uint32_t index;
         if (!string.is_null() && string->AsArrayIndex(&index)) {
@@ -3777,9 +3917,7 @@
       default:
         if (Token::IsKeyword(next)) {
           Consume(next);
-          Handle<String> string =
-              factory()->LookupSymbol(scanner_.literal_string(),
-                                      scanner_.literal_length());
+          Handle<String> string = GetSymbol(CHECK_OK);
           key = NEW(Literal(string));
         } else {
           // Unexpected token.
@@ -3972,7 +4110,9 @@
       }
       Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
       scanner_.SeekForward(end_pos);
-      pre_data()->Skip(entry.predata_skip());
+      pre_data()->Skip(entry.predata_function_skip(),
+                       entry.predata_symbol_skip(),
+                       entry.symbol_id_skip());
       materialized_literal_count = entry.literal_count();
       expected_property_count = entry.property_count();
       only_simple_this_property_assignments = false;
@@ -3984,7 +4124,9 @@
         pre_data()->SkipFunctionEntry(function_block_pos);
       }
       FunctionEntry entry = log()->LogFunction(function_block_pos);
-      int predata_position_before = log()->position();
+      int predata_function_position_before = log()->function_position();
+      int predata_symbol_position_before = log()->symbol_position();
+      int symbol_ids_before = log()->symbol_ids();
       ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
       materialized_literal_count = temp_scope.materialized_literal_count();
       expected_property_count = temp_scope.expected_property_count();
@@ -3998,7 +4140,12 @@
         entry.set_end_pos(end_pos);
         entry.set_literal_count(materialized_literal_count);
         entry.set_property_count(expected_property_count);
-        entry.set_predata_skip(log()->position() - predata_position_before);
+        entry.set_predata_function_skip(
+            log()->function_position() - predata_function_position_before);
+        entry.set_predata_symbol_skip(
+            log()->symbol_position() - predata_symbol_position_before);
+        entry.set_symbol_id_skip(
+            log()->symbol_ids() - symbol_ids_before);
       }
     }
 
@@ -4148,8 +4295,7 @@
 Handle<String> Parser::ParseIdentifier(bool* ok) {
   Expect(Token::IDENTIFIER, ok);
   if (!*ok) return Handle<String>();
-  return factory()->LookupSymbol(scanner_.literal_string(),
-                                 scanner_.literal_length());
+  return GetSymbol(ok);
 }
 
 
@@ -4160,8 +4306,7 @@
     *ok = false;
     return Handle<String>();
   }
-  return factory()->LookupSymbol(scanner_.literal_string(),
-                                 scanner_.literal_length());
+  return GetSymbol(ok);
 }
 
 
@@ -4179,8 +4324,7 @@
     *is_get = strcmp(token, "get") == 0;
     *is_set = !*is_get && strcmp(token, "set") == 0;
   }
-  return factory()->LookupSymbol(scanner_.literal_string(),
-                                 scanner_.literal_length());
+  return GetSymbol(ok);
 }
 
 
@@ -4362,8 +4506,7 @@
   if (peek() != Token::RBRACE) {
     do {
       Expect(Token::STRING, CHECK_OK);
-      Handle<String> key = factory()->LookupSymbol(scanner_.literal_string(),
-                                                   scanner_.literal_length());
+      Handle<String> key = GetSymbol(CHECK_OK);
       Expect(Token::COLON, CHECK_OK);
       Expression* value = ParseJsonValue(CHECK_OK);
       Literal* key_literal;
@@ -5251,7 +5394,7 @@
 
 
 ScriptDataImpl::~ScriptDataImpl() {
-  store_.Dispose();
+  if (owns_store_) store_.Dispose();
 }
 
 
diff --git a/src/parser.h b/src/parser.h
index 2952581..56412a0 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -72,14 +72,25 @@
     backing_[kPropertyCountOffset] = value;
   }
 
-  int predata_skip() { return backing_[kPredataSkipOffset]; }
-  void set_predata_skip(int value) {
-    backing_[kPredataSkipOffset] = value;
+  int predata_function_skip() { return backing_[kPredataFunctionSkipOffset]; }
+  void set_predata_function_skip(int value) {
+    backing_[kPredataFunctionSkipOffset] = value;
   }
 
+  int predata_symbol_skip() { return backing_[kPredataSymbolSkipOffset]; }
+  void set_predata_symbol_skip(int value) {
+    backing_[kPredataSymbolSkipOffset] = value;
+  }
+
+  int symbol_id_skip() { return backing_[kSymbolIdSkipOffset]; }
+  void set_symbol_id_skip(int value) {
+    backing_[kSymbolIdSkipOffset] = value;
+  }
+
+
   bool is_valid() { return backing_.length() > 0; }
 
-  static const int kSize = 5;
+  static const int kSize = 7;
 
  private:
   Vector<unsigned> backing_;
@@ -87,7 +98,9 @@
   static const int kEndPosOffset = 1;
   static const int kLiteralCountOffset = 2;
   static const int kPropertyCountOffset = 3;
-  static const int kPredataSkipOffset = 4;
+  static const int kPredataFunctionSkipOffset = 4;
+  static const int kPredataSymbolSkipOffset = 5;
+  static const int kSymbolIdSkipOffset = 6;
 };
 
 
@@ -95,12 +108,30 @@
  public:
   explicit ScriptDataImpl(Vector<unsigned> store)
       : store_(store),
-        index_(kHeaderSize) { }
+        function_index_(kHeaderSize),
+        symbol_id_(0),
+        owns_store_(true) {
+    Initialize();
+  }
+
+  void Initialize() {
+    if (store_.length() >= kHeaderSize) {
+      // Otherwise we won't satisfy the SanityCheck.
+      symbol_index_ = kHeaderSize + store_[kFunctionsSizeOffset];
+    }
+  }
+
+  // Create an empty ScriptDataImpl that is guaranteed to not satisfy
+  // a SanityCheck.
+  ScriptDataImpl() : store_(Vector<unsigned>()), owns_store_(false) { }
+
   virtual ~ScriptDataImpl();
   virtual int Length();
   virtual const char* Data();
   virtual bool HasError();
+
   FunctionEntry GetFunctionEntry(int start);
+  int GetSymbolIdentifier(int start);
   void SkipFunctionEntry(int start);
   bool SanityCheck();
 
@@ -108,36 +139,67 @@
   const char* BuildMessage();
   Vector<const char*> BuildArgs();
 
+  int symbol_count() {
+    return (store_.length() > kHeaderSize) ? store_[kSymbolCountOffset] : 0;
+  }
+  // The following functions should only be called if SanityCheck has
+  // returned true.
   bool has_error() { return store_[kHasErrorOffset]; }
   unsigned magic() { return store_[kMagicOffset]; }
   unsigned version() { return store_[kVersionOffset]; }
+
   // Skip forward in the preparser data by the given number
   // of unsigned ints.
-  virtual void Skip(int entries) {
-    ASSERT(entries >= 0);
-    ASSERT(entries <= store_.length() - index_);
-    index_ += entries;
+  virtual void Skip(int function_entries, int symbol_entries, int symbol_ids) {
+    ASSERT(function_entries >= 0);
+    ASSERT(function_entries
+           <= (static_cast<int>(store_[kFunctionsSizeOffset])
+               - (function_index_ - kHeaderSize)));
+    function_index_ += function_entries;
+    symbol_index_ += symbol_entries;
+    symbol_id_ += symbol_ids;
   }
 
   static const unsigned kMagicNumber = 0xBadDead;
-  static const unsigned kCurrentVersion = 1;
+  static const unsigned kCurrentVersion = 2;
 
   static const int kMagicOffset = 0;
   static const int kVersionOffset = 1;
   static const int kHasErrorOffset = 2;
-  static const int kSizeOffset = 3;
-  static const int kHeaderSize = 4;
+  static const int kFunctionsSizeOffset = 3;
+  static const int kSymbolCountOffset = 4;
+  static const int kSizeOffset = 5;
+  static const int kHeaderSize = 6;
+
+  static const int kMessageStartPos = 0;
+  static const int kMessageEndPos = 1;
+  static const int kMessageArgCountPos = 2;
+  static const int kMessageTextPos = 3;
 
  private:
   Vector<unsigned> store_;
-  int index_;
+  int function_index_;
+  int symbol_index_;
+  int symbol_id_;
+  bool owns_store_;
 
   unsigned Read(int position);
   unsigned* ReadAddress(int position);
 
-  void FindStart(int position);
+  ScriptDataImpl(const char* backing_store, int length)
+      : store_(reinterpret_cast<unsigned*>(const_cast<char*>(backing_store)),
+               length / sizeof(unsigned)),
+        function_index_(kHeaderSize),
+        symbol_id_(0),
+        owns_store_(false) {
+    ASSERT_EQ(0, reinterpret_cast<intptr_t>(backing_store) % sizeof(unsigned));
+    Initialize();
+  }
+
   // Read strings written by ParserRecorder::WriteString.
   static const char* ReadString(unsigned* start, int* chars);
+
+  friend class ScriptData;
 };
 
 
diff --git a/src/runtime.cc b/src/runtime.cc
index c7ec6bf..43a6734 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -4677,9 +4677,8 @@
                  (len == 1 || data[0] != '0')) {
         // String hash is not calculated yet but all the data are present.
         // Update the hash field to speed up sequential convertions.
-        uint32_t hash = StringHasher::MakeCachedArrayIndex(d, len);
+        uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
 #ifdef DEBUG
-        ASSERT((hash & String::kContainsCachedArrayIndexMask) == 0);
         subject->Hash();  // Force hash calculation.
         ASSERT_EQ(static_cast<int>(subject->hash_field()),
                   static_cast<int>(hash));
diff --git a/src/v8-counters.h b/src/v8-counters.h
index af657f1..8c948cc 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -98,6 +98,8 @@
   SC(total_parse_size, V8.TotalParseSize)                             \
   /* Amount of source code skipped over using preparsing. */          \
   SC(total_preparse_skipped, V8.TotalPreparseSkipped)                 \
+  /* Number of symbol lookups skipped using preparsing */             \
+  SC(total_preparse_symbols_skipped, V8.TotalPreparseSymbolSkipped)   \
   /* Amount of compiled source code. */                               \
   SC(total_compile_size, V8.TotalCompileSize)                         \
   /* Amount of source code compiled with the old codegen. */          \
diff --git a/src/version.cc b/src/version.cc
index 3ba41b7..0af1795 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     4
-#define BUILD_NUMBER      1
+#define BUILD_NUMBER      2
 #define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 4b6fa9c..2b50db7 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -37,6 +37,7 @@
 #include "top.h"
 #include "utils.h"
 #include "cctest.h"
+#include "parser.h"
 
 static const bool kLogThreading = true;
 
@@ -3605,6 +3606,29 @@
 }
 
 
+static const char* kNativeCallInExtensionSource =
+    "function call_runtime_last_index_of(x) {"
+    "  return %StringLastIndexOf(x, 'bob', 10);"
+    "}";
+
+
+static const char* kNativeCallTest =
+    "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
+
+// Test that a native runtime calls are supported in extensions.
+THREADED_TEST(NativeCallInExtensions) {
+  v8::HandleScope handle_scope;
+  v8::RegisterExtension(new Extension("nativecall",
+                                      kNativeCallInExtensionSource));
+  const char* extension_names[] = { "nativecall" };
+  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::Handle<Context> context = Context::New(&extensions);
+  Context::Scope lock(context);
+  v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
+  CHECK_EQ(result, v8::Integer::New(3));
+}
+
+
 static void CheckDependencies(const char* name, const char* expected) {
   v8::HandleScope handle_scope;
   v8::ExtensionConfiguration config(1, &name);
@@ -8601,15 +8625,12 @@
       v8::ScriptData::PreCompile(script, i::StrLength(script));
   CHECK(!sd->HasError());
   // ScriptDataImpl private implementation details
-  const int kUnsignedSize = sizeof(unsigned);
-  const int kHeaderSize = 4;
-  const int kFunctionEntrySize = 5;
+  const int kHeaderSize = i::ScriptDataImpl::kHeaderSize;
+  const int kFunctionEntrySize = i::FunctionEntry::kSize;
   const int kFunctionEntryStartOffset = 0;
   const int kFunctionEntryEndOffset = 1;
   unsigned* sd_data =
       reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
-  CHECK_EQ(sd->Length(),
-           (kHeaderSize + 2 * kFunctionEntrySize) * kUnsignedSize);
 
   // Overwrite function bar's end position with 0.
   sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index fee6624..7c669d3 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -91,7 +91,7 @@
   Label L, C;
 
   __ mov(r1, Operand(r0));
-  __ mov(r0, Operand(0));
+  __ mov(r0, Operand(0, RelocInfo::NONE));
   __ b(&C);
 
   __ bind(&L);
@@ -99,7 +99,7 @@
   __ sub(r1, r1, Operand(1));
 
   __ bind(&C);
-  __ teq(r1, Operand(0));
+  __ teq(r1, Operand(0, RelocInfo::NONE));
   __ b(ne, &L);
   __ mov(pc, Operand(lr));
 
@@ -135,7 +135,7 @@
   __ sub(r1, r1, Operand(1));
 
   __ bind(&C);
-  __ teq(r1, Operand(0));
+  __ teq(r1, Operand(0, RelocInfo::NONE));
   __ b(ne, &L);
   __ mov(pc, Operand(lr));
 
diff --git a/test/cctest/test-assembler-mips.cc b/test/cctest/test-assembler-mips.cc
index 0a2310e..955562b 100644
--- a/test/cctest/test-assembler-mips.cc
+++ b/test/cctest/test-assembler-mips.cc
@@ -109,7 +109,7 @@
 
   __ bind(&C);
   __ xori(v1, a1, 0);
-  __ Branch(ne, &L, v1, Operand(0));
+  __ Branch(ne, &L, v1, Operand(0, RelocInfo::NONE));
   __ nop();
 
   __ jr(ra);
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 9531b57..f5526ce 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -4591,6 +4591,18 @@
 }
 
 
+// We match parts of the message to get source line.
+int GetSourceLineFromBreakEventMessage(char *message) {
+  const char* source_line = "\"sourceLine\":";
+  char* pos = strstr(message, source_line);
+  if (pos == NULL) {
+    return -1;
+  }
+  int res = -1;
+  res = StringToInt(pos + strlen(source_line));
+  return res;
+}
+
 /* Test MessageQueues */
 /* Tests the message queues that hold debugger commands and
  * response messages to the debugger.  Fills queues and makes
@@ -4870,6 +4882,9 @@
   v8::String::Value json(message.GetJSON());
   Utf16ToAscii(*json, json.length(), print_buffer);
   if (IsBreakEventMessage(print_buffer)) {
+    // Check that we are inside the while loop.
+    int source_line = GetSourceLineFromBreakEventMessage(print_buffer);
+    CHECK(8 <= source_line && source_line <= 13);
     threaded_debugging_barriers.barrier_2.Wait();
   }
 }
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index ed0c8b5..5ddd044 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -31,6 +31,7 @@
 
 #include "token.h"
 #include "scanner.h"
+#include "parser.h"
 #include "utils.h"
 #include "execution.h"
 
@@ -148,7 +149,7 @@
       NULL
   };
 
-  // Parser needs a stack limit.
+  // Parser/Scanner needs a stack limit.
   int marker;
   i::StackGuard::SetStackLimit(
       reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
@@ -160,3 +161,81 @@
     delete data;
   }
 }
+
+
+class ScriptResource : public v8::String::ExternalAsciiStringResource {
+ public:
+  ScriptResource(const char* data, size_t length)
+      : data_(data), length_(length) { }
+
+  const char* data() const { return data_; }
+  size_t length() const { return length_; }
+
+ private:
+  const char* data_;
+  size_t length_;
+};
+
+
+TEST(Preparsing) {
+  v8::HandleScope handles;
+  v8::Persistent<v8::Context> context = v8::Context::New();
+  v8::Context::Scope context_scope(context);
+  int marker;
+  i::StackGuard::SetStackLimit(
+      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+
+  // Source containing functions that might be lazily compiled  and all types
+  // of symbols (string, propertyName, regexp).
+  const char* source =
+      "var x = 42;"
+      "function foo(a) { return function nolazy(b) { return a + b; } }"
+      "function bar(a) { if (a) return function lazy(b) { return b; } }"
+      "var z = {'string': 'string literal', bareword: 'propertyName', "
+      "         42: 'number literal', for: 'keyword as propertyName', "
+      "         f\\u006fr: 'keyword propertyname with escape'};"
+      "var v = /RegExp Literal/;"
+      "var w = /RegExp Literal\\u0020With Escape/gin;"
+      "var y = { get getter() { return 42; }, "
+      "          set setter(v) { this.value = v; }};";
+  int source_length = strlen(source);
+  const char* error_source = "var x = y z;";
+  int error_source_length = strlen(error_source);
+
+  v8::ScriptData* preparse =
+      v8::ScriptData::PreCompile(source, source_length);
+  CHECK(!preparse->HasError());
+  bool lazy_flag = i::FLAG_lazy;
+  {
+    i::FLAG_lazy = true;
+    ScriptResource* resource = new ScriptResource(source, source_length);
+    v8::Local<v8::String> script_source = v8::String::NewExternal(resource);
+    v8::Script::Compile(script_source, NULL, preparse);
+  }
+
+  {
+    i::FLAG_lazy = false;
+
+    ScriptResource* resource = new ScriptResource(source, source_length);
+    v8::Local<v8::String> script_source = v8::String::NewExternal(resource);
+    v8::Script::New(script_source, NULL, preparse, v8::Local<v8::String>());
+  }
+  delete preparse;
+  i::FLAG_lazy = lazy_flag;
+
+  // Syntax error.
+  v8::ScriptData* error_preparse =
+      v8::ScriptData::PreCompile(error_source, error_source_length);
+  CHECK(error_preparse->HasError());
+  i::ScriptDataImpl *pre_impl =
+      reinterpret_cast<i::ScriptDataImpl*>(error_preparse);
+  i::Scanner::Location error_location =
+      pre_impl->MessageLocation();
+  // Error is at "z" in source, location 10..11.
+  CHECK_EQ(10, error_location.beg_pos);
+  CHECK_EQ(11, error_location.end_pos);
+  // Should not crash.
+  const char* message = pre_impl->BuildMessage();
+  i::Vector<const char*> args = pre_impl->BuildArgs();
+  CHECK_GT(strlen(message), 0);
+}
diff --git a/test/mjsunit/regress/regress-push-args-twice.js b/test/mjsunit/regress/regress-push-args-twice.js
new file mode 100644
index 0000000..faa6007
--- /dev/null
+++ b/test/mjsunit/regress/regress-push-args-twice.js
@@ -0,0 +1,37 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Check that the ADD binary op stub correctly handles non-number arguments
+// passed on registers.
+
+try {
+  for (var key = 0; key != 10; key++) {
+    var x = 1 + undefined;
+  }
+} catch(e) {
+  fail("no exception", e);
+}
diff --git a/test/mjsunit/str-to-num.js b/test/mjsunit/str-to-num.js
index 20e2986..28e98d9 100644
--- a/test/mjsunit/str-to-num.js
+++ b/test/mjsunit/str-to-num.js
@@ -203,3 +203,7 @@
 assertTrue(isNaN(toNumber("1e")), "1e");
 assertTrue(isNaN(toNumber("1e ")), "1e_");
 assertTrue(isNaN(toNumber("1" + repeat('0', 1000) + 'junk')), "1e1000 junk");
+
+for (var i = 1; i < 12; i++) {
+  assertEquals(toNumber('1' + repeat('0', i)), Math.pow(10.0, i));
+}