Push version 2.5.9 to trunk.

Fixed crashes during GC caused by partially initialize heap objects.

Fixed bug in process sample that caused memory leaks.

Improved performance on ARM by implementing missing stubs and inlining.

Improved heap profiler support.

Added separate seeding on Windows of the random number generator used internally by the compiler (issue 936).

Exposed API for getting the name of the function used to construct an object.

Fixed date parser to handle one and two digit millisecond values (issue 944).

Fixed number parsing to disallow space between sign and digits (issue 946).


git-svn-id: http://v8.googlecode.com/svn/trunk@5896 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/AUTHORS b/AUTHORS
index 68f9b63..3749ceb 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,7 +9,6 @@
 Hewlett-Packard Development Company, LP
 
 Alexander Botero-Lowry <alexbl@FreeBSD.org>
-Alexandre Rames <alexandre.rames@arm.com>
 Alexandre Vassalotti <avassalotti@gmail.com>
 Andreas Anyuru <andreas.anyuru@gmail.com>
 Burcu Dogan <burcujdogan@gmail.com>
diff --git a/ChangeLog b/ChangeLog
index 9f2005f..86e41e1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2010-11-29: Version 2.5.9
+
+        Fixed crashes during GC caused by partially initialize heap
+        objects.
+
+        Fixed bug in process sample that caused memory leaks.
+
+        Improved performance on ARM by implementing missing stubs and
+        inlining.
+
+        Improved heap profiler support.
+
+        Added separate seeding on Windows of the random number generator
+        used internally by the compiler (issue 936).
+
+        Exposed API for getting the name of the function used to construct
+        an object.
+
+        Fixed date parser to handle one and two digit millisecond
+        values (issue 944).
+
+        Fixed number parsing to disallow space between sign and
+        digits (issue 946).
+
+
 2010-11-23: Version 2.5.8
 
         Removed dependency on Gay's dtoa.
diff --git a/include/v8.h b/include/v8.h
index 9baa17d..8ecf63a 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1539,6 +1539,11 @@
    */
   V8EXPORT Local<String> ObjectProtoToString();
 
+  /**
+   * Returns the name of the function invoked as a constructor for this object.
+   */
+  V8EXPORT Local<String> GetConstructorName();
+
   /** Gets the number of internal fields for this Object. */
   V8EXPORT int InternalFieldCount();
   /** Gets the value in an internal field. */
diff --git a/preparser/preparser-process.cc b/preparser/preparser-process.cc
new file mode 100644
index 0000000..706a225
--- /dev/null
+++ b/preparser/preparser-process.cc
@@ -0,0 +1,227 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdarg.h>
+#include "../include/v8stdint.h"
+#include "globals.h"
+#include "checks.h"
+#include "allocation.h"
+#include "utils.h"
+#include "list.h"
+#include "smart-pointer.h"
+#include "scanner-base.h"
+#include "preparse-data.h"
+#include "preparser.h"
+
+enum ResultCode { kSuccess = 0, kErrorReading = 1, kErrorWriting = 2 };
+
+namespace v8 {
+namespace internal {
+
+// THIS FILE IS PROOF-OF-CONCEPT ONLY.
+// The final goal is a stand-alone preparser library.
+
+// UTF16Buffer based on an UTF-8 string in memory.
+class UTF8UTF16Buffer : public UTF16Buffer {
+ public:
+  UTF8UTF16Buffer(uint8_t* buffer, size_t length)
+      : UTF16Buffer(),
+        buffer_(buffer),
+        offset_(0),
+        end_offset_(static_cast<int>(length)) { }
+
+  virtual void PushBack(uc32 ch) {
+    // Pushback assumes that the character pushed back is the
+    // one that was most recently read, and jumps back in the
+    // UTF-8 stream by the length of that character's encoding.
+    offset_ -= unibrow::Utf8::Length(ch);
+    pos_--;
+#ifdef DEBUG
+    int tmp = 0;
+    ASSERT_EQ(ch, unibrow::Utf8::ValueOf(buffer_ + offset_,
+                                         end_offset_ - offset_,
+                                         &tmp);
+#endif
+  }
+
+  virtual uc32 Advance() {
+    if (offset_ == end_offset_) return -1;
+    uint8_t first_char = buffer_[offset_];
+    if (first_char <= unibrow::Utf8::kMaxOneByteChar) {
+      pos_++;
+      offset_++;
+      return static_cast<uc32>(first_char);
+    }
+    unibrow::uchar codepoint =
+        unibrow::Utf8::CalculateValue(buffer_ + offset_,
+                                      end_offset_ - offset_,
+                                      &offset_);
+    pos_++;
+    return static_cast<uc32>(codepoint);
+  }
+
+  virtual void SeekForward(int pos) {
+    while (pos_ < pos) {
+      uint8_t first_byte = buffer_[offset_++];
+      while (first_byte & 0x80u && offset_ < end_offset_) {
+        offset_++;
+        first_byte <<= 1;
+      }
+      pos_++;
+    }
+  }
+
+ private:
+  const uint8_t* buffer_;
+  unsigned offset_;
+  unsigned end_offset_;
+};
+
+
+class StandAloneJavaScriptScanner : public JavaScriptScanner {
+ public:
+  void Initialize(UTF16Buffer* source) {
+    source_ = source;
+    literal_flags_ = kLiteralString | kLiteralIdentifier;
+    Init();
+    // Skip initial whitespace allowing HTML comment ends just like
+    // after a newline and scan first token.
+    has_line_terminator_before_next_ = true;
+    SkipWhiteSpace();
+    Scan();
+  }
+};
+
+
+// Write a number to dest in network byte order.
+void WriteUInt32(FILE* dest, uint32_t value, bool* ok) {
+  for (int i = 3; i >= 0; i--) {
+    uint8_t byte = static_cast<uint8_t>(value >> (i << 3));
+    int result = fputc(byte, dest);
+    if (result == EOF) {
+      *ok = false;
+      return;
+    }
+  }
+}
+
+// Read number from FILE* in network byte order.
+uint32_t ReadUInt32(FILE* source, bool* ok) {
+  uint32_t n = 0;
+  for (int i = 0; i < 4; i++) {
+    int c = fgetc(source);
+    if (c == EOF) {
+      *ok = false;
+      return 0;
+    }
+    n = (n << 8) + static_cast<uint32_t>(c);
+  }
+  return n;
+}
+
+
+bool ReadBuffer(FILE* source, void* buffer, size_t length) {
+  size_t actually_read = fread(buffer, 1, length, stdin);
+  return (actually_read == length);
+}
+
+
+bool WriteBuffer(FILE* dest, void* buffer, size_t length) {
+  size_t actually_written = fwrite(buffer, 1, length, dest);
+  return (actually_written == length);
+}
+
+// Preparse stdin and output result on stdout.
+int PreParseIO() {
+  fprintf(stderr, "LOG: Enter parsing loop\n");
+  bool ok = true;
+  uint32_t length = ReadUInt32(stdin, &ok);
+  if (!ok) return kErrorReading;
+  SmartPointer<byte> buffer(NewArray<byte>(length));
+  if (!ReadBuffer(stdin, *buffer, length)) {
+    return kErrorReading;
+  }
+  UTF8UTF16Buffer input_buffer(*buffer, static_cast<size_t>(length));
+  StandAloneJavaScriptScanner scanner;
+  scanner.Initialize(&input_buffer);
+  CompleteParserRecorder recorder;
+  preparser::PreParser preparser;
+
+  if (!preparser.PreParseProgram(&scanner, &recorder, true)) {
+    if (scanner.stack_overflow()) {
+      // Report stack overflow error/no-preparser-data.
+      WriteUInt32(stdout, 0, &ok);
+      if (!ok) return kErrorWriting;
+      return 0;
+    }
+  }
+  Vector<unsigned> pre_data = recorder.ExtractData();
+
+  uint32_t size = static_cast<uint32_t>(pre_data.length() * sizeof(uint32_t));
+  WriteUInt32(stdout, size, &ok);
+  if (!ok) return kErrorWriting;
+  if (!WriteBuffer(stdout,
+                   reinterpret_cast<byte*>(pre_data.start()),
+                   size)) {
+    return kErrorWriting;
+  }
+  return 0;
+}
+
+// Functions declared by allocation.h
+
+void FatalProcessOutOfMemory(const char* location) {
+  V8_Fatal("", 0, location);
+}
+
+bool EnableSlowAsserts() { return true; }
+
+} }  // namespace v8::internal
+
+
+int main(int argc, char* argv[]) {
+  int status = 0;
+  do {
+    status = v8::internal::PreParseIO();
+  } while (status == 0);
+  fprintf(stderr, "EXIT: Failure %d\n", status);
+  return EXIT_FAILURE;
+}
+
+
+// Fatal error handling declared by checks.h.
+
+extern "C" void V8_Fatal(const char* file, int line, const char* format, ...) {
+  fflush(stdout);
+  fflush(stderr);
+  va_list arguments;
+  va_start(arguments, format);
+  vfprintf(stderr, format, arguments);
+  va_end(arguments);
+  fputs("\n#\n\n", stderr);
+  exit(EXIT_FAILURE);
+}
diff --git a/samples/process.cc b/samples/process.cc
index 9233c0d..6be4ea5 100644
--- a/samples/process.cc
+++ b/samples/process.cc
@@ -152,18 +152,16 @@
   Handle<ObjectTemplate> global = ObjectTemplate::New();
   global->Set(String::New("log"), FunctionTemplate::New(LogCallback));
 
-  // Each processor gets its own context so different processors
-  // don't affect each other (ignore the first three lines).
-  Handle<Context> context = Context::New(NULL, global);
-
-  // Store the context in the processor object in a persistent handle,
-  // since we want the reference to remain after we return from this
-  // method.
-  context_ = Persistent<Context>::New(context);
+  // Each processor gets its own context so different processors don't
+  // affect each other. Context::New returns a persistent handle which
+  // is what we need for the reference to remain after we return from
+  // this method. That persistent handle has to be disposed in the
+  // destructor.
+  context_ = Context::New(NULL, global);
 
   // Enter the new context so all the following operations take place
   // within it.
-  Context::Scope context_scope(context);
+  Context::Scope context_scope(context_);
 
   // Make the options mapping available within the context
   if (!InstallMaps(opts, output))
@@ -176,7 +174,7 @@
   // The script compiled and ran correctly.  Now we fetch out the
   // Process function from the global object.
   Handle<String> process_name = String::New("Process");
-  Handle<Value> process_val = context->Global()->Get(process_name);
+  Handle<Value> process_val = context_->Global()->Get(process_name);
 
   // If there is no Process function, or if it is not a function,
   // bail out
diff --git a/samples/shell.cc b/samples/shell.cc
index 2bdc5a1..1a13f5f 100644
--- a/samples/shell.cc
+++ b/samples/shell.cc
@@ -37,7 +37,6 @@
                    v8::Handle<v8::Value> name,
                    bool print_result,
                    bool report_exceptions);
-v8::Handle<v8::Value> PrintToInteger(const v8::Arguments& args);
 v8::Handle<v8::Value> Print(const v8::Arguments& args);
 v8::Handle<v8::Value> Read(const v8::Arguments& args);
 v8::Handle<v8::Value> Load(const v8::Arguments& args);
@@ -54,8 +53,7 @@
   v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
   // Bind the global 'print' function to the C++ Print callback.
   global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
-global->Set(v8::String::New("print2int"), v8::FunctionTemplate::New(PrintToInteger));
-// Bind the global 'read' function to the C++ Read callback.
+  // Bind the global 'read' function to the C++ Read callback.
   global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read));
   // Bind the global 'load' function to the C++ Load callback.
   global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
@@ -140,16 +138,6 @@
 }
 
 
-v8::Handle<v8::Value> PrintToInteger(const v8::Arguments& args) {
-  v8::HandleScope handle_scope;
-  v8::String::Utf8Value str(args[0]);
-  const char* cstr = ToCString(str);
-  printf("%s -> %d\n", cstr, args[0]->ToInt32()->Value());
-  fflush(stdout);
-  return v8::Undefined();
-}
-
-
 // The callback that is invoked by v8 whenever the JavaScript 'read'
 // function is called.  This function loads the content of the file named in
 // the argument into a JavaScript string.
diff --git a/src/SConscript b/src/SConscript
index a83f4d5..8953698 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -89,6 +89,8 @@
     objects-visiting.cc
     oprofile-agent.cc
     parser.cc
+    preparser.cc
+    preparse-data.cc
     profile-generator.cc
     property.cc
     regexp-macro-assembler-irregexp.cc
diff --git a/src/api.cc b/src/api.cc
index b46cd02..19af866 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2451,6 +2451,15 @@
 }
 
 
+Local<String> v8::Object::GetConstructorName() {
+  ON_BAILOUT("v8::Object::GetConstructorName()", return Local<v8::String>());
+  ENTER_V8;
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  i::Handle<i::String> name(self->constructor_name());
+  return Utils::ToLocal(name);
+}
+
+
 bool v8::Object::Delete(v8::Handle<String> key) {
   ON_BAILOUT("v8::Object::Delete()", return false);
   ENTER_V8;
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index f72ad76..15720c9 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -164,7 +164,7 @@
 
 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
   Instr current_instr = Assembler::instr_at(pc_);
-  return !Assembler::IsNop(current_instr, 2);
+  return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
 }
 
 
@@ -288,9 +288,7 @@
   }
 #endif
 
-  // Verify that the instruction to patch is a
-  // ldr<cond> <Rd>, [pc +/- offset_12].
-  ASSERT((instr & 0x0f7f0000) == 0x051f0000);
+  ASSERT(IsLdrPcImmediateOffset(instr));
   int offset = instr & 0xfff;  // offset_12 is unsigned
   if ((instr & (1 << 23)) == 0) offset = -offset;  // U bit defines offset sign
   // Verify that the constant pool comes after the instruction referencing it.
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 4cb421c..cfdd164 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -397,13 +397,6 @@
 }
 
 
-bool Assembler::IsNop(Instr instr, int type) {
-  // Check for mov rx, rx.
-  ASSERT(0 <= type && type <= 14);  // mov pc, pc is not a nop.
-  return instr == (al | 13*B21 | type*B12 | type);
-}
-
-
 bool Assembler::IsBranch(Instr instr) {
   return (instr & (B27 | B25)) == (B27 | B25);
 }
@@ -510,6 +503,13 @@
 }
 
 
+bool Assembler::IsLdrPcImmediateOffset(Instr instr) {
+  // Check the instruction is indeed a
+  // ldr<cond> <Rd>, [pc +/- offset_12].
+  return (instr & 0x0f7f0000) == 0x051f0000;
+}
+
+
 // Labels refer to positions in the (to be) generated code.
 // There are bound, linked, and unused labels.
 //
@@ -1113,8 +1113,8 @@
     positions_recorder()->WriteRecordedPositions();
   }
   // Don't allow nop instructions in the form mov rn, rn to be generated using
-  // the mov instruction. They must be generated using nop(int)
-  // pseudo instructions.
+  // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
+  // or MarkCode(int/NopMarkerTypes) pseudo instructions.
   ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
   addrmod1(cond | 13*B21 | s, r0, dst, src);
 }
@@ -2376,6 +2376,13 @@
 }
 
 
+bool Assembler::IsNop(Instr instr, int type) {
+  // Check for mov rx, rx.
+  ASSERT(0 <= type && type <= 14);  // mov pc, pc is not a nop.
+  return instr == (al | 13*B21 | type*B12 | type);
+}
+
+
 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
   uint32_t dummy1;
   uint32_t dummy2;
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 606ff86..ee4c9aa 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -1079,7 +1079,22 @@
              const Condition cond = al);
 
   // Pseudo instructions
-  void nop(int type = 0);
+
+  // Different nop operations are used by the code generator to detect certain
+  // states of the generated code.
+  enum NopMarkerTypes {
+    NON_MARKING_NOP = 0,
+    DEBUG_BREAK_NOP,
+    // IC markers.
+    PROPERTY_ACCESS_INLINED,
+    PROPERTY_ACCESS_INLINED_CONTEXT,
+    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
+    // Helper values.
+    LAST_CODE_MARKER,
+    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
+  };
+
+  void nop(int type = 0);   // 0 is the default non-marking type.
 
   void push(Register src, Condition cond = al) {
     str(src, MemOperand(sp, 4, NegPreIndex), cond);
@@ -1151,7 +1166,6 @@
   static void instr_at_put(byte* pc, Instr instr) {
     *reinterpret_cast<Instr*>(pc) = instr;
   }
-  static bool IsNop(Instr instr, int type = 0);
   static bool IsBranch(Instr instr);
   static int GetBranchOffset(Instr instr);
   static bool IsLdrRegisterImmediate(Instr instr);
@@ -1168,6 +1182,8 @@
   static bool IsLdrRegFpOffset(Instr instr);
   static bool IsStrRegFpNegOffset(Instr instr);
   static bool IsLdrRegFpNegOffset(Instr instr);
+  static bool IsLdrPcImmediateOffset(Instr instr);
+  static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
 
 
  protected:
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index cf2f426..862ef39 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -482,9 +482,128 @@
 
 
 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
-  // TODO(849): implement custom construct stub.
-  // Generate a copy of the generic stub for now.
-  Generate_JSConstructStubGeneric(masm);
+  // ----------- S t a t e -------------
+  //  -- r0                     : number of arguments
+  //  -- r1                     : constructor function
+  //  -- lr                     : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+  __ IncrementCounter(&Counters::string_ctor_calls, 1, r2, r3);
+
+  Register function = r1;
+  if (FLAG_debug_code) {
+    __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2);
+    __ cmp(function, Operand(r2));
+    __ Assert(eq, "Unexpected String function");
+  }
+
+  // Load the first arguments in r0 and get rid of the rest.
+  Label no_arguments;
+  __ cmp(r0, Operand(0));
+  __ b(eq, &no_arguments);
+  // First args = sp[(argc - 1) * 4].
+  __ sub(r0, r0, Operand(1));
+  __ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
+  // sp now point to args[0], drop args[0] + receiver.
+  __ Drop(2);
+
+  Register argument = r2;
+  Label not_cached, argument_is_string;
+  NumberToStringStub::GenerateLookupNumberStringCache(
+      masm,
+      r0,        // Input.
+      argument,  // Result.
+      r3,        // Scratch.
+      r4,        // Scratch.
+      r5,        // Scratch.
+      false,     // Is it a Smi?
+      &not_cached);
+  __ IncrementCounter(&Counters::string_ctor_cached_number, 1, r3, r4);
+  __ bind(&argument_is_string);
+
+  // ----------- S t a t e -------------
+  //  -- r2     : argument converted to string
+  //  -- r1     : constructor function
+  //  -- lr     : return address
+  // -----------------------------------
+
+  Label gc_required;
+  __ AllocateInNewSpace(JSValue::kSize,
+                        r0,  // Result.
+                        r3,  // Scratch.
+                        r4,  // Scratch.
+                        &gc_required,
+                        TAG_OBJECT);
+
+  // Initialising the String Object.
+  Register map = r3;
+  __ LoadGlobalFunctionInitialMap(function, map, r4);
+  if (FLAG_debug_code) {
+    __ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset));
+    __ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2));
+    __ Assert(eq, "Unexpected string wrapper instance size");
+    __ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
+    __ cmp(r4, Operand(0));
+    __ Assert(eq, "Unexpected unused properties of string wrapper");
+  }
+  __ str(map, FieldMemOperand(r0, HeapObject::kMapOffset));
+
+  __ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
+  __ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
+  __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
+
+  __ str(argument, FieldMemOperand(r0, JSValue::kValueOffset));
+
+  // Ensure the object is fully initialized.
+  STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
+
+  __ Ret();
+
+  // The argument was not found in the number to string cache. Check
+  // if it's a string already before calling the conversion builtin.
+  Label convert_argument;
+  __ bind(&not_cached);
+  __ BranchOnSmi(r0, &convert_argument);
+
+  // Is it a String?
+  __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  ASSERT(kNotStringTag != 0);
+  __ tst(r3, Operand(kIsNotStringMask));
+  __ b(ne, &convert_argument);
+  __ mov(argument, r0);
+  __ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4);
+  __ b(&argument_is_string);
+
+  // Invoke the conversion builtin and put the result into r2.
+  __ bind(&convert_argument);
+  __ push(function);  // Preserve the function.
+  __ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4);
+  __ EnterInternalFrame();
+  __ push(r0);
+  __ InvokeBuiltin(Builtins::TO_STRING, CALL_JS);
+  __ LeaveInternalFrame();
+  __ pop(function);
+  __ mov(argument, r0);
+  __ b(&argument_is_string);
+
+  // Load the empty string into r2, remove the receiver from the
+  // stack, and jump back to the case where the argument is a string.
+  __ bind(&no_arguments);
+  __ LoadRoot(argument, Heap::kEmptyStringRootIndex);
+  __ Drop(1);
+  __ b(&argument_is_string);
+
+  // At this point the argument is already a string. Call runtime to
+  // create a string wrapper.
+  __ bind(&gc_required);
+  __ IncrementCounter(&Counters::string_ctor_gc_required, 1, r3, r4);
+  __ EnterInternalFrame();
+  __ push(argument);
+  __ CallRuntime(Runtime::kNewStringWrapper, 1);
+  __ LeaveInternalFrame();
+  __ Ret();
 }
 
 
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 3e6743a..27e14df 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -6024,6 +6024,68 @@
 }
 
 
+class DeferredCountOperation: public DeferredCode {
+ public:
+  DeferredCountOperation(Register value,
+                         bool is_increment,
+                         bool is_postfix,
+                         int target_size)
+      : value_(value),
+        is_increment_(is_increment),
+        is_postfix_(is_postfix),
+        target_size_(target_size) {}
+
+  virtual void Generate() {
+    VirtualFrame copied_frame(*frame_state()->frame());
+
+    Label slow;
+    // Check for smi operand.
+    __ tst(value_, Operand(kSmiTagMask));
+    __ b(ne, &slow);
+
+    // Revert optimistic increment/decrement.
+    if (is_increment_) {
+      __ sub(value_, value_, Operand(Smi::FromInt(1)));
+    } else {
+      __ add(value_, value_, Operand(Smi::FromInt(1)));
+    }
+
+    // Slow case: Convert to number.  At this point the
+    // value to be incremented is in the value register..
+    __ bind(&slow);
+
+    // Convert the operand to a number.
+    copied_frame.EmitPush(value_);
+
+    copied_frame.InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1);
+
+    if (is_postfix_) {
+      // Postfix: store to result (on the stack).
+      __ str(r0,  MemOperand(sp, target_size_ * kPointerSize));
+    }
+
+    copied_frame.EmitPush(r0);
+    copied_frame.EmitPush(Operand(Smi::FromInt(1)));
+
+    if (is_increment_) {
+      copied_frame.CallRuntime(Runtime::kNumberAdd, 2);
+    } else {
+      copied_frame.CallRuntime(Runtime::kNumberSub, 2);
+    }
+
+    __ Move(value_, r0);
+
+    copied_frame.MergeTo(frame_state()->frame());
+  }
+
+ private:
+  Register value_;
+  bool is_increment_;
+  bool is_postfix_;
+  int target_size_;
+};
+
+
 void CodeGenerator::VisitCountOperation(CountOperation* node) {
 #ifdef DEBUG
   int original_height = frame_->height();
@@ -6083,9 +6145,7 @@
     // the target.  It also pushes the current value of the target.
     target.GetValue();
 
-    JumpTarget slow;
-    JumpTarget exit;
-
+    bool value_is_known_smi = frame_->KnownSmiAt(0);
     Register value = frame_->PopToRegister();
 
     // Postfix: Store the old value as the result.
@@ -6097,9 +6157,27 @@
       value = VirtualFrame::scratch0();
     }
 
-    // Check for smi operand.
-    __ tst(value, Operand(kSmiTagMask));
-    slow.Branch(ne);
+    // We can't use any type information here since the virtual frame from the
+    // deferred code may have lost information and we can't merge a virtual
+    // frame with less specific type knowledge to a virtual frame with more
+    // specific knowledge that has already used that specific knowledge to
+    // generate code.
+    frame_->ForgetTypeInfo();
+
+    // The constructor here will capture the current virtual frame and use it to
+    // merge to after the deferred code has run.  No virtual frame changes are
+    // allowed from here until the 'BindExit' below.
+    DeferredCode* deferred =
+        new DeferredCountOperation(value,
+                                   is_increment,
+                                   is_postfix,
+                                   target.size());
+    if (!value_is_known_smi) {
+      // Check for smi operand.
+      __ tst(value, Operand(kSmiTagMask));
+
+      deferred->Branch(ne);
+    }
 
     // Perform optimistic increment/decrement.
     if (is_increment) {
@@ -6108,46 +6186,13 @@
       __ sub(value, value, Operand(Smi::FromInt(1)), SetCC);
     }
 
-    // If the increment/decrement didn't overflow, we're done.
-    exit.Branch(vc);
+    // If increment/decrement overflows, go to deferred code.
+    deferred->Branch(vs);
 
-    // Revert optimistic increment/decrement.
-    if (is_increment) {
-      __ sub(value, value, Operand(Smi::FromInt(1)));
-    } else {
-      __ add(value, value, Operand(Smi::FromInt(1)));
-    }
+    deferred->BindExit();
 
-    // Slow case: Convert to number.  At this point the
-    // value to be incremented is in the value register..
-    slow.Bind();
-
-    // Convert the operand to a number.
-    frame_->EmitPush(value);
-
-    {
-      VirtualFrame::SpilledScope spilled(frame_);
-      frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1);
-
-      if (is_postfix) {
-        // Postfix: store to result (on the stack).
-        __ str(r0, frame_->ElementAt(target.size()));
-      }
-
-      // Compute the new value.
-      frame_->EmitPush(r0);
-      frame_->EmitPush(Operand(Smi::FromInt(1)));
-      if (is_increment) {
-        frame_->CallRuntime(Runtime::kNumberAdd, 2);
-      } else {
-        frame_->CallRuntime(Runtime::kNumberSub, 2);
-      }
-    }
-
-    __ Move(value, r0);
     // Store the new value in the target if not const.
     // At this point the answer is in the value register.
-    exit.Bind();
     frame_->EmitPush(value);
     // Set the target with the result, leaving the result on
     // top of the stack.  Removes the target from the stack if
@@ -6537,16 +6582,29 @@
 class DeferredReferenceGetNamedValue: public DeferredCode {
  public:
   explicit DeferredReferenceGetNamedValue(Register receiver,
-                                          Handle<String> name)
-      : receiver_(receiver), name_(name) {
-    set_comment("[ DeferredReferenceGetNamedValue");
+                                          Handle<String> name,
+                                          bool is_contextual)
+      : receiver_(receiver),
+        name_(name),
+        is_contextual_(is_contextual),
+        is_dont_delete_(false) {
+    set_comment(is_contextual
+                ? "[ DeferredReferenceGetNamedValue (contextual)"
+                : "[ DeferredReferenceGetNamedValue");
   }
 
   virtual void Generate();
 
+  void set_is_dont_delete(bool value) {
+    ASSERT(is_contextual_);
+    is_dont_delete_ = value;
+  }
+
  private:
   Register receiver_;
   Handle<String> name_;
+  bool is_contextual_;
+  bool is_dont_delete_;
 };
 
 
@@ -6573,10 +6631,20 @@
   // The rest of the instructions in the deferred code must be together.
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
-    __ Call(ic, RelocInfo::CODE_TARGET);
-    // The call must be followed by a nop(1) instruction to indicate that the
-    // in-object has been inlined.
-    __ nop(PROPERTY_ACCESS_INLINED);
+    RelocInfo::Mode mode = is_contextual_
+        ? RelocInfo::CODE_TARGET_CONTEXT
+        : RelocInfo::CODE_TARGET;
+    __ Call(ic,  mode);
+    // We must mark the code just after the call with the correct marker.
+    MacroAssembler::NopMarkerTypes code_marker;
+    if (is_contextual_) {
+      code_marker = is_dont_delete_
+                   ? MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE
+                   : MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT;
+    } else {
+      code_marker = MacroAssembler::PROPERTY_ACCESS_INLINED;
+    }
+    __ MarkCode(code_marker);
 
     // At this point the answer is in r0.  We move it to the expected register
     // if necessary.
@@ -6640,7 +6708,7 @@
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // keyed load has been inlined.
-    __ nop(PROPERTY_ACCESS_INLINED);
+    __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
 
     // Now go back to the frame that we entered with.  This will not overwrite
     // the receiver or key registers since they were not in use when we came
@@ -6697,7 +6765,7 @@
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // keyed store has been inlined.
-    __ nop(PROPERTY_ACCESS_INLINED);
+    __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
 
     // Block the constant pool for one more instruction after leaving this
     // constant pool block scope to include the branch instruction ending the
@@ -6745,7 +6813,7 @@
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // named store has been inlined.
-    __ nop(PROPERTY_ACCESS_INLINED);
+    __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
 
     // Go back to the frame we entered with. The instructions
     // generated by this merge are skipped over by the inline store
@@ -6763,7 +6831,14 @@
 
 // Consumes the top of stack (the receiver) and pushes the result instead.
 void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
-  if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) {
+  bool contextual_load_in_builtin =
+      is_contextual &&
+      (Bootstrapper::IsActive() ||
+      (!info_->closure().is_null() && info_->closure()->IsBuiltin()));
+
+  if (scope()->is_global_scope() ||
+      loop_nesting() == 0 ||
+      contextual_load_in_builtin) {
     Comment cmnt(masm(), "[ Load from named Property");
     // Setup the name register and call load IC.
     frame_->CallLoadIC(name,
@@ -6773,12 +6848,19 @@
     frame_->EmitPush(r0);  // Push answer.
   } else {
     // Inline the in-object property case.
-    Comment cmnt(masm(), "[ Inlined named property load");
+    Comment cmnt(masm(), is_contextual
+                             ? "[ Inlined contextual property load"
+                             : "[ Inlined named property load");
 
     // Counter will be decremented in the deferred code. Placed here to avoid
     // having it in the instruction stream below where patching will occur.
-    __ IncrementCounter(&Counters::named_load_inline, 1,
-                        frame_->scratch0(), frame_->scratch1());
+    if (is_contextual) {
+      __ IncrementCounter(&Counters::named_load_global_inline, 1,
+                          frame_->scratch0(), frame_->scratch1());
+    } else {
+      __ IncrementCounter(&Counters::named_load_inline, 1,
+                          frame_->scratch0(), frame_->scratch1());
+    }
 
     // The following instructions are the inlined load of an in-object property.
     // Parts of this code is patched, so the exact instructions generated needs
@@ -6789,18 +6871,56 @@
     Register receiver = frame_->PopToRegister();
 
     DeferredReferenceGetNamedValue* deferred =
-        new DeferredReferenceGetNamedValue(receiver, name);
+        new DeferredReferenceGetNamedValue(receiver, name, is_contextual);
 
-#ifdef DEBUG
-    int kInlinedNamedLoadInstructions = 7;
-    Label check_inlined_codesize;
-    masm_->bind(&check_inlined_codesize);
-#endif
+    bool is_dont_delete = false;
+    if (is_contextual) {
+      if (!info_->closure().is_null()) {
+        // When doing lazy compilation we can check if the global cell
+        // already exists and use its "don't delete" status as a hint.
+        AssertNoAllocation no_gc;
+        v8::internal::GlobalObject* global_object =
+            info_->closure()->context()->global();
+        LookupResult lookup;
+        global_object->LocalLookupRealNamedProperty(*name, &lookup);
+        if (lookup.IsProperty() && lookup.type() == NORMAL) {
+          ASSERT(lookup.holder() == global_object);
+          ASSERT(global_object->property_dictionary()->ValueAt(
+              lookup.GetDictionaryEntry())->IsJSGlobalPropertyCell());
+          is_dont_delete = lookup.IsDontDelete();
+        }
+      }
+      if (is_dont_delete) {
+        __ IncrementCounter(&Counters::dont_delete_hint_hit, 1,
+                            frame_->scratch0(), frame_->scratch1());
+      }
+    }
 
     { Assembler::BlockConstPoolScope block_const_pool(masm_);
-      // Check that the receiver is a heap object.
-      __ tst(receiver, Operand(kSmiTagMask));
-      deferred->Branch(eq);
+      if (!is_contextual) {
+        // Check that the receiver is a heap object.
+        __ tst(receiver, Operand(kSmiTagMask));
+        deferred->Branch(eq);
+      }
+
+      // Check for the_hole_value if necessary.
+      // Below we rely on the number of instructions generated, and we can't
+      // cope with the Check macro which does not generate a fixed number of
+      // instructions.
+      Label skip, check_the_hole, cont;
+      if (FLAG_debug_code && is_contextual && is_dont_delete) {
+        __ b(&skip);
+        __ bind(&check_the_hole);
+        __ Check(ne, "DontDelete cells can't contain the hole");
+        __ b(&cont);
+        __ bind(&skip);
+      }
+
+#ifdef DEBUG
+      int InlinedNamedLoadInstructions = 5;
+      Label check_inlined_codesize;
+      masm_->bind(&check_inlined_codesize);
+#endif
 
       Register scratch = VirtualFrame::scratch0();
       Register scratch2 = VirtualFrame::scratch1();
@@ -6812,12 +6932,42 @@
       __ cmp(scratch, scratch2);
       deferred->Branch(ne);
 
-      // Initially use an invalid index. The index will be patched by the
-      // inline cache code.
-      __ ldr(receiver, MemOperand(receiver, 0));
+      if (is_contextual) {
+#ifdef DEBUG
+        InlinedNamedLoadInstructions += 1;
+#endif
+        // Load the (initially invalid) cell and get its value.
+        masm()->mov(receiver, Operand(Factory::null_value()));
+        __ ldr(receiver,
+               FieldMemOperand(receiver, JSGlobalPropertyCell::kValueOffset));
+
+        deferred->set_is_dont_delete(is_dont_delete);
+
+        if (!is_dont_delete) {
+#ifdef DEBUG
+          InlinedNamedLoadInstructions += 3;
+#endif
+          __ cmp(receiver, Operand(Factory::the_hole_value()));
+          deferred->Branch(eq);
+        } else if (FLAG_debug_code) {
+#ifdef DEBUG
+          InlinedNamedLoadInstructions += 3;
+#endif
+          __ cmp(receiver, Operand(Factory::the_hole_value()));
+          __ b(&check_the_hole, eq);
+          __ bind(&cont);
+        }
+      } else {
+        // Initially use an invalid index. The index will be patched by the
+        // inline cache code.
+        __ ldr(receiver, MemOperand(receiver, 0));
+      }
 
       // Make sure that the expected number of instructions are generated.
-      ASSERT_EQ(kInlinedNamedLoadInstructions,
+      // If the code before is updated, the offsets in ic-arm.cc
+      // LoadIC::PatchInlinedContextualLoad and PatchInlinedLoad need
+      // to be updated.
+      ASSERT_EQ(InlinedNamedLoadInstructions,
                 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
     }
 
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 6905d23..1930f5e 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -194,14 +194,6 @@
 };
 
 
-// Different nop operations are used by the code generator to detect certain
-// states of the generated code.
-enum NopMarkerTypes {
-  NON_MARKING_NOP = 0,
-  PROPERTY_ACCESS_INLINED
-};
-
-
 // -------------------------------------------------------------------------
 // CodeGenerator
 
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index 8128f7d..f19e693 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -279,7 +279,7 @@
   __ bind(&check_codesize);
   __ RecordDebugBreakSlot();
   for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
-    __ nop(2);
+    __ nop(MacroAssembler::DEBUG_BREAK_NOP);
   }
   ASSERT_EQ(Assembler::kDebugBreakSlotInstructions,
             masm->InstructionsGeneratedSince(&check_codesize));
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 4c1f983..ef7cf6a 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -904,9 +904,9 @@
   __ TailCallExternalReference(ref, 2, 1);
 }
 
-
-static inline bool IsInlinedICSite(Address address,
-                                   Address* inline_end_address) {
+// Returns the code marker, or the 0 if the code is not marked.
+static inline int InlinedICSiteMarker(Address address,
+                                      Address* inline_end_address) {
   // If the instruction after the call site is not the pseudo instruction nop1
   // then this is not related to an inlined in-object property load. The nop1
   // instruction is located just after the call to the IC in the deferred code
@@ -914,9 +914,11 @@
   // a branch instruction for jumping back from the deferred code.
   Address address_after_call = address + Assembler::kCallTargetAddressOffset;
   Instr instr_after_call = Assembler::instr_at(address_after_call);
-  if (!Assembler::IsNop(instr_after_call, PROPERTY_ACCESS_INLINED)) {
-    return false;
-  }
+  int code_marker = MacroAssembler::GetCodeMarker(instr_after_call);
+
+  // A negative result means the code is not marked.
+  if (code_marker <= 0) return 0;
+
   Address address_after_nop = address_after_call + Assembler::kInstrSize;
   Instr instr_after_nop = Assembler::instr_at(address_after_nop);
   // There may be some reg-reg move and frame merging code to skip over before
@@ -933,7 +935,7 @@
   ASSERT(b_offset < 0);  // Jumping back from deferred code.
   *inline_end_address = address_after_nop + b_offset;
 
-  return true;
+  return code_marker;
 }
 
 
@@ -941,7 +943,10 @@
   // Find the end of the inlined code for handling the load if this is an
   // inlined IC call site.
   Address inline_end_address;
-  if (!IsInlinedICSite(address, &inline_end_address)) return false;
+  if (InlinedICSiteMarker(address, &inline_end_address)
+      != Assembler::PROPERTY_ACCESS_INLINED) {
+    return false;
+  }
 
   // Patch the offset of the property load instruction (ldr r0, [r1, #+XXX]).
   // The immediate must be representable in 12 bits.
@@ -959,8 +964,12 @@
   CPU::FlushICache(ldr_property_instr_address, 1 * Assembler::kInstrSize);
 
   // Patch the map check.
+  // For PROPERTY_ACCESS_INLINED, the load map instruction is generated
+  // 4 instructions before the end of the inlined code.
+  // See codgen-arm.cc CodeGenerator::EmitNamedLoad.
+  int ldr_map_offset = -4;
   Address ldr_map_instr_address =
-      inline_end_address - 4 * Assembler::kInstrSize;
+      inline_end_address + ldr_map_offset * Assembler::kInstrSize;
   Assembler::set_target_address_at(ldr_map_instr_address,
                                    reinterpret_cast<Address>(map));
   return true;
@@ -971,8 +980,41 @@
                                         Object* map,
                                         Object* cell,
                                         bool is_dont_delete) {
-  // TODO(<bug#>): implement this.
-  return false;
+  // Find the end of the inlined code for handling the contextual load if
+  // this is inlined IC call site.
+  Address inline_end_address;
+  int marker = InlinedICSiteMarker(address, &inline_end_address);
+  if (!((marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT) ||
+        (marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE))) {
+    return false;
+  }
+  // On ARM we don't rely on the is_dont_delete argument as the hint is already
+  // embedded in the code marker.
+  bool marker_is_dont_delete =
+      marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE;
+
+  // These are the offsets from the end of the inlined code.
+  // See codgen-arm.cc CodeGenerator::EmitNamedLoad.
+  int ldr_map_offset = marker_is_dont_delete ? -5: -8;
+  int ldr_cell_offset = marker_is_dont_delete ? -2: -5;
+  if (FLAG_debug_code && marker_is_dont_delete) {
+    // Three extra instructions were generated to check for the_hole_value.
+    ldr_map_offset -= 3;
+    ldr_cell_offset -= 3;
+  }
+  Address ldr_map_instr_address =
+      inline_end_address + ldr_map_offset * Assembler::kInstrSize;
+  Address ldr_cell_instr_address =
+      inline_end_address + ldr_cell_offset * Assembler::kInstrSize;
+
+  // Patch the map check.
+  Assembler::set_target_address_at(ldr_map_instr_address,
+                                   reinterpret_cast<Address>(map));
+  // Patch the cell address.
+  Assembler::set_target_address_at(ldr_cell_instr_address,
+                                   reinterpret_cast<Address>(cell));
+
+  return true;
 }
 
 
@@ -980,7 +1022,10 @@
   // Find the end of the inlined code for the store if there is an
   // inlined version of the store.
   Address inline_end_address;
-  if (!IsInlinedICSite(address, &inline_end_address)) return false;
+  if (InlinedICSiteMarker(address, &inline_end_address)
+      != Assembler::PROPERTY_ACCESS_INLINED) {
+    return false;
+  }
 
   // Compute the address of the map load instruction.
   Address ldr_map_instr_address =
@@ -1025,7 +1070,10 @@
 
 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) {
   Address inline_end_address;
-  if (!IsInlinedICSite(address, &inline_end_address)) return false;
+  if (InlinedICSiteMarker(address, &inline_end_address)
+      != Assembler::PROPERTY_ACCESS_INLINED) {
+    return false;
+  }
 
   // Patch the map check.
   Address ldr_map_instr_address =
@@ -1042,7 +1090,10 @@
   // Find the end of the inlined code for handling the store if this is an
   // inlined IC call site.
   Address inline_end_address;
-  if (!IsInlinedICSite(address, &inline_end_address)) return false;
+  if (InlinedICSiteMarker(address, &inline_end_address)
+      != Assembler::PROPERTY_ACCESS_INLINED) {
+    return false;
+  }
 
   // Patch the map check.
   Address ldr_map_instr_address =
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index d2c22af..ea85c79 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1693,6 +1693,33 @@
 }
 
 
+void MacroAssembler::LoadGlobalFunction(int index, Register function) {
+  // Load the global or builtins object from the current context.
+  ldr(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+  // Load the global context from the global or builtins object.
+  ldr(function, FieldMemOperand(function,
+                                GlobalObject::kGlobalContextOffset));
+  // Load the function from the global context.
+  ldr(function, MemOperand(function, Context::SlotOffset(index)));
+}
+
+
+void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
+                                                  Register map,
+                                                  Register scratch) {
+  // Load the initial map. The global functions all have initial maps.
+  ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+  if (FLAG_debug_code) {
+    Label ok, fail;
+    CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, false);
+    b(&ok);
+    bind(&fail);
+    Abort("Global functions must have initial map");
+    bind(&ok);
+  }
+}
+
+
 void MacroAssembler::JumpIfNotBothSmi(Register reg1,
                                       Register reg2,
                                       Label* on_not_both_smi) {
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 8d89d69..8bd134c 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -264,6 +264,14 @@
 
   void LoadContext(Register dst, int context_chain_length);
 
+  void LoadGlobalFunction(int index, Register function);
+
+  // Load the initial map from the global function. The registers
+  // function and map can be the same, function is then overwritten.
+  void LoadGlobalFunctionInitialMap(Register function,
+                                    Register map,
+                                    Register scratch);
+
   // ---------------------------------------------------------------------------
   // JavaScript invokes
 
@@ -319,6 +327,40 @@
                               Register scratch,
                               Label* miss);
 
+  inline void MarkCode(NopMarkerTypes type) {
+    nop(type);
+  }
+
+  // Check if the given instruction is a 'type' marker.
+  // ie. check if is is a mov r<type>, r<type> (referenced as nop(type))
+  // These instructions are generated to mark special location in the code,
+  // like some special IC code.
+  static inline bool IsMarkedCode(Instr instr, int type) {
+    ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
+    return IsNop(instr, type);
+  }
+
+
+  static inline int GetCodeMarker(Instr instr) {
+    int dst_reg_offset = 12;
+    int dst_mask = 0xf << dst_reg_offset;
+    int src_mask = 0xf;
+    int dst_reg = (instr & dst_mask) >> dst_reg_offset;
+    int src_reg = instr & src_mask;
+    uint32_t non_register_mask = ~(dst_mask | src_mask);
+    uint32_t mov_mask = al | 13 << 21;
+
+    // Return <n> if we have a mov rn rn, else return -1.
+    int type = ((instr & non_register_mask) == mov_mask) &&
+               (dst_reg == src_reg) &&
+               (FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
+                   ? src_reg
+                   : -1;
+    ASSERT((type == -1) ||
+           ((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
+    return type;
+  }
+
 
   // ---------------------------------------------------------------------------
   // Allocation support
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index f3f7a5d..0a5eac2 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -2902,8 +2902,7 @@
 }
 
 
-MaybeObject* ConstructStubCompiler::CompileConstructStub(
-    SharedFunctionInfo* shared) {
+MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
   // ----------- S t a t e -------------
   //  -- r0    : argc
   //  -- r1    : constructor
@@ -2987,6 +2986,7 @@
   // r7: undefined
   // Fill the initialized properties with a constant value or a passed argument
   // depending on the this.x = ...; assignment in the function.
+  SharedFunctionInfo* shared = function->shared();
   for (int i = 0; i < shared->this_property_assignments_count(); i++) {
     if (shared->IsThisPropertyAssignmentArgument(i)) {
       Label not_passed, next;
@@ -3011,8 +3011,9 @@
   }
 
   // Fill the unused in-object property fields with undefined.
+  ASSERT(function->has_initial_map());
   for (int i = shared->this_property_assignments_count();
-       i < shared->CalculateInObjectProperties();
+       i < function->initial_map()->inobject_properties();
        i++) {
       __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
   }
diff --git a/src/checks.cc b/src/checks.cc
index 1ab8802..3c3d940 100644
--- a/src/checks.cc
+++ b/src/checks.cc
@@ -107,3 +107,4 @@
   intptr_t HeapObjectTagMask() { return kHeapObjectTagMask; }
 
 } }  // namespace v8::internal
+
diff --git a/src/checks.h b/src/checks.h
index 6b49322..d49f97f 100644
--- a/src/checks.h
+++ b/src/checks.h
@@ -31,7 +31,6 @@
 #include <string.h>
 
 extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
-void API_Fatal(const char* location, const char* format, ...);
 
 // The FATAL, UNREACHABLE and UNIMPLEMENTED macros are useful during
 // development, but they should not be relied on in the final product.
@@ -222,28 +221,6 @@
 }
 
 
-namespace v8 {
-  class Value;
-  template <class T> class Handle;
-}
-
-
-void CheckNonEqualsHelper(const char* file,
-                          int line,
-                          const char* unexpected_source,
-                          v8::Handle<v8::Value> unexpected,
-                          const char* value_source,
-                          v8::Handle<v8::Value> value);
-
-
-void CheckEqualsHelper(const char* file,
-                       int line,
-                       const char* expected_source,
-                       v8::Handle<v8::Value> expected,
-                       const char* value_source,
-                       v8::Handle<v8::Value> value);
-
-
 #define CHECK_EQ(expected, value) CheckEqualsHelper(__FILE__, __LINE__, \
   #expected, expected, #value, value)
 
@@ -307,17 +284,6 @@
 // and release compilation modes behaviour.
 #define STATIC_ASSERT(test)  STATIC_CHECK(test)
 
-namespace v8 { namespace internal {
-
-intptr_t HeapObjectTagMask();
-
-} }  // namespace v8::internal
-
-#define ASSERT_TAG_ALIGNED(address) \
-  ASSERT((reinterpret_cast<intptr_t>(address) & HeapObjectTagMask()) == 0)
-
-#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & HeapObjectTagMask()) == 0)
-
 #define ASSERT_NOT_NULL(p)  ASSERT_NE(NULL, p)
 
 #endif  // V8_CHECKS_H_
diff --git a/src/conversions.cc b/src/conversions.cc
index 19fa777..a954d6c 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -448,12 +448,12 @@
   bool sign = false;
 
   if (*current == '+') {
-    // Ignore leading sign; skip following spaces.
+    // Ignore leading sign.
     ++current;
-    if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
+    if (current == end) return JUNK_STRING_VALUE;
   } else if (*current == '-') {
     ++current;
-    if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
+    if (current == end) return JUNK_STRING_VALUE;
     sign = true;
   }
 
diff --git a/src/dateparser-inl.h b/src/dateparser-inl.h
index e52cc94..ac28c62 100644
--- a/src/dateparser-inl.h
+++ b/src/dateparser-inl.h
@@ -59,7 +59,7 @@
       } else if (in.Skip('.') && time.IsExpecting(n)) {
         time.Add(n);
         if (!in.IsAsciiDigit()) return false;
-        int n = in.ReadUnsignedNumber();
+        int n = in.ReadMilliseconds();
         time.AddFinal(n);
       } else if (tz.IsExpecting(n)) {
         tz.SetAbsoluteMinute(n);
diff --git a/src/dateparser.h b/src/dateparser.h
index 28053f4..40e56f3 100644
--- a/src/dateparser.h
+++ b/src/dateparser.h
@@ -87,6 +87,18 @@
       return n;
     }
 
+    // Read a string of digits, take the first three or fewer as an unsigned
+    // number of milliseconds, and ignore any digits after the first three.
+    int ReadMilliseconds() {
+      has_read_number_ = true;
+      int n = 0;
+      int power;
+      for (power = 100; IsAsciiDigit(); Next(), power = power / 10) {
+        n = n + power * (ch_ - '0');
+      }
+      return n;
+    }
+
     // Read a word (sequence of chars. >= 'A'), fill the given buffer with a
     // lower-case prefix, and pad any remainder of the buffer with zeroes.
     // Return word length.
diff --git a/src/handles.cc b/src/handles.cc
index 3dfb886..37a5011 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -143,7 +143,7 @@
 
 void SetExpectedNofProperties(Handle<JSFunction> func, int nof) {
   // If objects constructed from this function exist then changing
-  // 'estimated_nof_properties' is dangerous since the previois value might
+  // 'estimated_nof_properties' is dangerous since the previous value might
   // have been compiled into the fast construct stub. More over, the inobject
   // slack tracking logic might have adjusted the previous value, so even
   // passing the same value is risky.
diff --git a/src/hashmap.cc b/src/hashmap.cc
index 3c4e5cd..1422afd 100644
--- a/src/hashmap.cc
+++ b/src/hashmap.cc
@@ -25,7 +25,11 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "v8.h"
+#include "../include/v8stdint.h"
+#include "globals.h"
+#include "checks.h"
+#include "utils.h"
+#include "allocation.h"
 
 #include "hashmap.h"
 
@@ -195,7 +199,7 @@
   ASSERT(IsPowerOf2(capacity));
   map_ = reinterpret_cast<Entry*>(allocator_->New(capacity * sizeof(Entry)));
   if (map_ == NULL) {
-    V8::FatalProcessOutOfMemory("HashMap::Initialize");
+    v8::internal::FatalProcessOutOfMemory("HashMap::Initialize");
     return;
   }
   capacity_ = capacity;
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index 3fb1ec1..91ac986 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -69,7 +69,8 @@
 JSObjectsCluster Clusterizer::Clusterize(HeapObject* obj, bool fine_grain) {
   if (obj->IsJSObject()) {
     JSObject* js_obj = JSObject::cast(obj);
-    String* constructor = JSObject::cast(js_obj)->constructor_name();
+    String* constructor = GetConstructorNameForHeapProfile(
+        JSObject::cast(js_obj));
     // Differentiate Object and Array instances.
     if (fine_grain && (constructor == Heap::Object_symbol() ||
                        constructor == Heap::Array_symbol())) {
@@ -714,7 +715,7 @@
 
 static void PrintProducerStackTrace(Object* obj, void* trace) {
   if (!obj->IsJSObject()) return;
-  String* constructor = JSObject::cast(obj)->constructor_name();
+  String* constructor = GetConstructorNameForHeapProfile(JSObject::cast(obj));
   SmartPointer<char> s_name(
       constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
   LOG(HeapSampleJSProducerEvent(GetConstructorName(*s_name),
@@ -886,7 +887,8 @@
     return JSObjectsCluster(String::cast(object));
   } else {
     JSObject* js_obj = JSObject::cast(object);
-    String* constructor = JSObject::cast(js_obj)->constructor_name();
+    String* constructor = GetConstructorNameForHeapProfile(
+        JSObject::cast(js_obj));
     return JSObjectsCluster(constructor, object);
   }
 }
@@ -1064,6 +1066,8 @@
 
   // Fill up references.
   IterateRetainers<AllocatingRetainersIterator>(&entries_map);
+
+  snapshot->SetDominatorsToSelf();
 }
 
 
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 61aadf7..cbf93dd 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -537,7 +537,6 @@
 
 
 void MacroAssembler::LoadAllocationTopHelper(Register result,
-                                             Register result_end,
                                              Register scratch,
                                              AllocationFlags flags) {
   ExternalReference new_space_allocation_top =
@@ -559,7 +558,6 @@
   if (scratch.is(no_reg)) {
     mov(result, Operand::StaticVariable(new_space_allocation_top));
   } else {
-    ASSERT(!scratch.is(result_end));
     mov(Operand(scratch), Immediate(new_space_allocation_top));
     mov(result, Operand(scratch, 0));
   }
@@ -608,7 +606,7 @@
   ASSERT(!result.is(result_end));
 
   // Load address of new object into result.
-  LoadAllocationTopHelper(result, result_end, scratch, flags);
+  LoadAllocationTopHelper(result, scratch, flags);
 
   Register top_reg = result_end.is_valid() ? result_end : result;
 
@@ -664,7 +662,7 @@
   ASSERT(!result.is(result_end));
 
   // Load address of new object into result.
-  LoadAllocationTopHelper(result, result_end, scratch, flags);
+  LoadAllocationTopHelper(result, scratch, flags);
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
@@ -705,7 +703,7 @@
   ASSERT(!result.is(result_end));
 
   // Load address of new object into result.
-  LoadAllocationTopHelper(result, result_end, scratch, flags);
+  LoadAllocationTopHelper(result, scratch, flags);
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index cea7a70..d208dbe 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -631,7 +631,6 @@
 
   // Allocation support helpers.
   void LoadAllocationTopHelper(Register result,
-                               Register result_end,
                                Register scratch,
                                AllocationFlags flags);
   void UpdateAllocationTopHelper(Register result_end, Register scratch);
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 3120ff9..adcb521 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -3021,8 +3021,7 @@
 
 // Specialized stub for constructing objects from functions which only have only
 // simple assignments of the form this.x = ...; in their body.
-MaybeObject* ConstructStubCompiler::CompileConstructStub(
-    SharedFunctionInfo* shared) {
+MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
   // ----------- S t a t e -------------
   //  -- eax : argc
   //  -- edi : constructor
@@ -3098,6 +3097,7 @@
   // edi: undefined
   // Fill the initialized properties with a constant value or a passed argument
   // depending on the this.x = ...; assignment in the function.
+  SharedFunctionInfo* shared = function->shared();
   for (int i = 0; i < shared->this_property_assignments_count(); i++) {
     if (shared->IsThisPropertyAssignmentArgument(i)) {
       // Check if the argument assigned to the property is actually passed.
@@ -3125,8 +3125,9 @@
   }
 
   // Fill the unused in-object property fields with undefined.
+  ASSERT(function->has_initial_map());
   for (int i = shared->this_property_assignments_count();
-       i < shared->CalculateInObjectProperties();
+       i < function->initial_map()->inobject_properties();
        i++) {
     __ mov(Operand(edx, i * kPointerSize), edi);
   }
diff --git a/src/log.cc b/src/log.cc
index d12aafb..55f15de 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -194,11 +194,6 @@
 
   ~Ticker() { if (IsActive()) Stop(); }
 
-  virtual void SampleStack(TickSample* sample) {
-    ASSERT(IsSynchronous());
-    StackTracer::Trace(sample);
-  }
-
   virtual void Tick(TickSample* sample) {
     if (profiler_) profiler_->Insert(sample);
     if (window_) window_->AddState(sample->state);
@@ -224,6 +219,12 @@
     if (!window_ && IsActive()) Stop();
   }
 
+ protected:
+  virtual void DoSampleStack(TickSample* sample) {
+    ASSERT(IsSynchronous());
+    StackTracer::Trace(sample);
+  }
+
  private:
   SlidingStateWindow* window_;
   Profiler* profiler_;
diff --git a/src/objects.cc b/src/objects.cc
index 8efb0da..f5d19e2 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1166,9 +1166,6 @@
 
 
 String* JSObject::constructor_name() {
-  if (IsJSFunction()) {
-    return Heap::closure_symbol();
-  }
   if (map()->constructor()->IsJSFunction()) {
     JSFunction* constructor = JSFunction::cast(map()->constructor());
     String* name = String::cast(constructor->shared()->name());
diff --git a/src/parser.cc b/src/parser.cc
index 7e4a51e..186d102 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -356,65 +356,6 @@
 }
 
 
-Vector<unsigned> PartialParserRecorder::ExtractData() {
-  int function_size = function_store_.size();
-  int total_size = ScriptDataImpl::kHeaderSize + function_size;
-  Vector<unsigned> data = Vector<unsigned>::New(total_size);
-  preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size;
-  preamble_[ScriptDataImpl::kSymbolCountOffset] = 0;
-  memcpy(data.start(), preamble_, sizeof(preamble_));
-  int symbol_start = ScriptDataImpl::kHeaderSize + function_size;
-  if (function_size > 0) {
-    function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize,
-                                           symbol_start));
-  }
-  return data;
-}
-
-
-void CompleteParserRecorder::LogSymbol(int start, Vector<const char> literal) {
-  if (!is_recording_) return;
-
-  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.
-    id = ++symbol_id_;
-    entry->value = reinterpret_cast<void*>(id);
-    Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
-    entry->key = &symbol[0];
-  }
-  WriteNumber(id - 1);
-}
-
-
-Vector<unsigned> CompleteParserRecorder::ExtractData() {
-  int function_size = function_store_.size();
-  // Add terminator to symbols, then pad to unsigned size.
-  int symbol_size = symbol_store_.size();
-  int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned));
-  symbol_store_.AddBlock(padding, ScriptDataImpl::kNumberTerminator);
-  symbol_size += padding;
-  int total_size = ScriptDataImpl::kHeaderSize + function_size
-      + (symbol_size / sizeof(unsigned));
-  Vector<unsigned> data = Vector<unsigned>::New(total_size);
-  preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size;
-  preamble_[ScriptDataImpl::kSymbolCountOffset] = symbol_id_;
-  memcpy(data.start(), preamble_, sizeof(preamble_));
-  int symbol_start = ScriptDataImpl::kHeaderSize + function_size;
-  if (function_size > 0) {
-    function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize,
-                                           symbol_start));
-  }
-  if (!has_error()) {
-    symbol_store_.WriteTo(
-        Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
-  }
-  return data;
-}
-
-
 FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
   // The current pre-data entry must be a FunctionEntry with the given
   // start position.
@@ -437,92 +378,52 @@
 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 (store_.length() < PreparseDataConstants::kHeaderSize) return false;
+  if (magic() != PreparseDataConstants::kMagicNumber) return false;
+  if (version() != PreparseDataConstants::kCurrentVersion) return false;
   if (has_error()) {
     // Extra sane sanity check for error message encoding.
-    if (store_.length() <= kHeaderSize + kMessageTextPos) return false;
-    if (Read(kMessageStartPos) > Read(kMessageEndPos)) return false;
-    unsigned arg_count = Read(kMessageArgCountPos);
-    int pos = kMessageTextPos;
+    if (store_.length() <= PreparseDataConstants::kHeaderSize
+                         + PreparseDataConstants::kMessageTextPos) {
+      return false;
+    }
+    if (Read(PreparseDataConstants::kMessageStartPos) >
+        Read(PreparseDataConstants::kMessageEndPos)) {
+      return false;
+    }
+    unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
+    int pos = PreparseDataConstants::kMessageTextPos;
     for (unsigned int i = 0; i <= arg_count; i++) {
-      if (store_.length() <= kHeaderSize + pos) return false;
+      if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
+        return false;
+      }
       int length = static_cast<int>(Read(pos));
       if (length < 0) return false;
       pos += 1 + length;
     }
-    if (store_.length() < kHeaderSize + pos) return false;
+    if (store_.length() < PreparseDataConstants::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]);
+      static_cast<int>(store_[PreparseDataConstants::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]);
+      static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
   if (symbol_count < 0) return false;
   // Check that the total size has room for header and function entries.
   int minimum_size =
-      ScriptDataImpl::kHeaderSize + functions_size;
+      PreparseDataConstants::kHeaderSize + functions_size;
   if (store_.length() < minimum_size) return false;
   return true;
 }
 
 
 
-PartialParserRecorder::PartialParserRecorder()
-    : function_store_(0),
-      is_recording_(true),
-      pause_count_(0) {
-  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(6, ScriptDataImpl::kHeaderSize);
-#ifdef DEBUG
-  prev_start_ = -1;
-#endif
-}
-
-
-CompleteParserRecorder::CompleteParserRecorder()
-    : PartialParserRecorder(),
-      symbol_store_(0),
-      symbol_entries_(0),
-      symbol_table_(vector_compare),
-      symbol_id_(0) {
-}
-
-
-void PartialParserRecorder::WriteString(Vector<const char> str) {
-  function_store_.Add(str.length());
-  for (int i = 0; i < str.length(); i++) {
-    function_store_.Add(str[i]);
-  }
-}
-
-
-void CompleteParserRecorder::WriteNumber(int number) {
-  ASSERT(number >= 0);
-
-  int mask = (1 << 28) - 1;
-  for (int i = 28; i > 0; i -= 7) {
-    if (number > mask) {
-      symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u);
-      number &= mask;
-    }
-    mask >>= 7;
-  }
-  symbol_store_.Add(static_cast<byte>(number));
-}
-
-
-
 const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
   int length = start[0];
   char* result = NewArray<char>(length + 1);
@@ -534,47 +435,26 @@
   return result;
 }
 
-
-void PartialParserRecorder::LogMessage(Scanner::Location loc,
-                                       const char* message,
-                                       Vector<const char*> args) {
-  if (has_error()) return;
-  preamble_[ScriptDataImpl::kHasErrorOffset] = true;
-  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]));
-  }
-  is_recording_ = false;
-}
-
-
 Scanner::Location ScriptDataImpl::MessageLocation() {
-  int beg_pos = Read(kMessageStartPos);
-  int end_pos = Read(kMessageEndPos);
+  int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
+  int end_pos = Read(PreparseDataConstants::kMessageEndPos);
   return Scanner::Location(beg_pos, end_pos);
 }
 
 
 const char* ScriptDataImpl::BuildMessage() {
-  unsigned* start = ReadAddress(kMessageTextPos);
+  unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
   return ReadString(start, NULL);
 }
 
 
 Vector<const char*> ScriptDataImpl::BuildArgs() {
-  int arg_count = Read(kMessageArgCountPos);
+  int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
   const char** array = NewArray<const char*>(arg_count);
   // Position after text found by skipping past length field and
   // length field content words.
-  int pos = kMessageTextPos + 1 + Read(kMessageTextPos);
+  int pos = PreparseDataConstants::kMessageTextPos + 1
+      + Read(PreparseDataConstants::kMessageTextPos);
   for (int i = 0; i < arg_count; i++) {
     int count = 0;
     array[i] = ReadString(ReadAddress(pos), &count);
@@ -585,12 +465,12 @@
 
 
 unsigned ScriptDataImpl::Read(int position) {
-  return store_[ScriptDataImpl::kHeaderSize + position];
+  return store_[PreparseDataConstants::kHeaderSize + position];
 }
 
 
 unsigned* ScriptDataImpl::ReadAddress(int position) {
-  return &store_[ScriptDataImpl::kHeaderSize + position];
+  return &store_[PreparseDataConstants::kHeaderSize + position];
 }
 
 
@@ -4601,9 +4481,10 @@
 
 void ScriptDataImpl::Initialize() {
   // Prepares state for use.
-  if (store_.length() >= kHeaderSize) {
-    function_index_ = kHeaderSize;
-    int symbol_data_offset = kHeaderSize + store_[kFunctionsSizeOffset];
+  if (store_.length() >= PreparseDataConstants::kHeaderSize) {
+    function_index_ = PreparseDataConstants::kHeaderSize;
+    int symbol_data_offset = PreparseDataConstants::kHeaderSize
+        + store_[PreparseDataConstants::kFunctionsSizeOffset];
     if (store_.length() > symbol_data_offset) {
       symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
     } else {
@@ -4625,7 +4506,7 @@
   byte* data = *source;
   if (data >= symbol_data_end_) return -1;
   byte input = *data;
-  if (input == kNumberTerminator) {
+  if (input == PreparseDataConstants::kNumberTerminator) {
     // End of stream marker.
     return -1;
   }
@@ -4646,11 +4527,11 @@
 static ScriptDataImpl* DoPreParse(Handle<String> source,
                                   unibrow::CharacterStream* stream,
                                   bool allow_lazy,
-                                  PartialParserRecorder* recorder,
+                                  ParserRecorder* recorder,
                                   int literal_flags) {
   V8JavaScriptScanner scanner;
   scanner.Initialize(source, stream, literal_flags);
-  preparser::PreParser<JavaScriptScanner, PartialParserRecorder> preparser;
+  preparser::PreParser preparser;
   if (!preparser.PreParseProgram(&scanner, recorder, allow_lazy)) {
     Top::StackOverflow();
     return NULL;
diff --git a/src/parser.h b/src/parser.h
index 9a84ab9..a067bd7 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -32,6 +32,7 @@
 #include "ast.h"
 #include "scanner.h"
 #include "scopes.h"
+#include "preparse-data.h"
 
 namespace v8 {
 namespace internal {
@@ -123,32 +124,15 @@
   Vector<const char*> BuildArgs();
 
   int symbol_count() {
-    return (store_.length() > kHeaderSize) ? store_[kSymbolCountOffset] : 0;
+    return (store_.length() > PreparseDataConstants::kHeaderSize)
+        ? store_[PreparseDataConstants::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]; }
-
-  static const unsigned kMagicNumber = 0xBadDead;
-  static const unsigned kCurrentVersion = 5;
-
-  static const int kMagicOffset = 0;
-  static const int kVersionOffset = 1;
-  static const int kHasErrorOffset = 2;
-  static const int kFunctionsSizeOffset = 3;
-  static const int kSymbolCountOffset = 4;
-  static const int kSizeOffset = 5;
-  static const int kHeaderSize = 6;
-
-  // If encoding a message, the following positions are fixed.
-  static const int kMessageStartPos = 0;
-  static const int kMessageEndPos = 1;
-  static const int kMessageArgCountPos = 2;
-  static const int kMessageTextPos = 3;
-
-  static const byte kNumberTerminator = 0x80u;
+  bool has_error() { return store_[PreparseDataConstants::kHasErrorOffset]; }
+  unsigned magic() { return store_[PreparseDataConstants::kMagicOffset]; }
+  unsigned version() { return store_[PreparseDataConstants::kVersionOffset]; }
 
  private:
   Vector<unsigned> store_;
@@ -177,127 +161,6 @@
 };
 
 
-// Record only functions.
-class PartialParserRecorder {
- public:
-  PartialParserRecorder();
-  virtual ~PartialParserRecorder() {}
-
-  void LogFunction(int start, int end, int literals, int properties) {
-    function_store_.Add(start);
-    function_store_.Add(end);
-    function_store_.Add(literals);
-    function_store_.Add(properties);
-  }
-
-  virtual void LogSymbol(int start, const char* symbol, int length) { }
-
-  // Logs an error message and marks the log as containing an error.
-  // Further logging will be ignored, and ExtractData will return a vector
-  // representing the error only.
-  void LogMessage(int start,
-                  int end,
-                  const char* message,
-                  const char* argument_opt) {
-    Scanner::Location location(start, end);
-    Vector<const char*> arguments;
-    if (argument_opt != NULL) {
-      arguments = Vector<const char*>(&argument_opt, 1);
-    }
-    this->LogMessage(location, message, arguments);
-  }
-
-  int function_position() { return function_store_.size(); }
-
-  void LogMessage(Scanner::Location loc,
-                  const char* message,
-                  Vector<const char*> args);
-
-  virtual Vector<unsigned> ExtractData();
-
-  void PauseRecording() {
-    pause_count_++;
-    is_recording_ = false;
-  }
-
-  void ResumeRecording() {
-    ASSERT(pause_count_ > 0);
-    if (--pause_count_ == 0) is_recording_ = !has_error();
-  }
-
-  int symbol_position() { return 0; }
-  int symbol_ids() { return 0; }
-
- protected:
-  bool has_error() {
-    return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
-  }
-
-  bool is_recording() {
-    return is_recording_;
-  }
-
-  void WriteString(Vector<const char> str);
-
-  Collector<unsigned> function_store_;
-  unsigned preamble_[ScriptDataImpl::kHeaderSize];
-  bool is_recording_;
-  int pause_count_;
-
-#ifdef DEBUG
-  int prev_start_;
-#endif
-};
-
-
-// Record both functions and symbols.
-class CompleteParserRecorder: public PartialParserRecorder {
- public:
-  CompleteParserRecorder();
-  virtual ~CompleteParserRecorder() { }
-
-  void LogSymbol(int start, Vector<const char> literal);
-
-  virtual void LogSymbol(int start, const char* symbol, int length) {
-    LogSymbol(start, Vector<const char>(symbol, length));
-  }
-
-  virtual Vector<unsigned> ExtractData();
-
-  int symbol_position() { return symbol_store_.size(); }
-  int symbol_ids() { return symbol_id_; }
-
- private:
-  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;
-  }
-
-  // Write a non-negative number to the symbol store.
-  void WriteNumber(int number);
-
-  Collector<byte> symbol_store_;
-  Collector<Vector<const char> > symbol_entries_;
-  HashMap symbol_table_;
-  int symbol_id_;
-};
-
-
-
 class ParserApi {
  public:
   // Parses the source code represented by the compilation info and sets its
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 6b8f2c0..0d89a16 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -620,7 +620,8 @@
     : interval_(interval),
       profiling_(profiling),
       synchronous_(profiling),
-      active_(false) {
+      active_(false),
+      samples_taken_(0) {
   data_ = new PlatformData();
 }
 
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 89003ba..cb8e919 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -865,7 +865,8 @@
     : interval_(interval),
       profiling_(profiling),
       synchronous_(profiling),
-      active_(false) {
+      active_(false),
+      samples_taken_(0) {
   data_ = new PlatformData(this);
 }
 
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index 5e0e78d..c3f21dc 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -634,7 +634,8 @@
     : interval_(interval),
       profiling_(profiling),
       synchronous_(profiling),
-      active_(false) {
+      active_(false),
+      samples_taken_(0) {
   data_ = new PlatformData(this);
 }
 
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index e03059a..0751fc7 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -572,7 +572,11 @@
 
 
 Sampler::Sampler(int interval, bool profiling)
-    : interval_(interval), profiling_(profiling), active_(false) {
+    : interval_(interval),
+      profiling_(profiling),
+      synchronous_(profiling),
+      active_(false),
+      samples_taken_(0) {
   data_ = new PlatformData();
 }
 
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index fcd69de..ff5d83b 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -605,7 +605,8 @@
     : interval_(interval),
       profiling_(profiling),
       synchronous_(profiling),
-      active_(false) {
+      active_(false),
+      samples_taken_(0) {
   data_ = new PlatformData();
 }
 
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index a0ba5e8..1dcc84b 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -54,6 +54,11 @@
 #define _WIN32_WINNT 0x501
 #endif
 
+// Required before stdlib.h inclusion for cryptographically strong rand_s.
+#ifndef _CRT_RAND_S
+#define _CRT_RAND_S
+#endif  // _CRT_RAND_S
+
 #include <windows.h>
 
 #include <time.h>  // For LocalOffset() implementation.
@@ -584,11 +589,8 @@
 
 void OS::Setup() {
   // Seed the random number generator.
-  // Convert the current time to a 64-bit integer first, before converting it
-  // to an unsigned. Going directly can cause an overflow and the seed to be
-  // set to all ones. The seed will be identical for different instances that
-  // call this setup code within the same millisecond.
-  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
+  unsigned int seed;
+  CHECK_EQ(rand_s(&seed), 0);
   srand(static_cast<unsigned int>(seed));
 }
 
@@ -1903,7 +1905,8 @@
     : interval_(interval),
       profiling_(profiling),
       synchronous_(profiling),
-      active_(false) {
+      active_(false),
+      samples_taken_(0) {
   data_ = new PlatformData(this);
 }
 
diff --git a/src/platform.h b/src/platform.h
index 42e6eae..49efc3c 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -554,11 +554,14 @@
 class Sampler {
  public:
   // Initialize sampler.
-  explicit Sampler(int interval, bool profiling);
+  Sampler(int interval, bool profiling);
   virtual ~Sampler();
 
   // Performs stack sampling.
-  virtual void SampleStack(TickSample* sample) = 0;
+  void SampleStack(TickSample* sample) {
+    DoSampleStack(sample);
+    IncSamplesTaken();
+  }
 
   // This method is called for each sampling period with the current
   // program counter.
@@ -580,14 +583,24 @@
   // Whether the sampler is running (that is, consumes resources).
   bool IsActive() const { return active_; }
 
+  // Used in tests to make sure that stack sampling is performed.
+  int samples_taken() const { return samples_taken_; }
+  void ResetSamplesTaken() { samples_taken_ = 0; }
+
   class PlatformData;
 
+ protected:
+  virtual void DoSampleStack(TickSample* sample) = 0;
+
  private:
+  void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
+
   const int interval_;
   const bool profiling_;
   const bool synchronous_;
   bool active_;
   PlatformData* data_;  // Platform specific data.
+  int samples_taken_;  // Counts stack samples taken.
   DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
 };
 
diff --git a/src/preparse-data.cc b/src/preparse-data.cc
new file mode 100644
index 0000000..9a36771
--- /dev/null
+++ b/src/preparse-data.cc
@@ -0,0 +1,180 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "../include/v8stdint.h"
+#include "globals.h"
+#include "checks.h"
+#include "allocation.h"
+#include "utils.h"
+#include "list-inl.h"
+#include "hashmap.h"
+#include "preparse-data.h"
+
+namespace v8 {
+namespace internal {
+
+// ----------------------------------------------------------------------------
+// FunctionLoggingParserRecorder
+
+FunctionLoggingParserRecorder::FunctionLoggingParserRecorder()
+    : function_store_(0),
+      is_recording_(true),
+      pause_count_(0) {
+  preamble_[PreparseDataConstants::kMagicOffset] =
+      PreparseDataConstants::kMagicNumber;
+  preamble_[PreparseDataConstants::kVersionOffset] =
+      PreparseDataConstants::kCurrentVersion;
+  preamble_[PreparseDataConstants::kHasErrorOffset] = false;
+  preamble_[PreparseDataConstants::kFunctionsSizeOffset] = 0;
+  preamble_[PreparseDataConstants::kSymbolCountOffset] = 0;
+  preamble_[PreparseDataConstants::kSizeOffset] = 0;
+  ASSERT_EQ(6, PreparseDataConstants::kHeaderSize);
+#ifdef DEBUG
+  prev_start_ = -1;
+#endif
+}
+
+
+void FunctionLoggingParserRecorder::LogMessage(int start_pos,
+                                               int end_pos,
+                                               const char* message,
+                                               const char* arg_opt) {
+  if (has_error()) return;
+  preamble_[PreparseDataConstants::kHasErrorOffset] = true;
+  function_store_.Reset();
+  STATIC_ASSERT(PreparseDataConstants::kMessageStartPos == 0);
+  function_store_.Add(start_pos);
+  STATIC_ASSERT(PreparseDataConstants::kMessageEndPos == 1);
+  function_store_.Add(end_pos);
+  STATIC_ASSERT(PreparseDataConstants::kMessageArgCountPos == 2);
+  function_store_.Add((arg_opt == NULL) ? 0 : 1);
+  STATIC_ASSERT(PreparseDataConstants::kMessageTextPos == 3);
+  WriteString(CStrVector(message));
+  if (arg_opt) WriteString(CStrVector(arg_opt));
+  is_recording_ = false;
+}
+
+
+void FunctionLoggingParserRecorder::WriteString(Vector<const char> str) {
+  function_store_.Add(str.length());
+  for (int i = 0; i < str.length(); i++) {
+    function_store_.Add(str[i]);
+  }
+}
+
+// ----------------------------------------------------------------------------
+// PartialParserRecorder -  Record both function entries and symbols.
+
+Vector<unsigned> PartialParserRecorder::ExtractData() {
+  int function_size = function_store_.size();
+  int total_size = PreparseDataConstants::kHeaderSize + function_size;
+  Vector<unsigned> data = Vector<unsigned>::New(total_size);
+  preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
+  preamble_[PreparseDataConstants::kSymbolCountOffset] = 0;
+  memcpy(data.start(), preamble_, sizeof(preamble_));
+  int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
+  if (function_size > 0) {
+    function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
+                                           symbol_start));
+  }
+  return data;
+}
+
+
+// ----------------------------------------------------------------------------
+// CompleteParserRecorder -  Record both function entries and symbols.
+
+CompleteParserRecorder::CompleteParserRecorder()
+    : FunctionLoggingParserRecorder(),
+      symbol_store_(0),
+      symbol_entries_(0),
+      symbol_table_(vector_compare),
+      symbol_id_(0) {
+}
+
+
+void CompleteParserRecorder::LogSymbol(
+    int start, const char* literal_chars, int length) {
+  if (!is_recording_) return;
+
+  Vector<const char> literal(literal_chars, length);
+  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.
+    id = ++symbol_id_;
+    entry->value = reinterpret_cast<void*>(id);
+    Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
+    entry->key = &symbol[0];
+  }
+  WriteNumber(id - 1);
+}
+
+
+Vector<unsigned> CompleteParserRecorder::ExtractData() {
+  int function_size = function_store_.size();
+  // Add terminator to symbols, then pad to unsigned size.
+  int symbol_size = symbol_store_.size();
+  int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned));
+  symbol_store_.AddBlock(padding, PreparseDataConstants::kNumberTerminator);
+  symbol_size += padding;
+  int total_size = PreparseDataConstants::kHeaderSize + function_size
+      + (symbol_size / sizeof(unsigned));
+  Vector<unsigned> data = Vector<unsigned>::New(total_size);
+  preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
+  preamble_[PreparseDataConstants::kSymbolCountOffset] = symbol_id_;
+  memcpy(data.start(), preamble_, sizeof(preamble_));
+  int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
+  if (function_size > 0) {
+    function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
+                                           symbol_start));
+  }
+  if (!has_error()) {
+    symbol_store_.WriteTo(
+        Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
+  }
+  return data;
+}
+
+
+void CompleteParserRecorder::WriteNumber(int number) {
+  ASSERT(number >= 0);
+
+  int mask = (1 << 28) - 1;
+  for (int i = 28; i > 0; i -= 7) {
+    if (number > mask) {
+      symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u);
+      number &= mask;
+    }
+    mask >>= 7;
+  }
+  symbol_store_.Add(static_cast<byte>(number));
+}
+
+
+} }  // namespace v8::internal.
diff --git a/src/preparse-data.h b/src/preparse-data.h
new file mode 100644
index 0000000..a96e50f
--- /dev/null
+++ b/src/preparse-data.h
@@ -0,0 +1,223 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PREPARSER_DATA_H_
+#define V8_PREPARSER_DATA_H_
+
+#include "hashmap.h"
+
+namespace v8 {
+namespace internal {
+
+// Generic and general data used by preparse data recorders and readers.
+
+class PreparseDataConstants : public AllStatic {
+ public:
+  // Layout and constants of the preparse data exchange format.
+  static const unsigned kMagicNumber = 0xBadDead;
+  static const unsigned kCurrentVersion = 5;
+
+  static const int kMagicOffset = 0;
+  static const int kVersionOffset = 1;
+  static const int kHasErrorOffset = 2;
+  static const int kFunctionsSizeOffset = 3;
+  static const int kSymbolCountOffset = 4;
+  static const int kSizeOffset = 5;
+  static const int kHeaderSize = 6;
+
+  // If encoding a message, the following positions are fixed.
+  static const int kMessageStartPos = 0;
+  static const int kMessageEndPos = 1;
+  static const int kMessageArgCountPos = 2;
+  static const int kMessageTextPos = 3;
+
+  static const byte kNumberTerminator = 0x80u;
+};
+
+
+// ----------------------------------------------------------------------------
+// ParserRecorder - Logging of preparser data.
+
+// Abstract interface for preparse data recorder.
+class ParserRecorder {
+ public:
+  ParserRecorder() { }
+  virtual ~ParserRecorder() { }
+
+  // Logs the scope and some details of a function literal in the source.
+  virtual void LogFunction(int start,
+                           int end,
+                           int literals,
+                           int properties) = 0;
+
+  // Logs a symbol creation of a literal or identifier.
+  virtual void LogSymbol(int start, const char* symbol, int length) = 0;
+
+  // Logs an error message and marks the log as containing an error.
+  // Further logging will be ignored, and ExtractData will return a vector
+  // representing the error only.
+  virtual void LogMessage(int start,
+                          int end,
+                          const char* message,
+                          const char* argument_opt) = 0;
+
+  virtual int function_position() = 0;
+
+  virtual int symbol_position() = 0;
+
+  virtual int symbol_ids() = 0;
+
+  virtual Vector<unsigned> ExtractData() = 0;
+
+  virtual void PauseRecording() = 0;
+
+  virtual void ResumeRecording() = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+// FunctionLoggingParserRecorder - Record only function entries
+
+class FunctionLoggingParserRecorder : public ParserRecorder {
+ public:
+  FunctionLoggingParserRecorder();
+  virtual ~FunctionLoggingParserRecorder() {}
+
+  virtual void LogFunction(int start, int end, int literals, int properties) {
+    function_store_.Add(start);
+    function_store_.Add(end);
+    function_store_.Add(literals);
+    function_store_.Add(properties);
+  }
+
+  // Logs an error message and marks the log as containing an error.
+  // Further logging will be ignored, and ExtractData will return a vector
+  // representing the error only.
+  virtual void LogMessage(int start,
+                          int end,
+                          const char* message,
+                          const char* argument_opt);
+
+  virtual int function_position() { return function_store_.size(); }
+
+
+  virtual Vector<unsigned> ExtractData() = 0;
+
+  virtual void PauseRecording() {
+    pause_count_++;
+    is_recording_ = false;
+  }
+
+  virtual void ResumeRecording() {
+    ASSERT(pause_count_ > 0);
+    if (--pause_count_ == 0) is_recording_ = !has_error();
+  }
+
+ protected:
+  bool has_error() {
+    return static_cast<bool>(preamble_[PreparseDataConstants::kHasErrorOffset]);
+  }
+
+  bool is_recording() {
+    return is_recording_;
+  }
+
+  void WriteString(Vector<const char> str);
+
+  Collector<unsigned> function_store_;
+  unsigned preamble_[PreparseDataConstants::kHeaderSize];
+  bool is_recording_;
+  int pause_count_;
+
+#ifdef DEBUG
+  int prev_start_;
+#endif
+};
+
+
+// ----------------------------------------------------------------------------
+// PartialParserRecorder - Record only function entries
+
+class PartialParserRecorder : public FunctionLoggingParserRecorder {
+ public:
+  PartialParserRecorder() : FunctionLoggingParserRecorder() { }
+  virtual void LogSymbol(int start, const char* symbol, int length) { }
+  virtual ~PartialParserRecorder() { }
+  virtual Vector<unsigned> ExtractData();
+  virtual int symbol_position() { return 0; }
+  virtual int symbol_ids() { return 0; }
+};
+
+
+// ----------------------------------------------------------------------------
+// CompleteParserRecorder -  Record both function entries and symbols.
+
+class CompleteParserRecorder: public FunctionLoggingParserRecorder {
+ public:
+  CompleteParserRecorder();
+  virtual ~CompleteParserRecorder() { }
+
+  virtual void LogSymbol(int start, const char* symbol, int length);
+
+  virtual Vector<unsigned> ExtractData();
+
+  virtual int symbol_position() { return symbol_store_.size(); }
+  virtual int symbol_ids() { return symbol_id_; }
+
+ private:
+  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;
+  }
+
+  // Write a non-negative number to the symbol store.
+  void WriteNumber(int number);
+
+  Collector<byte> symbol_store_;
+  Collector<Vector<const char> > symbol_entries_;
+  HashMap symbol_table_;
+  int symbol_id_;
+};
+
+
+} }  // namespace v8::internal.
+
+#endif  // V8_PREPARSER_DATA_H_
diff --git a/src/preparser.cc b/src/preparser.cc
new file mode 100644
index 0000000..9061731
--- /dev/null
+++ b/src/preparser.cc
@@ -0,0 +1,1184 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "../include/v8stdint.h"
+#include "unicode.h"
+#include "globals.h"
+#include "checks.h"
+#include "allocation.h"
+#include "utils.h"
+#include "list.h"
+#include "scanner-base.h"
+#include "preparse-data.h"
+#include "preparser.h"
+
+namespace v8 {
+namespace preparser {
+
+// Preparsing checks a JavaScript program and emits preparse-data that helps
+// a later parsing to be faster.
+// See preparser-data.h for the data.
+
+// The PreParser checks that the syntax follows the grammar for JavaScript,
+// and collects some information about the program along the way.
+// The grammar check is only performed in order to understand the program
+// sufficiently to deduce some information about it, that can be used
+// to speed up later parsing. Finding errors is not the goal of pre-parsing,
+// rather it is to speed up properly written and correct programs.
+// That means that contextual checks (like a label being declared where
+// it is used) are generally omitted.
+
+namespace i = ::v8::internal;
+
+#define CHECK_OK  ok);  \
+  if (!*ok) return -1;  \
+  ((void)0
+#define DUMMY )  // to make indentation work
+#undef DUMMY
+
+
+void PreParser::ReportUnexpectedToken(i::Token::Value token) {
+  // We don't report stack overflows here, to avoid increasing the
+  // stack depth even further.  Instead we report it after parsing is
+  // over, in ParseProgram.
+  if (token == i::Token::ILLEGAL && scanner_->stack_overflow()) {
+    return;
+  }
+  i::JavaScriptScanner::Location source_location = scanner_->location();
+
+  // Four of the tokens are treated specially
+  switch (token) {
+  case i::Token::EOS:
+    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
+                           "unexpected_eos", NULL);
+  case i::Token::NUMBER:
+    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
+                           "unexpected_token_number", NULL);
+  case i::Token::STRING:
+    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
+                           "unexpected_token_string", NULL);
+  case i::Token::IDENTIFIER:
+    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
+                           "unexpected_token_identifier", NULL);
+  default:
+    const char* name = i::Token::String(token);
+    ReportMessageAt(source_location.beg_pos, source_location.end_pos,
+                    "unexpected_token", name);
+  }
+}
+
+
+SourceElements PreParser::ParseSourceElements(int end_token,
+                                                            bool* ok) {
+  // SourceElements ::
+  //   (Statement)* <end_token>
+
+  while (peek() != end_token) {
+    ParseStatement(CHECK_OK);
+  }
+  return kUnknownSourceElements;
+}
+
+
+Statement PreParser::ParseStatement(bool* ok) {
+  // Statement ::
+  //   Block
+  //   VariableStatement
+  //   EmptyStatement
+  //   ExpressionStatement
+  //   IfStatement
+  //   IterationStatement
+  //   ContinueStatement
+  //   BreakStatement
+  //   ReturnStatement
+  //   WithStatement
+  //   LabelledStatement
+  //   SwitchStatement
+  //   ThrowStatement
+  //   TryStatement
+  //   DebuggerStatement
+
+  // Note: Since labels can only be used by 'break' and 'continue'
+  // statements, which themselves are only valid within blocks,
+  // iterations or 'switch' statements (i.e., BreakableStatements),
+  // labels can be simply ignored in all other cases; except for
+  // trivial labeled break statements 'label: break label' which is
+  // parsed into an empty statement.
+
+  // Keep the source position of the statement
+  switch (peek()) {
+    case i::Token::LBRACE:
+      return ParseBlock(ok);
+
+    case i::Token::CONST:
+    case i::Token::VAR:
+      return ParseVariableStatement(ok);
+
+    case i::Token::SEMICOLON:
+      Next();
+      return kUnknownStatement;
+
+    case i::Token::IF:
+      return  ParseIfStatement(ok);
+
+    case i::Token::DO:
+      return ParseDoWhileStatement(ok);
+
+    case i::Token::WHILE:
+      return ParseWhileStatement(ok);
+
+    case i::Token::FOR:
+      return ParseForStatement(ok);
+
+    case i::Token::CONTINUE:
+      return ParseContinueStatement(ok);
+
+    case i::Token::BREAK:
+      return ParseBreakStatement(ok);
+
+    case i::Token::RETURN:
+      return ParseReturnStatement(ok);
+
+    case i::Token::WITH:
+      return ParseWithStatement(ok);
+
+    case i::Token::SWITCH:
+      return ParseSwitchStatement(ok);
+
+    case i::Token::THROW:
+      return ParseThrowStatement(ok);
+
+    case i::Token::TRY:
+      return ParseTryStatement(ok);
+
+    case i::Token::FUNCTION:
+      return ParseFunctionDeclaration(ok);
+
+    case i::Token::NATIVE:
+      return ParseNativeDeclaration(ok);
+
+    case i::Token::DEBUGGER:
+      return ParseDebuggerStatement(ok);
+
+    default:
+      return ParseExpressionOrLabelledStatement(ok);
+  }
+}
+
+
+Statement PreParser::ParseFunctionDeclaration(bool* ok) {
+  // FunctionDeclaration ::
+  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
+  Expect(i::Token::FUNCTION, CHECK_OK);
+  ParseIdentifier(CHECK_OK);
+  ParseFunctionLiteral(CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+// Language extension which is only enabled for source files loaded
+// through the API's extension mechanism.  A native function
+// declaration is resolved by looking up the function through a
+// callback provided by the extension.
+Statement PreParser::ParseNativeDeclaration(bool* ok) {
+  Expect(i::Token::NATIVE, CHECK_OK);
+  Expect(i::Token::FUNCTION, CHECK_OK);
+  ParseIdentifier(CHECK_OK);
+  Expect(i::Token::LPAREN, CHECK_OK);
+  bool done = (peek() == i::Token::RPAREN);
+  while (!done) {
+    ParseIdentifier(CHECK_OK);
+    done = (peek() == i::Token::RPAREN);
+    if (!done) {
+      Expect(i::Token::COMMA, CHECK_OK);
+    }
+  }
+  Expect(i::Token::RPAREN, CHECK_OK);
+  Expect(i::Token::SEMICOLON, CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseBlock(bool* ok) {
+  // Block ::
+  //   '{' Statement* '}'
+
+  // Note that a Block does not introduce a new execution scope!
+  // (ECMA-262, 3rd, 12.2)
+  //
+  Expect(i::Token::LBRACE, CHECK_OK);
+  while (peek() != i::Token::RBRACE) {
+    ParseStatement(CHECK_OK);
+  }
+  Expect(i::Token::RBRACE, CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseVariableStatement(bool* ok) {
+  // VariableStatement ::
+  //   VariableDeclarations ';'
+
+  Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+  return result;
+}
+
+
+// If the variable declaration declares exactly one non-const
+// variable, then *var is set to that variable. In all other cases,
+// *var is untouched; in particular, it is the caller's responsibility
+// to initialize it properly. This mechanism is also used for the parsing
+// of 'for-in' loops.
+Statement PreParser::ParseVariableDeclarations(bool accept_IN,
+                                                  int* num_decl,
+                                                  bool* ok) {
+  // VariableDeclarations ::
+  //   ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
+
+  if (peek() == i::Token::VAR) {
+    Consume(i::Token::VAR);
+  } else if (peek() == i::Token::CONST) {
+    Consume(i::Token::CONST);
+  } else {
+    *ok = false;
+    return 0;
+  }
+
+  // The scope of a variable/const declared anywhere inside a function
+  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). .
+  int nvars = 0;  // the number of variables declared
+  do {
+    // Parse variable name.
+    if (nvars > 0) Consume(i::Token::COMMA);
+    ParseIdentifier(CHECK_OK);
+    nvars++;
+    if (peek() == i::Token::ASSIGN) {
+      Expect(i::Token::ASSIGN, CHECK_OK);
+      ParseAssignmentExpression(accept_IN, CHECK_OK);
+    }
+  } while (peek() == i::Token::COMMA);
+
+  if (num_decl != NULL) *num_decl = nvars;
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseExpressionOrLabelledStatement(
+    bool* ok) {
+  // ExpressionStatement | LabelledStatement ::
+  //   Expression ';'
+  //   Identifier ':' Statement
+
+  Expression expr = ParseExpression(true, CHECK_OK);
+  if (peek() == i::Token::COLON && expr == kIdentifierExpression) {
+    Consume(i::Token::COLON);
+    return ParseStatement(ok);
+  }
+  // Parsed expression statement.
+  ExpectSemicolon(CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseIfStatement(bool* ok) {
+  // IfStatement ::
+  //   'if' '(' Expression ')' Statement ('else' Statement)?
+
+  Expect(i::Token::IF, CHECK_OK);
+  Expect(i::Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(i::Token::RPAREN, CHECK_OK);
+  ParseStatement(CHECK_OK);
+  if (peek() == i::Token::ELSE) {
+    Next();
+    ParseStatement(CHECK_OK);
+  }
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseContinueStatement(bool* ok) {
+  // ContinueStatement ::
+  //   'continue' [no line terminator] Identifier? ';'
+
+  Expect(i::Token::CONTINUE, CHECK_OK);
+  i::Token::Value tok = peek();
+  if (!scanner_->has_line_terminator_before_next() &&
+      tok != i::Token::SEMICOLON &&
+      tok != i::Token::RBRACE &&
+      tok != i::Token::EOS) {
+    ParseIdentifier(CHECK_OK);
+  }
+  ExpectSemicolon(CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseBreakStatement(bool* ok) {
+  // BreakStatement ::
+  //   'break' [no line terminator] Identifier? ';'
+
+  Expect(i::Token::BREAK, CHECK_OK);
+  i::Token::Value tok = peek();
+  if (!scanner_->has_line_terminator_before_next() &&
+      tok != i::Token::SEMICOLON &&
+      tok != i::Token::RBRACE &&
+      tok != i::Token::EOS) {
+    ParseIdentifier(CHECK_OK);
+  }
+  ExpectSemicolon(CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseReturnStatement(bool* ok) {
+  // ReturnStatement ::
+  //   'return' [no line terminator] Expression? ';'
+
+  // Consume the return token. It is necessary to do the before
+  // reporting any errors on it, because of the way errors are
+  // reported (underlining).
+  Expect(i::Token::RETURN, CHECK_OK);
+
+  // An ECMAScript program is considered syntactically incorrect if it
+  // contains a return statement that is not within the body of a
+  // function. See ECMA-262, section 12.9, page 67.
+  // This is not handled during preparsing.
+
+  i::Token::Value tok = peek();
+  if (!scanner_->has_line_terminator_before_next() &&
+      tok != i::Token::SEMICOLON &&
+      tok != i::Token::RBRACE &&
+      tok != i::Token::EOS) {
+    ParseExpression(true, CHECK_OK);
+  }
+  ExpectSemicolon(CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseWithStatement(bool* ok) {
+  // WithStatement ::
+  //   'with' '(' Expression ')' Statement
+  Expect(i::Token::WITH, CHECK_OK);
+  Expect(i::Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(i::Token::RPAREN, CHECK_OK);
+
+  scope_->EnterWith();
+  ParseStatement(CHECK_OK);
+  scope_->LeaveWith();
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseSwitchStatement(bool* ok) {
+  // SwitchStatement ::
+  //   'switch' '(' Expression ')' '{' CaseClause* '}'
+
+  Expect(i::Token::SWITCH, CHECK_OK);
+  Expect(i::Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(i::Token::RPAREN, CHECK_OK);
+
+  Expect(i::Token::LBRACE, CHECK_OK);
+  i::Token::Value token = peek();
+  while (token != i::Token::RBRACE) {
+    if (token == i::Token::CASE) {
+      Expect(i::Token::CASE, CHECK_OK);
+      ParseExpression(true, CHECK_OK);
+      Expect(i::Token::COLON, CHECK_OK);
+    } else if (token == i::Token::DEFAULT) {
+      Expect(i::Token::DEFAULT, CHECK_OK);
+      Expect(i::Token::COLON, CHECK_OK);
+    } else {
+      ParseStatement(CHECK_OK);
+    }
+    token = peek();
+  }
+  Expect(i::Token::RBRACE, CHECK_OK);
+
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseDoWhileStatement(bool* ok) {
+  // DoStatement ::
+  //   'do' Statement 'while' '(' Expression ')' ';'
+
+  Expect(i::Token::DO, CHECK_OK);
+  ParseStatement(CHECK_OK);
+  Expect(i::Token::WHILE, CHECK_OK);
+  Expect(i::Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(i::Token::RPAREN, CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseWhileStatement(bool* ok) {
+  // WhileStatement ::
+  //   'while' '(' Expression ')' Statement
+
+  Expect(i::Token::WHILE, CHECK_OK);
+  Expect(i::Token::LPAREN, CHECK_OK);
+  ParseExpression(true, CHECK_OK);
+  Expect(i::Token::RPAREN, CHECK_OK);
+  ParseStatement(CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseForStatement(bool* ok) {
+  // ForStatement ::
+  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
+
+  Expect(i::Token::FOR, CHECK_OK);
+  Expect(i::Token::LPAREN, CHECK_OK);
+  if (peek() != i::Token::SEMICOLON) {
+    if (peek() == i::Token::VAR || peek() == i::Token::CONST) {
+      int decl_count;
+      ParseVariableDeclarations(false, &decl_count, CHECK_OK);
+      if (peek() == i::Token::IN && decl_count == 1) {
+        Expect(i::Token::IN, CHECK_OK);
+        ParseExpression(true, CHECK_OK);
+        Expect(i::Token::RPAREN, CHECK_OK);
+
+        ParseStatement(CHECK_OK);
+        return kUnknownStatement;
+      }
+    } else {
+      ParseExpression(false, CHECK_OK);
+      if (peek() == i::Token::IN) {
+        Expect(i::Token::IN, CHECK_OK);
+        ParseExpression(true, CHECK_OK);
+        Expect(i::Token::RPAREN, CHECK_OK);
+
+        ParseStatement(CHECK_OK);
+        return kUnknownStatement;
+      }
+    }
+  }
+
+  // Parsed initializer at this point.
+  Expect(i::Token::SEMICOLON, CHECK_OK);
+
+  if (peek() != i::Token::SEMICOLON) {
+    ParseExpression(true, CHECK_OK);
+  }
+  Expect(i::Token::SEMICOLON, CHECK_OK);
+
+  if (peek() != i::Token::RPAREN) {
+    ParseExpression(true, CHECK_OK);
+  }
+  Expect(i::Token::RPAREN, CHECK_OK);
+
+  ParseStatement(CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseThrowStatement(bool* ok) {
+  // ThrowStatement ::
+  //   'throw' [no line terminator] Expression ';'
+
+  Expect(i::Token::THROW, CHECK_OK);
+  if (scanner_->has_line_terminator_before_next()) {
+    i::JavaScriptScanner::Location pos = scanner_->location();
+    ReportMessageAt(pos.beg_pos, pos.end_pos,
+                    "newline_after_throw", NULL);
+    *ok = false;
+    return kUnknownStatement;
+  }
+  ParseExpression(true, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseTryStatement(bool* ok) {
+  // TryStatement ::
+  //   'try' Block Catch
+  //   'try' Block Finally
+  //   'try' Block Catch Finally
+  //
+  // Catch ::
+  //   'catch' '(' Identifier ')' Block
+  //
+  // Finally ::
+  //   'finally' Block
+
+  // In preparsing, allow any number of catch/finally blocks, including zero
+  // of both.
+
+  Expect(i::Token::TRY, CHECK_OK);
+
+  ParseBlock(CHECK_OK);
+
+  bool catch_or_finally_seen = false;
+  if (peek() == i::Token::CATCH) {
+    Consume(i::Token::CATCH);
+    Expect(i::Token::LPAREN, CHECK_OK);
+    ParseIdentifier(CHECK_OK);
+    Expect(i::Token::RPAREN, CHECK_OK);
+    scope_->EnterWith();
+    ParseBlock(ok);
+    scope_->LeaveWith();
+    if (!*ok) return kUnknownStatement;
+    catch_or_finally_seen = true;
+  }
+  if (peek() == i::Token::FINALLY) {
+    Consume(i::Token::FINALLY);
+    ParseBlock(CHECK_OK);
+    catch_or_finally_seen = true;
+  }
+  if (!catch_or_finally_seen) {
+    *ok = false;
+  }
+  return kUnknownStatement;
+}
+
+
+Statement PreParser::ParseDebuggerStatement(bool* ok) {
+  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
+  // contexts this is used as a statement which invokes the debugger as if a
+  // break point is present.
+  // DebuggerStatement ::
+  //   'debugger' ';'
+
+  Expect(i::Token::DEBUGGER, CHECK_OK);
+  ExpectSemicolon(CHECK_OK);
+  return kUnknownStatement;
+}
+
+
+// Precedence = 1
+Expression PreParser::ParseExpression(bool accept_IN, bool* ok) {
+  // Expression ::
+  //   AssignmentExpression
+  //   Expression ',' AssignmentExpression
+
+  Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
+  while (peek() == i::Token::COMMA) {
+    Expect(i::Token::COMMA, CHECK_OK);
+    ParseAssignmentExpression(accept_IN, CHECK_OK);
+    result = kUnknownExpression;
+  }
+  return result;
+}
+
+
+// Precedence = 2
+Expression PreParser::ParseAssignmentExpression(bool accept_IN,
+                                                              bool* ok) {
+  // AssignmentExpression ::
+  //   ConditionalExpression
+  //   LeftHandSideExpression AssignmentOperator AssignmentExpression
+
+  Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
+
+  if (!i::Token::IsAssignmentOp(peek())) {
+    // Parsed conditional expression only (no assignment).
+    return expression;
+  }
+
+  i::Token::Value op = Next();  // Get assignment operator.
+  ParseAssignmentExpression(accept_IN, CHECK_OK);
+
+  if ((op == i::Token::ASSIGN) && (expression == kThisPropertyExpression)) {
+    scope_->AddProperty();
+  }
+
+  return kUnknownExpression;
+}
+
+
+// Precedence = 3
+Expression PreParser::ParseConditionalExpression(bool accept_IN,
+                                                               bool* ok) {
+  // ConditionalExpression ::
+  //   LogicalOrExpression
+  //   LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
+
+  // We start using the binary expression parser for prec >= 4 only!
+  Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
+  if (peek() != i::Token::CONDITIONAL) return expression;
+  Consume(i::Token::CONDITIONAL);
+  // In parsing the first assignment expression in conditional
+  // expressions we always accept the 'in' keyword; see ECMA-262,
+  // section 11.12, page 58.
+  ParseAssignmentExpression(true, CHECK_OK);
+  Expect(i::Token::COLON, CHECK_OK);
+  ParseAssignmentExpression(accept_IN, CHECK_OK);
+  return kUnknownExpression;
+}
+
+
+int PreParser::Precedence(i::Token::Value tok, bool accept_IN) {
+  if (tok == i::Token::IN && !accept_IN)
+    return 0;  // 0 precedence will terminate binary expression parsing
+
+  return i::Token::Precedence(tok);
+}
+
+
+// Precedence >= 4
+Expression PreParser::ParseBinaryExpression(int prec,
+                                                          bool accept_IN,
+                                                          bool* ok) {
+  Expression result = ParseUnaryExpression(CHECK_OK);
+  for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
+    // prec1 >= 4
+    while (Precedence(peek(), accept_IN) == prec1) {
+      Next();
+      ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
+      result = kUnknownExpression;
+    }
+  }
+  return result;
+}
+
+
+Expression PreParser::ParseUnaryExpression(bool* ok) {
+  // UnaryExpression ::
+  //   PostfixExpression
+  //   'delete' UnaryExpression
+  //   'void' UnaryExpression
+  //   'typeof' UnaryExpression
+  //   '++' UnaryExpression
+  //   '--' UnaryExpression
+  //   '+' UnaryExpression
+  //   '-' UnaryExpression
+  //   '~' UnaryExpression
+  //   '!' UnaryExpression
+
+  i::Token::Value op = peek();
+  if (i::Token::IsUnaryOp(op) || i::Token::IsCountOp(op)) {
+    op = Next();
+    ParseUnaryExpression(ok);
+    return kUnknownExpression;
+  } else {
+    return ParsePostfixExpression(ok);
+  }
+}
+
+
+Expression PreParser::ParsePostfixExpression(bool* ok) {
+  // PostfixExpression ::
+  //   LeftHandSideExpression ('++' | '--')?
+
+  Expression expression = ParseLeftHandSideExpression(CHECK_OK);
+  if (!scanner_->has_line_terminator_before_next() &&
+      i::Token::IsCountOp(peek())) {
+    Next();
+    return kUnknownExpression;
+  }
+  return expression;
+}
+
+
+Expression PreParser::ParseLeftHandSideExpression(bool* ok) {
+  // LeftHandSideExpression ::
+  //   (NewExpression | MemberExpression) ...
+
+  Expression result;
+  if (peek() == i::Token::NEW) {
+    result = ParseNewExpression(CHECK_OK);
+  } else {
+    result = ParseMemberExpression(CHECK_OK);
+  }
+
+  while (true) {
+    switch (peek()) {
+      case i::Token::LBRACK: {
+        Consume(i::Token::LBRACK);
+        ParseExpression(true, CHECK_OK);
+        Expect(i::Token::RBRACK, CHECK_OK);
+        if (result == kThisExpression) {
+          result = kThisPropertyExpression;
+        } else {
+          result = kUnknownExpression;
+        }
+        break;
+      }
+
+      case i::Token::LPAREN: {
+        ParseArguments(CHECK_OK);
+        result = kUnknownExpression;
+        break;
+      }
+
+      case i::Token::PERIOD: {
+        Consume(i::Token::PERIOD);
+        ParseIdentifierName(CHECK_OK);
+        if (result == kThisExpression) {
+          result = kThisPropertyExpression;
+        } else {
+          result = kUnknownExpression;
+        }
+        break;
+      }
+
+      default:
+        return result;
+    }
+  }
+}
+
+
+Expression PreParser::ParseNewExpression(bool* ok) {
+  // NewExpression ::
+  //   ('new')+ MemberExpression
+
+  // The grammar for new expressions is pretty warped. The keyword
+  // 'new' can either be a part of the new expression (where it isn't
+  // followed by an argument list) or a part of the member expression,
+  // where it must be followed by an argument list. To accommodate
+  // this, we parse the 'new' keywords greedily and keep track of how
+  // many we have parsed. This information is then passed on to the
+  // member expression parser, which is only allowed to match argument
+  // lists as long as it has 'new' prefixes left
+  unsigned new_count = 0;
+  do {
+    Consume(i::Token::NEW);
+    new_count++;
+  } while (peek() == i::Token::NEW);
+
+  return ParseMemberWithNewPrefixesExpression(new_count, ok);
+}
+
+
+Expression PreParser::ParseMemberExpression(bool* ok) {
+  return ParseMemberWithNewPrefixesExpression(0, ok);
+}
+
+
+Expression PreParser::ParseMemberWithNewPrefixesExpression(
+    unsigned new_count, bool* ok) {
+  // MemberExpression ::
+  //   (PrimaryExpression | FunctionLiteral)
+  //     ('[' Expression ']' | '.' Identifier | Arguments)*
+
+  // Parse the initial primary or function expression.
+  Expression result = kUnknownExpression;
+  if (peek() == i::Token::FUNCTION) {
+    Consume(i::Token::FUNCTION);
+    if (peek() == i::Token::IDENTIFIER) {
+      ParseIdentifier(CHECK_OK);
+    }
+    result = ParseFunctionLiteral(CHECK_OK);
+  } else {
+    result = ParsePrimaryExpression(CHECK_OK);
+  }
+
+  while (true) {
+    switch (peek()) {
+      case i::Token::LBRACK: {
+        Consume(i::Token::LBRACK);
+        ParseExpression(true, CHECK_OK);
+        Expect(i::Token::RBRACK, CHECK_OK);
+        if (result == kThisExpression) {
+          result = kThisPropertyExpression;
+        } else {
+          result = kUnknownExpression;
+        }
+        break;
+      }
+      case i::Token::PERIOD: {
+        Consume(i::Token::PERIOD);
+        ParseIdentifierName(CHECK_OK);
+        if (result == kThisExpression) {
+          result = kThisPropertyExpression;
+        } else {
+          result = kUnknownExpression;
+        }
+        break;
+      }
+      case i::Token::LPAREN: {
+        if (new_count == 0) return result;
+        // Consume one of the new prefixes (already parsed).
+        ParseArguments(CHECK_OK);
+        new_count--;
+        result = kUnknownExpression;
+        break;
+      }
+      default:
+        return result;
+    }
+  }
+}
+
+
+Expression PreParser::ParsePrimaryExpression(bool* ok) {
+  // PrimaryExpression ::
+  //   'this'
+  //   'null'
+  //   'true'
+  //   'false'
+  //   Identifier
+  //   Number
+  //   String
+  //   ArrayLiteral
+  //   ObjectLiteral
+  //   RegExpLiteral
+  //   '(' Expression ')'
+
+  Expression result = kUnknownExpression;
+  switch (peek()) {
+    case i::Token::THIS: {
+      Next();
+      result = kThisExpression;
+      break;
+    }
+
+    case i::Token::IDENTIFIER: {
+      ParseIdentifier(CHECK_OK);
+      result = kIdentifierExpression;
+      break;
+    }
+
+    case i::Token::NULL_LITERAL:
+    case i::Token::TRUE_LITERAL:
+    case i::Token::FALSE_LITERAL:
+    case i::Token::NUMBER: {
+      Next();
+      break;
+    }
+    case i::Token::STRING: {
+      Next();
+      result = GetStringSymbol();
+      break;
+    }
+
+    case i::Token::ASSIGN_DIV:
+      result = ParseRegExpLiteral(true, CHECK_OK);
+      break;
+
+    case i::Token::DIV:
+      result = ParseRegExpLiteral(false, CHECK_OK);
+      break;
+
+    case i::Token::LBRACK:
+      result = ParseArrayLiteral(CHECK_OK);
+      break;
+
+    case i::Token::LBRACE:
+      result = ParseObjectLiteral(CHECK_OK);
+      break;
+
+    case i::Token::LPAREN:
+      Consume(i::Token::LPAREN);
+      result = ParseExpression(true, CHECK_OK);
+      Expect(i::Token::RPAREN, CHECK_OK);
+      if (result == kIdentifierExpression) result = kUnknownExpression;
+      break;
+
+    case i::Token::MOD:
+      result = ParseV8Intrinsic(CHECK_OK);
+      break;
+
+    default: {
+      Next();
+      *ok = false;
+      return kUnknownExpression;
+    }
+  }
+
+  return result;
+}
+
+
+Expression PreParser::ParseArrayLiteral(bool* ok) {
+  // ArrayLiteral ::
+  //   '[' Expression? (',' Expression?)* ']'
+  Expect(i::Token::LBRACK, CHECK_OK);
+  while (peek() != i::Token::RBRACK) {
+    if (peek() != i::Token::COMMA) {
+      ParseAssignmentExpression(true, CHECK_OK);
+    }
+    if (peek() != i::Token::RBRACK) {
+      Expect(i::Token::COMMA, CHECK_OK);
+    }
+  }
+  Expect(i::Token::RBRACK, CHECK_OK);
+
+  scope_->NextMaterializedLiteralIndex();
+  return kUnknownExpression;
+}
+
+
+Expression PreParser::ParseObjectLiteral(bool* ok) {
+  // ObjectLiteral ::
+  //   '{' (
+  //       ((IdentifierName | String | Number) ':' AssignmentExpression)
+  //     | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
+  //    )*[','] '}'
+
+  Expect(i::Token::LBRACE, CHECK_OK);
+  while (peek() != i::Token::RBRACE) {
+    i::Token::Value next = peek();
+    switch (next) {
+      case i::Token::IDENTIFIER: {
+        bool is_getter = false;
+        bool is_setter = false;
+        ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
+        if ((is_getter || is_setter) && peek() != i::Token::COLON) {
+            i::Token::Value name = Next();
+            if (name != i::Token::IDENTIFIER &&
+                name != i::Token::NUMBER &&
+                name != i::Token::STRING &&
+                !i::Token::IsKeyword(name)) {
+              *ok = false;
+              return kUnknownExpression;
+            }
+            ParseFunctionLiteral(CHECK_OK);
+            if (peek() != i::Token::RBRACE) {
+              Expect(i::Token::COMMA, CHECK_OK);
+            }
+            continue;  // restart the while
+        }
+        break;
+      }
+      case i::Token::STRING:
+        Consume(next);
+        GetStringSymbol();
+        break;
+      case i::Token::NUMBER:
+        Consume(next);
+        break;
+      default:
+        if (i::Token::IsKeyword(next)) {
+          Consume(next);
+        } else {
+          // Unexpected token.
+          *ok = false;
+          return kUnknownExpression;
+        }
+    }
+
+    Expect(i::Token::COLON, CHECK_OK);
+    ParseAssignmentExpression(true, CHECK_OK);
+
+    // TODO(1240767): Consider allowing trailing comma.
+    if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
+  }
+  Expect(i::Token::RBRACE, CHECK_OK);
+
+  scope_->NextMaterializedLiteralIndex();
+  return kUnknownExpression;
+}
+
+
+Expression PreParser::ParseRegExpLiteral(bool seen_equal,
+                                         bool* ok) {
+  if (!scanner_->ScanRegExpPattern(seen_equal)) {
+    Next();
+    i::JavaScriptScanner::Location location = scanner_->location();
+    ReportMessageAt(location.beg_pos, location.end_pos,
+                    "unterminated_regexp", NULL);
+    *ok = false;
+    return kUnknownExpression;
+  }
+
+  scope_->NextMaterializedLiteralIndex();
+
+  if (!scanner_->ScanRegExpFlags()) {
+    Next();
+    i::JavaScriptScanner::Location location = scanner_->location();
+    ReportMessageAt(location.beg_pos, location.end_pos,
+                    "invalid_regexp_flags", NULL);
+    *ok = false;
+    return kUnknownExpression;
+  }
+  Next();
+  return kUnknownExpression;
+}
+
+
+Arguments PreParser::ParseArguments(bool* ok) {
+  // Arguments ::
+  //   '(' (AssignmentExpression)*[','] ')'
+
+  Expect(i::Token::LPAREN, CHECK_OK);
+  bool done = (peek() == i::Token::RPAREN);
+  int argc = 0;
+  while (!done) {
+    ParseAssignmentExpression(true, CHECK_OK);
+    argc++;
+    done = (peek() == i::Token::RPAREN);
+    if (!done) Expect(i::Token::COMMA, CHECK_OK);
+  }
+  Expect(i::Token::RPAREN, CHECK_OK);
+  return argc;
+}
+
+
+Expression PreParser::ParseFunctionLiteral(bool* ok) {
+  // Function ::
+  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
+
+  // Parse function body.
+  ScopeType outer_scope_type = scope_->type();
+  bool inside_with = scope_->IsInsideWith();
+  Scope function_scope(&scope_, kFunctionScope);
+
+  //  FormalParameterList ::
+  //    '(' (Identifier)*[','] ')'
+  Expect(i::Token::LPAREN, CHECK_OK);
+  bool done = (peek() == i::Token::RPAREN);
+  while (!done) {
+    ParseIdentifier(CHECK_OK);
+    done = (peek() == i::Token::RPAREN);
+    if (!done) {
+      Expect(i::Token::COMMA, CHECK_OK);
+    }
+  }
+  Expect(i::Token::RPAREN, CHECK_OK);
+
+  Expect(i::Token::LBRACE, CHECK_OK);
+  int function_block_pos = scanner_->location().beg_pos;
+
+  // Determine if the function will be lazily compiled.
+  // Currently only happens to top-level functions.
+  // Optimistically assume that all top-level functions are lazily compiled.
+  bool is_lazily_compiled =
+      (outer_scope_type == kTopLevelScope && !inside_with && allow_lazy_);
+
+  if (is_lazily_compiled) {
+    log_->PauseRecording();
+    ParseSourceElements(i::Token::RBRACE, ok);
+    log_->ResumeRecording();
+    if (!*ok) return kUnknownExpression;
+
+    Expect(i::Token::RBRACE, CHECK_OK);
+
+    int end_pos = scanner_->location().end_pos;
+    log_->LogFunction(function_block_pos, end_pos,
+                      function_scope.materialized_literal_count(),
+                      function_scope.expected_properties());
+  } else {
+    ParseSourceElements(i::Token::RBRACE, CHECK_OK);
+    Expect(i::Token::RBRACE, CHECK_OK);
+  }
+  return kUnknownExpression;
+}
+
+
+Expression PreParser::ParseV8Intrinsic(bool* ok) {
+  // CallRuntime ::
+  //   '%' Identifier Arguments
+
+  Expect(i::Token::MOD, CHECK_OK);
+  ParseIdentifier(CHECK_OK);
+  ParseArguments(CHECK_OK);
+
+  return kUnknownExpression;
+}
+
+
+void PreParser::ExpectSemicolon(bool* ok) {
+  // Check for automatic semicolon insertion according to
+  // the rules given in ECMA-262, section 7.9, page 21.
+  i::Token::Value tok = peek();
+  if (tok == i::Token::SEMICOLON) {
+    Next();
+    return;
+  }
+  if (scanner_->has_line_terminator_before_next() ||
+      tok == i::Token::RBRACE ||
+      tok == i::Token::EOS) {
+    return;
+  }
+  Expect(i::Token::SEMICOLON, ok);
+}
+
+
+Identifier PreParser::GetIdentifierSymbol() {
+  const char* literal_chars = scanner_->literal_string();
+  int literal_length = scanner_->literal_length();
+  int identifier_pos = scanner_->location().beg_pos;
+
+  log_->LogSymbol(identifier_pos, literal_chars, literal_length);
+
+  return kUnknownExpression;
+}
+
+
+Expression PreParser::GetStringSymbol() {
+  const char* literal_chars = scanner_->literal_string();
+  int literal_length = scanner_->literal_length();
+
+  int literal_position = scanner_->location().beg_pos;
+  log_->LogSymbol(literal_position, literal_chars, literal_length);
+
+  return kUnknownExpression;
+}
+
+
+Identifier PreParser::ParseIdentifier(bool* ok) {
+  Expect(i::Token::IDENTIFIER, ok);
+  if (!*ok) return kUnknownIdentifier;
+  return GetIdentifierSymbol();
+}
+
+
+Identifier PreParser::ParseIdentifierName(bool* ok) {
+  i::Token::Value next = Next();
+  if (i::Token::IsKeyword(next)) {
+    int pos = scanner_->location().beg_pos;
+    const char* keyword = i::Token::String(next);
+    log_->LogSymbol(pos, keyword, i::StrLength(keyword));
+    return kUnknownExpression;
+  }
+  if (next == i::Token::IDENTIFIER) {
+    return GetIdentifierSymbol();
+  }
+  *ok = false;
+  return kUnknownIdentifier;
+}
+
+
+// This function reads an identifier and determines whether or not it
+// is 'get' or 'set'.  The reason for not using ParseIdentifier and
+// checking on the output is that this involves heap allocation which
+// we can't do during preparsing.
+Identifier PreParser::ParseIdentifierOrGetOrSet(bool* is_get,
+                                                bool* is_set,
+                                                bool* ok) {
+  Expect(i::Token::IDENTIFIER, CHECK_OK);
+  if (scanner_->literal_length() == 3) {
+    const char* token = scanner_->literal_string();
+    *is_get = strncmp(token, "get", 3) == 0;
+    *is_set = !*is_get && strncmp(token, "set", 3) == 0;
+  }
+  return GetIdentifierSymbol();
+}
+
+#undef CHECK_OK
+} }  // v8::preparser
diff --git a/src/preparser.h b/src/preparser.h
index 8e8dfbe..b783d65 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -28,15 +28,12 @@
 #ifndef V8_PREPARSER_H
 #define V8_PREPARSER_H
 
-#include "unicode.h"
-#include "utils.h"
-
 namespace v8 {
 namespace preparser {
 
 // Preparsing checks a JavaScript program and emits preparse-data that helps
 // a later parsing to be faster.
-// See preparser-data.h for the data.
+// See preparse-data.h for the data.
 
 // The PreParser checks that the syntax follows the grammar for JavaScript,
 // and collects some information about the program along the way.
@@ -76,7 +73,6 @@
 typedef int Arguments;
 
 
-template <typename Scanner, typename PreParserLog>
 class PreParser {
  public:
   PreParser() : scope_(NULL), allow_lazy_(true) { }
@@ -86,8 +82,8 @@
   // success (even if parsing failed, the pre-parse data successfully
   // captured the syntax error), and false if a stack-overflow happened
   // during parsing.
-  bool PreParseProgram(Scanner* scanner,
-                       PreParserLog* log,
+  bool PreParseProgram(i::JavaScriptScanner* scanner,
+                       i::ParserRecorder* log,
                        bool allow_lazy) {
     allow_lazy_ = allow_lazy;
     scanner_ = scanner;
@@ -235,1185 +231,11 @@
 
   static int Precedence(i::Token::Value tok, bool accept_IN);
 
-  Scanner* scanner_;
-  PreParserLog* log_;
+  i::JavaScriptScanner* scanner_;
+  i::ParserRecorder* log_;
   Scope* scope_;
   bool allow_lazy_;
 };
-
-
-#define CHECK_OK  ok);  \
-  if (!*ok) return -1;  \
-  ((void)0
-#define DUMMY )  // to make indentation work
-#undef DUMMY
-
-
-template <typename Scanner, typename Log>
-void PreParser<Scanner, Log>::ReportUnexpectedToken(i::Token::Value token) {
-  // We don't report stack overflows here, to avoid increasing the
-  // stack depth even further.  Instead we report it after parsing is
-  // over, in ParseProgram.
-  if (token == i::Token::ILLEGAL && scanner_->stack_overflow()) {
-    return;
-  }
-  typename Scanner::Location source_location = scanner_->location();
-
-  // Four of the tokens are treated specially
-  switch (token) {
-  case i::Token::EOS:
-    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
-                           "unexpected_eos", NULL);
-  case i::Token::NUMBER:
-    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
-                           "unexpected_token_number", NULL);
-  case i::Token::STRING:
-    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
-                           "unexpected_token_string", NULL);
-  case i::Token::IDENTIFIER:
-    return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
-                           "unexpected_token_identifier", NULL);
-  default:
-    const char* name = i::Token::String(token);
-    ReportMessageAt(source_location.beg_pos, source_location.end_pos,
-                    "unexpected_token", name);
-  }
-}
-
-
-template <typename Scanner, typename Log>
-SourceElements PreParser<Scanner, Log>::ParseSourceElements(int end_token,
-                                                            bool* ok) {
-  // SourceElements ::
-  //   (Statement)* <end_token>
-
-  while (peek() != end_token) {
-    ParseStatement(CHECK_OK);
-  }
-  return kUnknownSourceElements;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseStatement(bool* ok) {
-  // Statement ::
-  //   Block
-  //   VariableStatement
-  //   EmptyStatement
-  //   ExpressionStatement
-  //   IfStatement
-  //   IterationStatement
-  //   ContinueStatement
-  //   BreakStatement
-  //   ReturnStatement
-  //   WithStatement
-  //   LabelledStatement
-  //   SwitchStatement
-  //   ThrowStatement
-  //   TryStatement
-  //   DebuggerStatement
-
-  // Note: Since labels can only be used by 'break' and 'continue'
-  // statements, which themselves are only valid within blocks,
-  // iterations or 'switch' statements (i.e., BreakableStatements),
-  // labels can be simply ignored in all other cases; except for
-  // trivial labeled break statements 'label: break label' which is
-  // parsed into an empty statement.
-
-  // Keep the source position of the statement
-  switch (peek()) {
-    case i::Token::LBRACE:
-      return ParseBlock(ok);
-
-    case i::Token::CONST:
-    case i::Token::VAR:
-      return ParseVariableStatement(ok);
-
-    case i::Token::SEMICOLON:
-      Next();
-      return kUnknownStatement;
-
-    case i::Token::IF:
-      return  ParseIfStatement(ok);
-
-    case i::Token::DO:
-      return ParseDoWhileStatement(ok);
-
-    case i::Token::WHILE:
-      return ParseWhileStatement(ok);
-
-    case i::Token::FOR:
-      return ParseForStatement(ok);
-
-    case i::Token::CONTINUE:
-      return ParseContinueStatement(ok);
-
-    case i::Token::BREAK:
-      return ParseBreakStatement(ok);
-
-    case i::Token::RETURN:
-      return ParseReturnStatement(ok);
-
-    case i::Token::WITH:
-      return ParseWithStatement(ok);
-
-    case i::Token::SWITCH:
-      return ParseSwitchStatement(ok);
-
-    case i::Token::THROW:
-      return ParseThrowStatement(ok);
-
-    case i::Token::TRY:
-      return ParseTryStatement(ok);
-
-    case i::Token::FUNCTION:
-      return ParseFunctionDeclaration(ok);
-
-    case i::Token::NATIVE:
-      return ParseNativeDeclaration(ok);
-
-    case i::Token::DEBUGGER:
-      return ParseDebuggerStatement(ok);
-
-    default:
-      return ParseExpressionOrLabelledStatement(ok);
-  }
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseFunctionDeclaration(bool* ok) {
-  // FunctionDeclaration ::
-  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
-  Expect(i::Token::FUNCTION, CHECK_OK);
-  ParseIdentifier(CHECK_OK);
-  ParseFunctionLiteral(CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-// Language extension which is only enabled for source files loaded
-// through the API's extension mechanism.  A native function
-// declaration is resolved by looking up the function through a
-// callback provided by the extension.
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseNativeDeclaration(bool* ok) {
-  Expect(i::Token::NATIVE, CHECK_OK);
-  Expect(i::Token::FUNCTION, CHECK_OK);
-  ParseIdentifier(CHECK_OK);
-  Expect(i::Token::LPAREN, CHECK_OK);
-  bool done = (peek() == i::Token::RPAREN);
-  while (!done) {
-    ParseIdentifier(CHECK_OK);
-    done = (peek() == i::Token::RPAREN);
-    if (!done) {
-      Expect(i::Token::COMMA, CHECK_OK);
-    }
-  }
-  Expect(i::Token::RPAREN, CHECK_OK);
-  Expect(i::Token::SEMICOLON, CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseBlock(bool* ok) {
-  // Block ::
-  //   '{' Statement* '}'
-
-  // Note that a Block does not introduce a new execution scope!
-  // (ECMA-262, 3rd, 12.2)
-  //
-  Expect(i::Token::LBRACE, CHECK_OK);
-  while (peek() != i::Token::RBRACE) {
-    ParseStatement(CHECK_OK);
-  }
-  Expect(i::Token::RBRACE, CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseVariableStatement(bool* ok) {
-  // VariableStatement ::
-  //   VariableDeclarations ';'
-
-  Statement result = ParseVariableDeclarations(true, NULL, CHECK_OK);
-  ExpectSemicolon(CHECK_OK);
-  return result;
-}
-
-
-// If the variable declaration declares exactly one non-const
-// variable, then *var is set to that variable. In all other cases,
-// *var is untouched; in particular, it is the caller's responsibility
-// to initialize it properly. This mechanism is also used for the parsing
-// of 'for-in' loops.
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseVariableDeclarations(bool accept_IN,
-                                                  int* num_decl,
-                                                  bool* ok) {
-  // VariableDeclarations ::
-  //   ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
-
-  if (peek() == i::Token::VAR) {
-    Consume(i::Token::VAR);
-  } else if (peek() == i::Token::CONST) {
-    Consume(i::Token::CONST);
-  } else {
-    *ok = false;
-    return 0;
-  }
-
-  // The scope of a variable/const declared anywhere inside a function
-  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). .
-  int nvars = 0;  // the number of variables declared
-  do {
-    // Parse variable name.
-    if (nvars > 0) Consume(i::Token::COMMA);
-    ParseIdentifier(CHECK_OK);
-    nvars++;
-    if (peek() == i::Token::ASSIGN) {
-      Expect(i::Token::ASSIGN, CHECK_OK);
-      ParseAssignmentExpression(accept_IN, CHECK_OK);
-    }
-  } while (peek() == i::Token::COMMA);
-
-  if (num_decl != NULL) *num_decl = nvars;
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseExpressionOrLabelledStatement(
-    bool* ok) {
-  // ExpressionStatement | LabelledStatement ::
-  //   Expression ';'
-  //   Identifier ':' Statement
-
-  Expression expr = ParseExpression(true, CHECK_OK);
-  if (peek() == i::Token::COLON && expr == kIdentifierExpression) {
-    Consume(i::Token::COLON);
-    return ParseStatement(ok);
-  }
-  // Parsed expression statement.
-  ExpectSemicolon(CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseIfStatement(bool* ok) {
-  // IfStatement ::
-  //   'if' '(' Expression ')' Statement ('else' Statement)?
-
-  Expect(i::Token::IF, CHECK_OK);
-  Expect(i::Token::LPAREN, CHECK_OK);
-  ParseExpression(true, CHECK_OK);
-  Expect(i::Token::RPAREN, CHECK_OK);
-  ParseStatement(CHECK_OK);
-  if (peek() == i::Token::ELSE) {
-    Next();
-    ParseStatement(CHECK_OK);
-  }
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseContinueStatement(bool* ok) {
-  // ContinueStatement ::
-  //   'continue' [no line terminator] Identifier? ';'
-
-  Expect(i::Token::CONTINUE, CHECK_OK);
-  i::Token::Value tok = peek();
-  if (!scanner_->has_line_terminator_before_next() &&
-      tok != i::Token::SEMICOLON &&
-      tok != i::Token::RBRACE &&
-      tok != i::Token::EOS) {
-    ParseIdentifier(CHECK_OK);
-  }
-  ExpectSemicolon(CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseBreakStatement(bool* ok) {
-  // BreakStatement ::
-  //   'break' [no line terminator] Identifier? ';'
-
-  Expect(i::Token::BREAK, CHECK_OK);
-  i::Token::Value tok = peek();
-  if (!scanner_->has_line_terminator_before_next() &&
-      tok != i::Token::SEMICOLON &&
-      tok != i::Token::RBRACE &&
-      tok != i::Token::EOS) {
-    ParseIdentifier(CHECK_OK);
-  }
-  ExpectSemicolon(CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseReturnStatement(bool* ok) {
-  // ReturnStatement ::
-  //   'return' [no line terminator] Expression? ';'
-
-  // Consume the return token. It is necessary to do the before
-  // reporting any errors on it, because of the way errors are
-  // reported (underlining).
-  Expect(i::Token::RETURN, CHECK_OK);
-
-  // An ECMAScript program is considered syntactically incorrect if it
-  // contains a return statement that is not within the body of a
-  // function. See ECMA-262, section 12.9, page 67.
-  // This is not handled during preparsing.
-
-  i::Token::Value tok = peek();
-  if (!scanner_->has_line_terminator_before_next() &&
-      tok != i::Token::SEMICOLON &&
-      tok != i::Token::RBRACE &&
-      tok != i::Token::EOS) {
-    ParseExpression(true, CHECK_OK);
-  }
-  ExpectSemicolon(CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseWithStatement(bool* ok) {
-  // WithStatement ::
-  //   'with' '(' Expression ')' Statement
-  Expect(i::Token::WITH, CHECK_OK);
-  Expect(i::Token::LPAREN, CHECK_OK);
-  ParseExpression(true, CHECK_OK);
-  Expect(i::Token::RPAREN, CHECK_OK);
-
-  scope_->EnterWith();
-  ParseStatement(CHECK_OK);
-  scope_->LeaveWith();
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseSwitchStatement(bool* ok) {
-  // SwitchStatement ::
-  //   'switch' '(' Expression ')' '{' CaseClause* '}'
-
-  Expect(i::Token::SWITCH, CHECK_OK);
-  Expect(i::Token::LPAREN, CHECK_OK);
-  ParseExpression(true, CHECK_OK);
-  Expect(i::Token::RPAREN, CHECK_OK);
-
-  Expect(i::Token::LBRACE, CHECK_OK);
-  i::Token::Value token = peek();
-  while (token != i::Token::RBRACE) {
-    if (token == i::Token::CASE) {
-      Expect(i::Token::CASE, CHECK_OK);
-      ParseExpression(true, CHECK_OK);
-      Expect(i::Token::COLON, CHECK_OK);
-    } else if (token == i::Token::DEFAULT) {
-      Expect(i::Token::DEFAULT, CHECK_OK);
-      Expect(i::Token::COLON, CHECK_OK);
-    } else {
-      ParseStatement(CHECK_OK);
-    }
-    token = peek();
-  }
-  Expect(i::Token::RBRACE, CHECK_OK);
-
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseDoWhileStatement(bool* ok) {
-  // DoStatement ::
-  //   'do' Statement 'while' '(' Expression ')' ';'
-
-  Expect(i::Token::DO, CHECK_OK);
-  ParseStatement(CHECK_OK);
-  Expect(i::Token::WHILE, CHECK_OK);
-  Expect(i::Token::LPAREN, CHECK_OK);
-  ParseExpression(true, CHECK_OK);
-  Expect(i::Token::RPAREN, CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseWhileStatement(bool* ok) {
-  // WhileStatement ::
-  //   'while' '(' Expression ')' Statement
-
-  Expect(i::Token::WHILE, CHECK_OK);
-  Expect(i::Token::LPAREN, CHECK_OK);
-  ParseExpression(true, CHECK_OK);
-  Expect(i::Token::RPAREN, CHECK_OK);
-  ParseStatement(CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseForStatement(bool* ok) {
-  // ForStatement ::
-  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
-
-  Expect(i::Token::FOR, CHECK_OK);
-  Expect(i::Token::LPAREN, CHECK_OK);
-  if (peek() != i::Token::SEMICOLON) {
-    if (peek() == i::Token::VAR || peek() == i::Token::CONST) {
-      int decl_count;
-      ParseVariableDeclarations(false, &decl_count, CHECK_OK);
-      if (peek() == i::Token::IN && decl_count == 1) {
-        Expect(i::Token::IN, CHECK_OK);
-        ParseExpression(true, CHECK_OK);
-        Expect(i::Token::RPAREN, CHECK_OK);
-
-        ParseStatement(CHECK_OK);
-        return kUnknownStatement;
-      }
-    } else {
-      ParseExpression(false, CHECK_OK);
-      if (peek() == i::Token::IN) {
-        Expect(i::Token::IN, CHECK_OK);
-        ParseExpression(true, CHECK_OK);
-        Expect(i::Token::RPAREN, CHECK_OK);
-
-        ParseStatement(CHECK_OK);
-        return kUnknownStatement;
-      }
-    }
-  }
-
-  // Parsed initializer at this point.
-  Expect(i::Token::SEMICOLON, CHECK_OK);
-
-  if (peek() != i::Token::SEMICOLON) {
-    ParseExpression(true, CHECK_OK);
-  }
-  Expect(i::Token::SEMICOLON, CHECK_OK);
-
-  if (peek() != i::Token::RPAREN) {
-    ParseExpression(true, CHECK_OK);
-  }
-  Expect(i::Token::RPAREN, CHECK_OK);
-
-  ParseStatement(CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseThrowStatement(bool* ok) {
-  // ThrowStatement ::
-  //   'throw' [no line terminator] Expression ';'
-
-  Expect(i::Token::THROW, CHECK_OK);
-  if (scanner_->has_line_terminator_before_next()) {
-    typename Scanner::Location pos = scanner_->location();
-    ReportMessageAt(pos.beg_pos, pos.end_pos,
-                    "newline_after_throw", NULL);
-    *ok = false;
-    return kUnknownStatement;
-  }
-  ParseExpression(true, CHECK_OK);
-  ExpectSemicolon(CHECK_OK);
-
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseTryStatement(bool* ok) {
-  // TryStatement ::
-  //   'try' Block Catch
-  //   'try' Block Finally
-  //   'try' Block Catch Finally
-  //
-  // Catch ::
-  //   'catch' '(' Identifier ')' Block
-  //
-  // Finally ::
-  //   'finally' Block
-
-  // In preparsing, allow any number of catch/finally blocks, including zero
-  // of both.
-
-  Expect(i::Token::TRY, CHECK_OK);
-
-  ParseBlock(CHECK_OK);
-
-  bool catch_or_finally_seen = false;
-  if (peek() == i::Token::CATCH) {
-    Consume(i::Token::CATCH);
-    Expect(i::Token::LPAREN, CHECK_OK);
-    ParseIdentifier(CHECK_OK);
-    Expect(i::Token::RPAREN, CHECK_OK);
-    scope_->EnterWith();
-    ParseBlock(ok);
-    scope_->LeaveWith();
-    if (!*ok) return kUnknownStatement;
-    catch_or_finally_seen = true;
-  }
-  if (peek() == i::Token::FINALLY) {
-    Consume(i::Token::FINALLY);
-    ParseBlock(CHECK_OK);
-    catch_or_finally_seen = true;
-  }
-  if (!catch_or_finally_seen) {
-    *ok = false;
-  }
-  return kUnknownStatement;
-}
-
-
-template <typename Scanner, typename Log>
-Statement PreParser<Scanner, Log>::ParseDebuggerStatement(bool* ok) {
-  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
-  // contexts this is used as a statement which invokes the debugger as if a
-  // break point is present.
-  // DebuggerStatement ::
-  //   'debugger' ';'
-
-  Expect(i::Token::DEBUGGER, CHECK_OK);
-  ExpectSemicolon(CHECK_OK);
-  return kUnknownStatement;
-}
-
-
-// Precedence = 1
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseExpression(bool accept_IN, bool* ok) {
-  // Expression ::
-  //   AssignmentExpression
-  //   Expression ',' AssignmentExpression
-
-  Expression result = ParseAssignmentExpression(accept_IN, CHECK_OK);
-  while (peek() == i::Token::COMMA) {
-    Expect(i::Token::COMMA, CHECK_OK);
-    ParseAssignmentExpression(accept_IN, CHECK_OK);
-    result = kUnknownExpression;
-  }
-  return result;
-}
-
-
-// Precedence = 2
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseAssignmentExpression(bool accept_IN,
-                                                              bool* ok) {
-  // AssignmentExpression ::
-  //   ConditionalExpression
-  //   LeftHandSideExpression AssignmentOperator AssignmentExpression
-
-  Expression expression = ParseConditionalExpression(accept_IN, CHECK_OK);
-
-  if (!i::Token::IsAssignmentOp(peek())) {
-    // Parsed conditional expression only (no assignment).
-    return expression;
-  }
-
-  i::Token::Value op = Next();  // Get assignment operator.
-  ParseAssignmentExpression(accept_IN, CHECK_OK);
-
-  if ((op == i::Token::ASSIGN) && (expression == kThisPropertyExpression)) {
-    scope_->AddProperty();
-  }
-
-  return kUnknownExpression;
-}
-
-
-// Precedence = 3
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseConditionalExpression(bool accept_IN,
-                                                               bool* ok) {
-  // ConditionalExpression ::
-  //   LogicalOrExpression
-  //   LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
-
-  // We start using the binary expression parser for prec >= 4 only!
-  Expression expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
-  if (peek() != i::Token::CONDITIONAL) return expression;
-  Consume(i::Token::CONDITIONAL);
-  // In parsing the first assignment expression in conditional
-  // expressions we always accept the 'in' keyword; see ECMA-262,
-  // section 11.12, page 58.
-  ParseAssignmentExpression(true, CHECK_OK);
-  Expect(i::Token::COLON, CHECK_OK);
-  ParseAssignmentExpression(accept_IN, CHECK_OK);
-  return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-int PreParser<Scanner, Log>::Precedence(i::Token::Value tok, bool accept_IN) {
-  if (tok == i::Token::IN && !accept_IN)
-    return 0;  // 0 precedence will terminate binary expression parsing
-
-  return i::Token::Precedence(tok);
-}
-
-
-// Precedence >= 4
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseBinaryExpression(int prec,
-                                                          bool accept_IN,
-                                                          bool* ok) {
-  Expression result = ParseUnaryExpression(CHECK_OK);
-  for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
-    // prec1 >= 4
-    while (Precedence(peek(), accept_IN) == prec1) {
-      Next();
-      ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
-      result = kUnknownExpression;
-    }
-  }
-  return result;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseUnaryExpression(bool* ok) {
-  // UnaryExpression ::
-  //   PostfixExpression
-  //   'delete' UnaryExpression
-  //   'void' UnaryExpression
-  //   'typeof' UnaryExpression
-  //   '++' UnaryExpression
-  //   '--' UnaryExpression
-  //   '+' UnaryExpression
-  //   '-' UnaryExpression
-  //   '~' UnaryExpression
-  //   '!' UnaryExpression
-
-  i::Token::Value op = peek();
-  if (i::Token::IsUnaryOp(op) || i::Token::IsCountOp(op)) {
-    op = Next();
-    ParseUnaryExpression(ok);
-    return kUnknownExpression;
-  } else {
-    return ParsePostfixExpression(ok);
-  }
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParsePostfixExpression(bool* ok) {
-  // PostfixExpression ::
-  //   LeftHandSideExpression ('++' | '--')?
-
-  Expression expression = ParseLeftHandSideExpression(CHECK_OK);
-  if (!scanner_->has_line_terminator_before_next() &&
-      i::Token::IsCountOp(peek())) {
-    Next();
-    return kUnknownExpression;
-  }
-  return expression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseLeftHandSideExpression(bool* ok) {
-  // LeftHandSideExpression ::
-  //   (NewExpression | MemberExpression) ...
-
-  Expression result;
-  if (peek() == i::Token::NEW) {
-    result = ParseNewExpression(CHECK_OK);
-  } else {
-    result = ParseMemberExpression(CHECK_OK);
-  }
-
-  while (true) {
-    switch (peek()) {
-      case i::Token::LBRACK: {
-        Consume(i::Token::LBRACK);
-        ParseExpression(true, CHECK_OK);
-        Expect(i::Token::RBRACK, CHECK_OK);
-        if (result == kThisExpression) {
-          result = kThisPropertyExpression;
-        } else {
-          result = kUnknownExpression;
-        }
-        break;
-      }
-
-      case i::Token::LPAREN: {
-        ParseArguments(CHECK_OK);
-        result = kUnknownExpression;
-        break;
-      }
-
-      case i::Token::PERIOD: {
-        Consume(i::Token::PERIOD);
-        ParseIdentifierName(CHECK_OK);
-        if (result == kThisExpression) {
-          result = kThisPropertyExpression;
-        } else {
-          result = kUnknownExpression;
-        }
-        break;
-      }
-
-      default:
-        return result;
-    }
-  }
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseNewExpression(bool* ok) {
-  // NewExpression ::
-  //   ('new')+ MemberExpression
-
-  // The grammar for new expressions is pretty warped. The keyword
-  // 'new' can either be a part of the new expression (where it isn't
-  // followed by an argument list) or a part of the member expression,
-  // where it must be followed by an argument list. To accommodate
-  // this, we parse the 'new' keywords greedily and keep track of how
-  // many we have parsed. This information is then passed on to the
-  // member expression parser, which is only allowed to match argument
-  // lists as long as it has 'new' prefixes left
-  unsigned new_count = 0;
-  do {
-    Consume(i::Token::NEW);
-    new_count++;
-  } while (peek() == i::Token::NEW);
-
-  return ParseMemberWithNewPrefixesExpression(new_count, ok);
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseMemberExpression(bool* ok) {
-  return ParseMemberWithNewPrefixesExpression(0, ok);
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseMemberWithNewPrefixesExpression(
-    unsigned new_count, bool* ok) {
-  // MemberExpression ::
-  //   (PrimaryExpression | FunctionLiteral)
-  //     ('[' Expression ']' | '.' Identifier | Arguments)*
-
-  // Parse the initial primary or function expression.
-  Expression result = kUnknownExpression;
-  if (peek() == i::Token::FUNCTION) {
-    Consume(i::Token::FUNCTION);
-    if (peek() == i::Token::IDENTIFIER) {
-      ParseIdentifier(CHECK_OK);
-    }
-    result = ParseFunctionLiteral(CHECK_OK);
-  } else {
-    result = ParsePrimaryExpression(CHECK_OK);
-  }
-
-  while (true) {
-    switch (peek()) {
-      case i::Token::LBRACK: {
-        Consume(i::Token::LBRACK);
-        ParseExpression(true, CHECK_OK);
-        Expect(i::Token::RBRACK, CHECK_OK);
-        if (result == kThisExpression) {
-          result = kThisPropertyExpression;
-        } else {
-          result = kUnknownExpression;
-        }
-        break;
-      }
-      case i::Token::PERIOD: {
-        Consume(i::Token::PERIOD);
-        ParseIdentifierName(CHECK_OK);
-        if (result == kThisExpression) {
-          result = kThisPropertyExpression;
-        } else {
-          result = kUnknownExpression;
-        }
-        break;
-      }
-      case i::Token::LPAREN: {
-        if (new_count == 0) return result;
-        // Consume one of the new prefixes (already parsed).
-        ParseArguments(CHECK_OK);
-        new_count--;
-        result = kUnknownExpression;
-        break;
-      }
-      default:
-        return result;
-    }
-  }
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParsePrimaryExpression(bool* ok) {
-  // PrimaryExpression ::
-  //   'this'
-  //   'null'
-  //   'true'
-  //   'false'
-  //   Identifier
-  //   Number
-  //   String
-  //   ArrayLiteral
-  //   ObjectLiteral
-  //   RegExpLiteral
-  //   '(' Expression ')'
-
-  Expression result = kUnknownExpression;
-  switch (peek()) {
-    case i::Token::THIS: {
-      Next();
-      result = kThisExpression;
-      break;
-    }
-
-    case i::Token::IDENTIFIER: {
-      ParseIdentifier(CHECK_OK);
-      result = kIdentifierExpression;
-      break;
-    }
-
-    case i::Token::NULL_LITERAL:
-    case i::Token::TRUE_LITERAL:
-    case i::Token::FALSE_LITERAL:
-    case i::Token::NUMBER: {
-      Next();
-      break;
-    }
-    case i::Token::STRING: {
-      Next();
-      result = GetStringSymbol();
-      break;
-    }
-
-    case i::Token::ASSIGN_DIV:
-      result = ParseRegExpLiteral(true, CHECK_OK);
-      break;
-
-    case i::Token::DIV:
-      result = ParseRegExpLiteral(false, CHECK_OK);
-      break;
-
-    case i::Token::LBRACK:
-      result = ParseArrayLiteral(CHECK_OK);
-      break;
-
-    case i::Token::LBRACE:
-      result = ParseObjectLiteral(CHECK_OK);
-      break;
-
-    case i::Token::LPAREN:
-      Consume(i::Token::LPAREN);
-      result = ParseExpression(true, CHECK_OK);
-      Expect(i::Token::RPAREN, CHECK_OK);
-      if (result == kIdentifierExpression) result = kUnknownExpression;
-      break;
-
-    case i::Token::MOD:
-      result = ParseV8Intrinsic(CHECK_OK);
-      break;
-
-    default: {
-      Next();
-      *ok = false;
-      return kUnknownExpression;
-    }
-  }
-
-  return result;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseArrayLiteral(bool* ok) {
-  // ArrayLiteral ::
-  //   '[' Expression? (',' Expression?)* ']'
-  Expect(i::Token::LBRACK, CHECK_OK);
-  while (peek() != i::Token::RBRACK) {
-    if (peek() != i::Token::COMMA) {
-      ParseAssignmentExpression(true, CHECK_OK);
-    }
-    if (peek() != i::Token::RBRACK) {
-      Expect(i::Token::COMMA, CHECK_OK);
-    }
-  }
-  Expect(i::Token::RBRACK, CHECK_OK);
-
-  scope_->NextMaterializedLiteralIndex();
-  return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseObjectLiteral(bool* ok) {
-  // ObjectLiteral ::
-  //   '{' (
-  //       ((IdentifierName | String | Number) ':' AssignmentExpression)
-  //     | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
-  //    )*[','] '}'
-
-  Expect(i::Token::LBRACE, CHECK_OK);
-  while (peek() != i::Token::RBRACE) {
-    i::Token::Value next = peek();
-    switch (next) {
-      case i::Token::IDENTIFIER: {
-        bool is_getter = false;
-        bool is_setter = false;
-        ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
-        if ((is_getter || is_setter) && peek() != i::Token::COLON) {
-            i::Token::Value name = Next();
-            if (name != i::Token::IDENTIFIER &&
-                name != i::Token::NUMBER &&
-                name != i::Token::STRING &&
-                !i::Token::IsKeyword(name)) {
-              *ok = false;
-              return kUnknownExpression;
-            }
-            ParseFunctionLiteral(CHECK_OK);
-            if (peek() != i::Token::RBRACE) {
-              Expect(i::Token::COMMA, CHECK_OK);
-            }
-            continue;  // restart the while
-        }
-        break;
-      }
-      case i::Token::STRING:
-        Consume(next);
-        GetStringSymbol();
-        break;
-      case i::Token::NUMBER:
-        Consume(next);
-        break;
-      default:
-        if (i::Token::IsKeyword(next)) {
-          Consume(next);
-        } else {
-          // Unexpected token.
-          *ok = false;
-          return kUnknownExpression;
-        }
-    }
-
-    Expect(i::Token::COLON, CHECK_OK);
-    ParseAssignmentExpression(true, CHECK_OK);
-
-    // TODO(1240767): Consider allowing trailing comma.
-    if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
-  }
-  Expect(i::Token::RBRACE, CHECK_OK);
-
-  scope_->NextMaterializedLiteralIndex();
-  return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseRegExpLiteral(bool seen_equal,
-                                                       bool* ok) {
-  if (!scanner_->ScanRegExpPattern(seen_equal)) {
-    Next();
-    typename Scanner::Location location = scanner_->location();
-    ReportMessageAt(location.beg_pos, location.end_pos,
-                    "unterminated_regexp", NULL);
-    *ok = false;
-    return kUnknownExpression;
-  }
-
-  scope_->NextMaterializedLiteralIndex();
-
-  if (!scanner_->ScanRegExpFlags()) {
-    Next();
-    typename Scanner::Location location = scanner_->location();
-    ReportMessageAt(location.beg_pos, location.end_pos,
-                    "invalid_regexp_flags", NULL);
-    *ok = false;
-    return kUnknownExpression;
-  }
-  Next();
-  return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Arguments PreParser<Scanner, Log>::ParseArguments(bool* ok) {
-  // Arguments ::
-  //   '(' (AssignmentExpression)*[','] ')'
-
-  Expect(i::Token::LPAREN, CHECK_OK);
-  bool done = (peek() == i::Token::RPAREN);
-  int argc = 0;
-  while (!done) {
-    ParseAssignmentExpression(true, CHECK_OK);
-    argc++;
-    done = (peek() == i::Token::RPAREN);
-    if (!done) Expect(i::Token::COMMA, CHECK_OK);
-  }
-  Expect(i::Token::RPAREN, CHECK_OK);
-  return argc;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseFunctionLiteral(bool* ok) {
-  // Function ::
-  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
-
-  // Parse function body.
-  ScopeType outer_scope_type = scope_->type();
-  bool inside_with = scope_->IsInsideWith();
-  Scope function_scope(&scope_, kFunctionScope);
-
-  //  FormalParameterList ::
-  //    '(' (Identifier)*[','] ')'
-  Expect(i::Token::LPAREN, CHECK_OK);
-  bool done = (peek() == i::Token::RPAREN);
-  while (!done) {
-    ParseIdentifier(CHECK_OK);
-    done = (peek() == i::Token::RPAREN);
-    if (!done) {
-      Expect(i::Token::COMMA, CHECK_OK);
-    }
-  }
-  Expect(i::Token::RPAREN, CHECK_OK);
-
-  Expect(i::Token::LBRACE, CHECK_OK);
-  int function_block_pos = scanner_->location().beg_pos;
-
-  // Determine if the function will be lazily compiled.
-  // Currently only happens to top-level functions.
-  // Optimistically assume that all top-level functions are lazily compiled.
-  bool is_lazily_compiled =
-      (outer_scope_type == kTopLevelScope && !inside_with && allow_lazy_);
-
-  if (is_lazily_compiled) {
-    log_->PauseRecording();
-    ParseSourceElements(i::Token::RBRACE, ok);
-    log_->ResumeRecording();
-    if (!*ok) return kUnknownExpression;
-
-    Expect(i::Token::RBRACE, CHECK_OK);
-
-    int end_pos = scanner_->location().end_pos;
-    log_->LogFunction(function_block_pos, end_pos,
-                      function_scope.materialized_literal_count(),
-                      function_scope.expected_properties());
-  } else {
-    ParseSourceElements(i::Token::RBRACE, CHECK_OK);
-    Expect(i::Token::RBRACE, CHECK_OK);
-  }
-  return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::ParseV8Intrinsic(bool* ok) {
-  // CallRuntime ::
-  //   '%' Identifier Arguments
-
-  Expect(i::Token::MOD, CHECK_OK);
-  ParseIdentifier(CHECK_OK);
-  ParseArguments(CHECK_OK);
-
-  return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-void PreParser<Scanner, Log>::ExpectSemicolon(bool* ok) {
-  // Check for automatic semicolon insertion according to
-  // the rules given in ECMA-262, section 7.9, page 21.
-  i::Token::Value tok = peek();
-  if (tok == i::Token::SEMICOLON) {
-    Next();
-    return;
-  }
-  if (scanner_->has_line_terminator_before_next() ||
-      tok == i::Token::RBRACE ||
-      tok == i::Token::EOS) {
-    return;
-  }
-  Expect(i::Token::SEMICOLON, ok);
-}
-
-
-template <typename Scanner, typename Log>
-Identifier PreParser<Scanner, Log>::GetIdentifierSymbol() {
-  const char* literal_chars = scanner_->literal_string();
-  int literal_length = scanner_->literal_length();
-  int identifier_pos = scanner_->location().beg_pos;
-
-  log_->LogSymbol(identifier_pos, literal_chars, literal_length);
-
-  return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Expression PreParser<Scanner, Log>::GetStringSymbol() {
-  const char* literal_chars = scanner_->literal_string();
-  int literal_length = scanner_->literal_length();
-
-  int literal_position = scanner_->location().beg_pos;
-  log_->LogSymbol(literal_position, literal_chars, literal_length);
-
-  return kUnknownExpression;
-}
-
-
-template <typename Scanner, typename Log>
-Identifier PreParser<Scanner, Log>::ParseIdentifier(bool* ok) {
-  Expect(i::Token::IDENTIFIER, ok);
-  if (!*ok) return kUnknownIdentifier;
-  return GetIdentifierSymbol();
-}
-
-
-template <typename Scanner, typename Log>
-Identifier PreParser<Scanner, Log>::ParseIdentifierName(bool* ok) {
-  i::Token::Value next = Next();
-  if (i::Token::IsKeyword(next)) {
-    int pos = scanner_->location().beg_pos;
-    const char* keyword = i::Token::String(next);
-    log_->LogSymbol(pos, keyword, i::StrLength(keyword));
-    return kUnknownExpression;
-  }
-  if (next == i::Token::IDENTIFIER) {
-    return GetIdentifierSymbol();
-  }
-  *ok = false;
-  return kUnknownIdentifier;
-}
-
-
-// This function reads an identifier and determines whether or not it
-// is 'get' or 'set'.  The reason for not using ParseIdentifier and
-// checking on the output is that this involves heap allocation which
-// we can't do during preparsing.
-template <typename Scanner, typename Log>
-Identifier PreParser<Scanner, Log>::ParseIdentifierOrGetOrSet(bool* is_get,
-                                                   bool* is_set,
-                                                   bool* ok) {
-  Expect(i::Token::IDENTIFIER, CHECK_OK);
-  if (scanner_->literal_length() == 3) {
-    const char* token = scanner_->literal_string();
-    *is_get = strncmp(token, "get", 3) == 0;
-    *is_set = !*is_get && strncmp(token, "set", 3) == 0;
-  }
-  return GetIdentifierSymbol();
-}
-
-#undef CHECK_OK
 } }  // v8::preparser
 
 #endif  // V8_PREPARSER_H
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index e0b63f9..640f13c 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -1295,8 +1295,8 @@
   } else if (object->IsJSObject()) {
     return AddEntry(object,
                     HeapEntry::kObject,
-                    collection_->GetName(
-                        JSObject::cast(object)->constructor_name()),
+                    collection_->GetName(GetConstructorNameForHeapProfile(
+                        JSObject::cast(object))),
                     children_count,
                     retainers_count);
   } else if (object->IsString()) {
@@ -1462,6 +1462,14 @@
 }
 
 
+void HeapSnapshot::SetDominatorsToSelf() {
+  for (int i = 0; i < entries_.length(); ++i) {
+    HeapEntry* entry = entries_[i];
+    if (entry->dominator() == NULL) entry->set_dominator(entry);
+  }
+}
+
+
 void HeapSnapshot::SetEntriesDominators() {
   // This array is used for maintaining reverse postorder of nodes.
   ScopedVector<HeapEntry*> ordered_entries(entries_.length());
@@ -1473,10 +1481,7 @@
     ordered_entries[i]->set_dominator(dominators[i]);
   }
   // For nodes unreachable from root, set dominator to itself.
-  for (int i = 0; i < entries_.length(); ++i) {
-    HeapEntry* entry = entries_[i];
-    if (entry->dominator() == NULL) entry->set_dominator(entry);
-  }
+  SetDominatorsToSelf();
 }
 
 
@@ -2764,6 +2769,12 @@
   sorted_entries->Sort(SortUsingEntryValue);
 }
 
+
+String* GetConstructorNameForHeapProfile(JSObject* object) {
+  if (object->IsJSFunction()) return Heap::closure_symbol();
+  return object->constructor_name();
+}
+
 } }  // namespace v8::internal
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 30d70a2..55c57fd 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -700,6 +700,7 @@
   List<HeapEntry*>* GetSortedEntriesList();
   template<class Visitor>
   void IterateEntries(Visitor* visitor) { entries_.Iterate(visitor); }
+  void SetDominatorsToSelf();
 
   void Print(int max_depth);
   void PrintEntriesSize();
@@ -1072,6 +1073,9 @@
   DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
 };
 
+
+String* GetConstructorNameForHeapProfile(JSObject* object);
+
 } }  // namespace v8::internal
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/src/runtime.cc b/src/runtime.cc
index e20c94f..c43a1ab 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -5020,11 +5020,12 @@
 // For example, "foo" => ["f", "o", "o"].
 static MaybeObject* Runtime_StringToArray(Arguments args) {
   HandleScope scope;
-  ASSERT(args.length() == 1);
+  ASSERT(args.length() == 2);
   CONVERT_ARG_CHECKED(String, s, 0);
+  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
 
   s->TryFlatten();
-  const int length = s->length();
+  const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
 
   Handle<FixedArray> elements;
   if (s->IsFlat() && s->IsAsciiRepresentation()) {
@@ -6391,7 +6392,7 @@
   }
   if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
     ConstructStubCompiler compiler;
-    MaybeObject* code = compiler.CompileConstructStub(function->shared());
+    MaybeObject* code = compiler.CompileConstructStub(*function);
     if (!code->IsFailure()) {
       function->shared()->set_construct_stub(
           Code::cast(code->ToObjectUnchecked()));
@@ -6459,7 +6460,6 @@
     // track one initial_map at a time, so we force the completion before the
     // function is called as a constructor for the first time.
     shared->CompleteInobjectSlackTracking();
-    TrySettingInlineConstructStub(function);
   }
 
   bool first_allocation = !shared->live_objects_may_exist();
diff --git a/src/runtime.h b/src/runtime.h
index e36988d..f9ebbc4 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -175,7 +175,7 @@
   F(StringReplaceRegExpWithString, 4, 1) \
   F(StringMatch, 3, 1) \
   F(StringTrim, 3, 1) \
-  F(StringToArray, 1, 1) \
+  F(StringToArray, 2, 1) \
   F(NewStringWrapper, 1, 1) \
   \
   /* Numbers */ \
diff --git a/src/string.js b/src/string.js
index d82ce05..3b3c82b 100644
--- a/src/string.js
+++ b/src/string.js
@@ -552,7 +552,7 @@
     var separator_length = separator.length;
 
     // If the separator string is empty then return the elements in the subject.
-    if (separator_length === 0) return %StringToArray(subject);
+    if (separator_length === 0) return %StringToArray(subject, limit);
 
     var result = %StringSplit(subject, separator, limit);
 
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 4886c7e..cef5481 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -740,7 +740,7 @@
  public:
   explicit ConstructStubCompiler() {}
 
-  MUST_USE_RESULT MaybeObject* CompileConstructStub(SharedFunctionInfo* shared);
+  MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
 
  private:
   MaybeObject* GetCode();
diff --git a/src/token.cc b/src/token.cc
index 21fa9ee..488e909 100644
--- a/src/token.cc
+++ b/src/token.cc
@@ -25,8 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "v8.h"
-
+#include "../include/v8stdint.h"
 #include "token.h"
 
 namespace v8 {
diff --git a/src/v8.h b/src/v8.h
index 74e98f1..a2313b0 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -54,7 +54,7 @@
 // Basic includes
 #include "../include/v8.h"
 #include "v8globals.h"
-#include "checks.h"
+#include "v8checks.h"
 #include "allocation.h"
 #include "v8utils.h"
 #include "flags.h"
diff --git a/src/v8checks.h b/src/v8checks.h
new file mode 100644
index 0000000..9857f73
--- /dev/null
+++ b/src/v8checks.h
@@ -0,0 +1,64 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_V8CHECKS_H_
+#define V8_V8CHECKS_H_
+
+#include "checks.h"
+
+void API_Fatal(const char* location, const char* format, ...);
+
+namespace v8 {
+  class Value;
+  template <class T> class Handle;
+
+namespace internal {
+  intptr_t HeapObjectTagMask();
+
+} }  // namespace v8::internal
+
+
+void CheckNonEqualsHelper(const char* file,
+                          int line,
+                          const char* unexpected_source,
+                          v8::Handle<v8::Value> unexpected,
+                          const char* value_source,
+                          v8::Handle<v8::Value> value);
+
+void CheckEqualsHelper(const char* file,
+                       int line,
+                       const char* expected_source,
+                       v8::Handle<v8::Value> expected,
+                       const char* value_source,
+                       v8::Handle<v8::Value> value);
+
+#define ASSERT_TAG_ALIGNED(address) \
+  ASSERT((reinterpret_cast<intptr_t>(address) & HeapObjectTagMask()) == 0)
+
+#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & HeapObjectTagMask()) == 0)
+
+#endif  // V8_V8CHECKS_H_
diff --git a/src/version.cc b/src/version.cc
index 0e0a7cf..61d314a 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      8
+#define BUILD_NUMBER      9
 #define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 834a6f6..d919833 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -1889,7 +1889,6 @@
 
 
 void MacroAssembler::LoadAllocationTopHelper(Register result,
-                                             Register result_end,
                                              Register scratch,
                                              AllocationFlags flags) {
   ExternalReference new_space_allocation_top =
@@ -1911,7 +1910,6 @@
   // Move address of new object to result. Use scratch register if available,
   // and keep address in scratch until call to UpdateAllocationTopHelper.
   if (scratch.is_valid()) {
-    ASSERT(!scratch.is(result_end));
     movq(scratch, new_space_allocation_top);
     movq(result, Operand(scratch, 0));
   } else if (result.is(rax)) {
@@ -1972,7 +1970,7 @@
   ASSERT(!result.is(result_end));
 
   // Load address of new object into result.
-  LoadAllocationTopHelper(result, result_end, scratch, flags);
+  LoadAllocationTopHelper(result, scratch, flags);
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
@@ -2029,7 +2027,7 @@
   ASSERT(!result.is(result_end));
 
   // Load address of new object into result.
-  LoadAllocationTopHelper(result, result_end, scratch, flags);
+  LoadAllocationTopHelper(result, scratch, flags);
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
@@ -2071,7 +2069,7 @@
   ASSERT(!result.is(result_end));
 
   // Load address of new object into result.
-  LoadAllocationTopHelper(result, result_end, scratch, flags);
+  LoadAllocationTopHelper(result, scratch, flags);
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 5b082fd..0b7e601 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -950,12 +950,9 @@
 
   // Allocation support helpers.
   // Loads the top of new-space into the result register.
-  // If flags contains RESULT_CONTAINS_TOP then result_end is valid and
-  // already contains the top of new-space, and scratch is invalid.
   // Otherwise the address of the new-space top is loaded into scratch (if
   // scratch is valid), and the new-space top is loaded into result.
   void LoadAllocationTopHelper(Register result,
-                               Register result_end,
                                Register scratch,
                                AllocationFlags flags);
   // Update allocation top with value in result_end register.
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index dbf93f5..7ba482c 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -2890,8 +2890,7 @@
 
 // Specialized stub for constructing objects from functions which only have only
 // simple assignments of the form this.x = ...; in their body.
-MaybeObject* ConstructStubCompiler::CompileConstructStub(
-    SharedFunctionInfo* shared) {
+MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
   // ----------- S t a t e -------------
   //  -- rax : argc
   //  -- rdi : constructor
@@ -2964,6 +2963,7 @@
   // r9: first in-object property of the JSObject
   // Fill the initialized properties with a constant value or a passed argument
   // depending on the this.x = ...; assignment in the function.
+  SharedFunctionInfo* shared = function->shared();
   for (int i = 0; i < shared->this_property_assignments_count(); i++) {
     if (shared->IsThisPropertyAssignmentArgument(i)) {
       // Check if the argument assigned to the property is actually passed.
@@ -2983,8 +2983,9 @@
   }
 
   // Fill the unused in-object property fields with undefined.
+  ASSERT(function->has_initial_map());
   for (int i = shared->this_property_assignments_count();
-       i < shared->CalculateInObjectProperties();
+       i < function->initial_map()->inobject_properties();
        i++) {
     __ movq(Operand(r9, i * kPointerSize), r8);
   }
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 5322314..8ce7a79 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -7819,6 +7819,31 @@
 }
 
 
+THREADED_TEST(ObjectGetConstructorName) {
+  v8::HandleScope scope;
+  LocalContext context;
+  v8_compile("function Parent() {};"
+             "function Child() {};"
+             "Child.prototype = new Parent();"
+             "var outer = { inner: function() { } };"
+             "var p = new Parent();"
+             "var c = new Child();"
+             "var x = new outer.inner();")->Run();
+
+  Local<v8::Value> p = context->Global()->Get(v8_str("p"));
+  CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
+      v8_str("Parent")));
+
+  Local<v8::Value> c = context->Global()->Get(v8_str("c"));
+  CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
+      v8_str("Child")));
+
+  Local<v8::Value> x = context->Global()->Get(v8_str("x"));
+  CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
+      v8_str("outer.inner")));
+}
+
+
 bool ApiTestFuzzer::fuzzing_ = false;
 i::Semaphore* ApiTestFuzzer::all_tests_done_=
   i::OS::CreateSemaphore(0);
@@ -8734,7 +8759,7 @@
       v8::ScriptData::PreCompile(script, i::StrLength(script));
   CHECK(!sd->HasError());
   // ScriptDataImpl private implementation details
-  const int kHeaderSize = i::ScriptDataImpl::kHeaderSize;
+  const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
   const int kFunctionEntrySize = i::FunctionEntry::kSize;
   const int kFunctionEntryStartOffset = 0;
   const int kFunctionEntryEndOffset = 1;
diff --git a/test/cctest/test-conversions.cc b/test/cctest/test-conversions.cc
index eef7184..1b5cc2d 100644
--- a/test/cctest/test-conversions.cc
+++ b/test/cctest/test-conversions.cc
@@ -104,8 +104,10 @@
   CHECK_EQ(0.0, StringToDouble("000", NO_FLAGS));
   CHECK_EQ(1.0, StringToDouble("1", NO_FLAGS));
   CHECK_EQ(-1.0, StringToDouble("-1", NO_FLAGS));
-  CHECK_EQ(-1.0, StringToDouble("  -  1  ", NO_FLAGS));
-  CHECK_EQ(1.0, StringToDouble("  +  1  ", NO_FLAGS));
+  CHECK_EQ(-1.0, StringToDouble("  -1  ", NO_FLAGS));
+  CHECK_EQ(1.0, StringToDouble("  +1  ", NO_FLAGS));
+  CHECK(isnan(StringToDouble("  -  1  ", NO_FLAGS)));
+  CHECK(isnan(StringToDouble("  +  1  ", NO_FLAGS)));
 
   CHECK_EQ(0.0, StringToDouble("0e0", ALLOW_HEX | ALLOW_OCTALS));
   CHECK_EQ(0.0, StringToDouble("0e1", ALLOW_HEX | ALLOW_OCTALS));
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index 4dd7fe8..95314d7 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -1178,4 +1178,19 @@
   CHECK_EQ(0, stream.eos_signaled());
 }
 
+
+// Must not crash in debug mode.
+TEST(AggregatedHeapSnapshotJSONSerialization) {
+  v8::HandleScope scope;
+  LocalContext env;
+
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(
+          v8::String::New("agg"), v8::HeapSnapshot::kAggregated);
+  TestJSONStream stream;
+  snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
+  CHECK_GT(stream.size(), 0);
+  CHECK_EQ(1, stream.eos_signaled());
+}
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 7168737..710c10e 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -139,6 +139,12 @@
 class LoggerTestHelper : public AllStatic {
  public:
   static bool IsSamplerActive() { return Logger::IsProfilerSamplerActive(); }
+  static void ResetSamplesTaken() {
+    reinterpret_cast<Sampler*>(Logger::ticker_)->ResetSamplesTaken();
+  }
+  static bool has_samples_taken() {
+    return reinterpret_cast<Sampler*>(Logger::ticker_)->samples_taken() > 0;
+  }
 };
 
 }  // namespace v8::internal
@@ -147,24 +153,6 @@
 using v8::internal::LoggerTestHelper;
 
 
-// Under Linux, we need to check if signals were delivered to avoid false
-// positives.  Under other platforms profiling is done via a high-priority
-// thread, so this case never happen.
-static bool was_sigprof_received = true;
-#ifdef __linux__
-
-struct sigaction old_sigprof_handler;
-pthread_t our_thread;
-
-static void SigProfSignalHandler(int signal, siginfo_t* info, void* context) {
-  if (signal != SIGPROF || !pthread_equal(pthread_self(), our_thread)) return;
-  was_sigprof_received = true;
-  old_sigprof_handler.sa_sigaction(signal, info, context);
-}
-
-#endif  // __linux__
-
-
 namespace {
 
 class ScopedLoggerInitializer {
@@ -258,6 +246,9 @@
 
 
 static void CheckThatProfilerWorks(LogBufferMatcher* matcher) {
+  CHECK(!LoggerTestHelper::IsSamplerActive());
+  LoggerTestHelper::ResetSamplesTaken();
+
   Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 0);
   CHECK(LoggerTestHelper::IsSamplerActive());
 
@@ -266,19 +257,6 @@
   const char* code_creation = "\ncode-creation,";  // eq. to /^code-creation,/
   CHECK_NE(NULL, matcher->Find(code_creation));
 
-#ifdef __linux__
-  // Intercept SIGPROF handler to make sure that the test process
-  // had received it. Under load, system can defer it causing test failure.
-  // It is important to execute this after 'ResumeProfiler'.
-  our_thread = pthread_self();
-  was_sigprof_received = false;
-  struct sigaction sa;
-  sa.sa_sigaction = SigProfSignalHandler;
-  sigemptyset(&sa.sa_mask);
-  sa.sa_flags = SA_SIGINFO;
-  CHECK_EQ(0, sigaction(SIGPROF, &sa, &old_sigprof_handler));
-#endif  // __linux__
-
   // Force compiler to generate new code by parametrizing source.
   EmbeddedVector<char, 100> script_src;
   i::OS::SNPrintF(script_src,
@@ -306,7 +284,7 @@
   CHECK_NE(NULL, matcher->Find(code_creation));
   const char* tick = "\ntick,";
   const bool ticks_found = matcher->Find(tick) != NULL;
-  CHECK_EQ(was_sigprof_received, ticks_found);
+  CHECK_EQ(LoggerTestHelper::has_samples_taken(), ticks_found);
 }
 
 
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 243d478..a93fc27 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -263,8 +263,7 @@
     i::CompleteParserRecorder log;
     i::V8JavaScriptScanner scanner;
     scanner.Initialize(i::Handle<i::String>::null(), &stream);
-    v8::preparser::PreParser<i::V8JavaScriptScanner,
-                             i::CompleteParserRecorder> preparser;
+    v8::preparser::PreParser preparser;
     bool result = preparser.PreParseProgram(&scanner, &log, true);
     CHECK(result);
     i::ScriptDataImpl data(log.ExtractData());
diff --git a/test/mjsunit/regress/regress-944.js b/test/mjsunit/regress/regress-944.js
new file mode 100644
index 0000000..d165336
--- /dev/null
+++ b/test/mjsunit/regress/regress-944.js
@@ -0,0 +1,46 @@
+// Copyright 2010 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 for parsing of proper ES5 15.9.1.15 (ISO 8601 / RFC 3339) time
+// strings that contain millisecond values with exactly 3 digits (as is
+// required by the spec format if the string has milliseconds at all).
+assertEquals(1290722550521, Date.parse("2010-11-25T22:02:30.521Z"));
+
+// Check for parsing of extension/generalization of the ES5 15.9.1.15 spec
+// format where millisecond values have only 1 or 2 digits.
+assertEquals(1290722550500, Date.parse("2010-11-25T22:02:30.5Z"));
+assertEquals(1290722550520, Date.parse("2010-11-25T22:02:30.52Z"));
+assertFalse(Date.parse("2010-11-25T22:02:30.5Z") === Date.parse("2010-11-25T22:02:30.005Z"));
+
+// Check that we truncate millisecond values having more than 3 digits.
+assertEquals(Date.parse("2010-11-25T22:02:30.1005Z"), Date.parse("2010-11-25T22:02:30.100Z"));
+
+// Check that we accept lots of digits.
+assertEquals(Date.parse("2010-11-25T22:02:30.999Z"), Date.parse("2010-11-25T22:02:30.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999Z"));
+
+// Fail if there's a decimal point but zero digits for (expected) milliseconds.
+assertTrue(isNaN(Date.parse("2010-11-25T22:02:30.Z")));
diff --git a/test/mjsunit/string-split.js b/test/mjsunit/string-split.js
index c741f6a..6fcf557 100644
--- a/test/mjsunit/string-split.js
+++ b/test/mjsunit/string-split.js
@@ -97,3 +97,22 @@
 assertEquals([], ''.split(/.?/));
 assertEquals([], ''.split(/.??/));
 assertEquals([], ''.split(/()()/));
+
+
+// Issue http://code.google.com/p/v8/issues/detail?id=929
+// (Splitting with empty separator and a limit.)
+
+function numberObj(num) {
+  return {valueOf: function() { return num; }};
+}
+
+assertEquals([], "abc".split("", 0));
+assertEquals([], "abc".split("", numberObj(0)));
+assertEquals(["a"], "abc".split("", 1));
+assertEquals(["a"], "abc".split("", numberObj(1)));
+assertEquals(["a", "b"], "abc".split("", 2));
+assertEquals(["a", "b"], "abc".split("", numberObj(2)));
+assertEquals(["a", "b", "c"], "abc".split("", 3));
+assertEquals(["a", "b", "c"], "abc".split("", numberObj(3)));
+assertEquals(["a", "b", "c"], "abc".split("", 4));
+assertEquals(["a", "b", "c"], "abc".split("", numberObj(4)));
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 43e1bd4..c1a5aab 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -406,6 +406,10 @@
         '../../src/parser.cc',
         '../../src/parser.h',
         '../../src/platform.h',
+        '../../src/preparse-data.cc',
+        '../../src/preparse-data.h',
+        '../../src/preparser.cc',
+        '../../src/preparser.h',
         '../../src/prettyprinter.cc',
         '../../src/prettyprinter.h',
         '../../src/property.cc',
@@ -471,8 +475,11 @@
         '../../src/v8-counters.h',
         '../../src/v8.cc',
         '../../src/v8.h',
+        '../../src/v8checks.h',
+        '../../src/v8globals.h',
         '../../src/v8threads.cc',
         '../../src/v8threads.h',
+        '../../src/v8utils.h',
         '../../src/variables.cc',
         '../../src/variables.h',
         '../../src/version.cc',
diff --git a/tools/presubmit.py b/tools/presubmit.py
index ebf8bd8..1d80f92 100755
--- a/tools/presubmit.py
+++ b/tools/presubmit.py
@@ -195,7 +195,7 @@
               or (name in CppLintProcessor.IGNORE_LINT))
 
   def GetPathsToSearch(self):
-    return ['src', 'include', 'samples', join('test', 'cctest')]
+    return ['src', 'preparser', 'include', 'samples', join('test', 'cctest')]
 
   def ProcessFiles(self, files, path):
     good_files_cache = FileContentsCache('.cpplint-cache')
diff --git a/tools/visual_studio/v8_base.vcproj b/tools/visual_studio/v8_base.vcproj
index 95eb196..902faff 100644
--- a/tools/visual_studio/v8_base.vcproj
+++ b/tools/visual_studio/v8_base.vcproj
@@ -762,6 +762,22 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\preparser.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\preparser.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\preparse-data.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\preparse-data.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\profile-generator.cc"
 				>
 			</File>
@@ -1034,6 +1050,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\v8checks.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8globals.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\v8threads.cc"
 				>
 			</File>
@@ -1042,6 +1066,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\v8utils.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\variables.cc"
 				>
 			</File>
@@ -1157,6 +1185,10 @@
 				RelativePath="..\..\include\v8.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\include\v8stdint.h"
+				>
+			</File>
 		</Filter>
 	</Files>
 	<Globals>