Update V8 to r5901 as required by WebKit r73109

Change-Id: Ic48c5b085ce90e0151e2e7e58c4c5afe87fce9d1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..974628d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+*.a
+*.exe
+*.lib
+*.log
+*.map
+*.mk
+*.ncb
+*.pyc
+*.scons*
+*.suo
+*.user
+*.xcodeproj
+*.idb
+*.pdb
+#*#
+*~
+.cpplint-cache
+d8
+d8_g
+shell
+shell_g
+/obj/
+/tools/visual_studio/Debug
+/tools/visual_studio/Release
+/xcodebuild/
+TAGS
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/Android.v8common.mk b/Android.v8common.mk
index 90d1037..0c33d18 100644
--- a/Android.v8common.mk
+++ b/Android.v8common.mk
@@ -7,6 +7,7 @@
 	src/assembler.cc \
 	src/ast.cc \
 	src/bignum.cc \
+	src/bignum-dtoa.cc \
 	src/bootstrapper.cc \
 	src/builtins.cc \
 	src/cached-powers.cc \
@@ -27,6 +28,8 @@
 	src/diy-fp.cc \
 	src/dtoa.cc \
 	src/execution.cc \
+	src/extensions/externalize-string-extension.cc \
+	src/extensions/gc-extension.cc \
 	src/factory.cc \
 	src/fast-dtoa.cc \
 	src/fixed-dtoa.cc \
@@ -54,6 +57,8 @@
 	src/objects-visiting.cc \
 	src/oprofile-agent.cc \
 	src/parser.cc \
+	src/preparse-data.cc \
+	src/preparser.cc \
 	src/property.cc \
 	src/regexp-macro-assembler.cc \
 	src/regexp-macro-assembler-irregexp.cc \
@@ -132,9 +137,6 @@
 		src/regexp-macro-assembler-tracer.cc
 endif
 
-V8_LOCAL_SRC_FILES += \
-	src/dtoa-config.c
-
 # The order of these JS library sources is important. The order here determines
 # the ordering of the JS code in libraries.cc, which must be in a specific order
 # to meet compiler dependency requirements.
diff --git a/ChangeLog b/ChangeLog
index 573ebb3..86e41e1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,61 @@
+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.
+
+        Improved heap profiler precision and speed.
+
+        Reduced overhead of callback invocations on ARM.
+
+
+2010-11-18: Version 2.5.7
+
+        Fixed obscure evaluation order bug (issue 931).
+
+        Split the random number state between JavaScript and the private API.
+
+        Fixed performance bug causing GCs when generating stack traces on
+        code from very large scripts.
+
+        Fixed bug in parser that allowed (foo):42 as a labelled statement
+        (issue 918).
+
+        Provide more accurate results about used heap size via
+        GetHeapStatistics.
+
+        Allow build-time customization of the max semispace size.
+
+        Made String.prototype.split honor limit when separator is empty
+        (issue 929).
+
+        Added missing failure check after expecting an identifier in
+        preparser (Chromium issue 62639).
+
+
 2010-11-10: Version 2.5.6
 
         Added support for VFP rounding modes to the ARM simulator.
diff --git a/LICENSE b/LICENSE
index e3ed242..c1fcb1a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -12,9 +12,6 @@
     based on layout tests from webkit.org which are copyrighted by
     Apple Computer, Inc. and released under a 3-clause BSD license.
 
-  - Dtoa, located under third_party/dtoa.  This code is copyrighted by
-    David M. Gay and released under an MIT license.
-
   - Strongtalk assembler, the basis of the files assembler-arm-inl.h,
     assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h,
     assembler-ia32.cc, assembler-ia32.h, assembler.cc and assembler.h.
diff --git a/V8_MERGE_REVISION b/V8_MERGE_REVISION
index 59bb530..4900304 100644
--- a/V8_MERGE_REVISION
+++ b/V8_MERGE_REVISION
@@ -1,4 +1,4 @@
 We use a V8 revision that has been used for a Chromium release.
 
-http://src.chromium.org/svn/releases/9.0.589.0/DEPS
-http://v8.googlecode.com/svn/trunk@5804
+http://src.chromium.org/svn/releases/9.0.600.0/DEPS
+http://v8.googlecode.com/svn/trunk@5901
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index fb492d9..72195c4 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -197,8 +197,13 @@
     kContextVariable = 0,  // A variable from a function context.
     kElement = 1,          // An element of an array.
     kProperty = 2,         // A named object property.
-    kInternal = 3          // A link that can't be accessed from JS,
-                           // thus, its name isn't a real property name.
+    kInternal = 3,         // A link that can't be accessed from JS,
+                           // thus, its name isn't a real property name
+                           // (e.g. parts of a ConsString).
+    kHidden = 4,           // A link that is needed for proper sizes
+                           // calculation, but may be hidden from user.
+    kShortcut = 5          // A link that must not be followed during
+                           // sizes calculation.
   };
 
   /** Returns edge type (see HeapGraphEdge::Type). */
@@ -240,7 +245,8 @@
 class V8EXPORT HeapGraphNode {
  public:
   enum Type {
-    kInternal = 0,   // Internal node, a virtual one, for housekeeping.
+    kInternal = 0,   // For compatibility, will be removed.
+    kHidden = 0,     // Hidden node, may be filtered when shown to user.
     kArray = 1,      // An array of elements.
     kString = 2,     // A string.
     kObject = 3,     // A JS object (except for arrays and strings).
@@ -276,16 +282,19 @@
   /** Returns node's own size, in bytes. */
   int GetSelfSize() const;
 
-  /** Returns node's network (self + reachable nodes) size, in bytes. */
-  int GetReachableSize() const;
-
   /**
    * Returns node's retained size, in bytes. That is, self + sizes of
    * the objects that are reachable only from this object. In other
    * words, the size of memory that will be reclaimed having this node
    * collected.
+   *
+   * Exact retained size calculation has O(N) (number of nodes)
+   * computational complexity, while approximate has O(1). It is
+   * assumed that initially heap profiling tools provide approximate
+   * sizes for all nodes, and then exact sizes are calculated for the
+   * most 'interesting' nodes.
    */
-  int GetRetainedSize() const;
+  int GetRetainedSize(bool exact) const;
 
   /** Returns child nodes count of the node. */
   int GetChildrenCount() const;
@@ -304,6 +313,12 @@
 
   /** Returns a retaining path by index. */
   const HeapGraphPath* GetRetainingPath(int index) const;
+
+  /**
+   * Returns a dominator node. This is the node that participates in every
+   * path from the snapshot root to the current node.
+   */
+  const HeapGraphNode* GetDominatorNode() const;
 };
 
 
diff --git a/include/v8.h b/include/v8.h
index f6c3c8b..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. */
@@ -3282,8 +3287,8 @@
 
 namespace internal {
 
-const int kPointerSize = sizeof(void*);  // NOLINT
-const int kIntSize = sizeof(int);  // NOLINT
+static const int kApiPointerSize = sizeof(void*);  // NOLINT
+static const int kApiIntSize = sizeof(int);  // NOLINT
 
 // Tag information for HeapObject.
 const int kHeapObjectTag = 1;
@@ -3319,19 +3324,19 @@
   }
 };
 
-const int kSmiShiftSize = SmiConstants<kPointerSize>::kSmiShiftSize;
-const int kSmiValueSize = SmiConstants<kPointerSize>::kSmiValueSize;
+const int kSmiShiftSize = SmiConstants<kApiPointerSize>::kSmiShiftSize;
+const int kSmiValueSize = SmiConstants<kApiPointerSize>::kSmiValueSize;
 
 template <size_t ptr_size> struct InternalConstants;
 
 // Internal constants for 32-bit systems.
 template <> struct InternalConstants<4> {
-  static const int kStringResourceOffset = 3 * kPointerSize;
+  static const int kStringResourceOffset = 3 * kApiPointerSize;
 };
 
 // Internal constants for 64-bit systems.
 template <> struct InternalConstants<8> {
-  static const int kStringResourceOffset = 3 * kPointerSize;
+  static const int kStringResourceOffset = 3 * kApiPointerSize;
 };
 
 /**
@@ -3345,12 +3350,12 @@
   // These values match non-compiler-dependent values defined within
   // the implementation of v8.
   static const int kHeapObjectMapOffset = 0;
-  static const int kMapInstanceTypeOffset = kPointerSize + kIntSize;
+  static const int kMapInstanceTypeOffset = kApiPointerSize + kApiIntSize;
   static const int kStringResourceOffset =
-      InternalConstants<kPointerSize>::kStringResourceOffset;
+      InternalConstants<kApiPointerSize>::kStringResourceOffset;
 
-  static const int kProxyProxyOffset = kPointerSize;
-  static const int kJSObjectHeaderSize = 3 * kPointerSize;
+  static const int kProxyProxyOffset = kApiPointerSize;
+  static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
   static const int kFullStringRepresentationMask = 0x07;
   static const int kExternalTwoByteRepresentationTag = 0x02;
 
@@ -3368,7 +3373,7 @@
   }
 
   static inline int SmiValue(internal::Object* value) {
-    return SmiConstants<kPointerSize>::SmiToInt(value);
+    return SmiConstants<kApiPointerSize>::SmiToInt(value);
   }
 
   static inline int GetInstanceType(internal::Object* obj) {
@@ -3559,7 +3564,7 @@
     // If the object is a plain JSObject, which is the common case,
     // we know where to find the internal fields and can return the
     // value directly.
-    int offset = I::kJSObjectHeaderSize + (internal::kPointerSize * index);
+    int offset = I::kJSObjectHeaderSize + (internal::kApiPointerSize * index);
     O* value = I::ReadField<O*>(obj, offset);
     O** result = HandleScope::CreateHandle(value);
     return Local<Value>(reinterpret_cast<Value*>(result));
@@ -3595,7 +3600,7 @@
     // If the object is a plain JSObject, which is the common case,
     // we know where to find the internal fields and can return the
     // value directly.
-    int offset = I::kJSObjectHeaderSize + (internal::kPointerSize * index);
+    int offset = I::kJSObjectHeaderSize + (internal::kApiPointerSize * index);
     O* value = I::ReadField<O*>(obj, offset);
     return I::GetExternalPointer(value);
   }
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/src/SConscript b/src/SConscript
index 030c643..8953698 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -41,6 +41,7 @@
     assembler.cc
     ast.cc
     bignum.cc
+    bignum-dtoa.cc
     bootstrapper.cc
     builtins.cc
     cached-powers.cc
@@ -88,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
@@ -119,6 +122,8 @@
     version.cc
     virtual-frame.cc
     zone.cc
+    extensions/gc-extension.cc
+    extensions/externalize-string-extension.cc
     """),
   'arch:arm': Split("""
     jump-target-light.cc
@@ -294,14 +299,8 @@
   libraries_src, libraries_empty_src = env.JS2C(['libraries.cc', 'libraries-empty.cc'], library_files, TYPE='CORE')
   libraries_obj = context.ConfigureObject(env, libraries_src, CPPPATH=['.'])
 
-  # Build dtoa.
-  dtoa_env = env.Copy()
-  dtoa_env.Replace(**context.flags['dtoa'])
-  dtoa_files = ['dtoa-config.c']
-  dtoa_obj = context.ConfigureObject(dtoa_env, dtoa_files)
-
   source_objs = context.ConfigureObject(env, source_files)
-  non_snapshot_files = [dtoa_obj, source_objs]
+  non_snapshot_files = [source_objs]
 
   # Create snapshot if necessary.  For cross compilation you should either
   # do without snapshots and take the performance hit or you should build a
diff --git a/src/accessors.cc b/src/accessors.cc
index 7c21659..08ef41b 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -316,8 +316,10 @@
   InitScriptLineEnds(script);
   ASSERT(script->line_ends()->IsFixedArray());
   Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
-  Handle<FixedArray> copy = Factory::CopyFixedArray(line_ends);
-  Handle<JSArray> js_array = Factory::NewJSArrayWithElements(copy);
+  // We do not want anyone to modify this array from JS.
+  ASSERT(*line_ends == Heap::empty_fixed_array() ||
+         line_ends->map() == Heap::fixed_cow_array_map());
+  Handle<JSArray> js_array = Factory::NewJSArrayWithElements(line_ends);
   return *js_array;
 }
 
diff --git a/src/allocation.cc b/src/allocation.cc
index 678f4fd..d74c37c 100644
--- a/src/allocation.cc
+++ b/src/allocation.cc
@@ -27,16 +27,21 @@
 
 #include <stdlib.h>
 
-#include "v8.h"
+#include "../include/v8stdint.h"
+#include "globals.h"
+#include "checks.h"
+#include "allocation.h"
+#include "utils.h"
 
 namespace v8 {
 namespace internal {
 
-
 void* Malloced::New(size_t size) {
   ASSERT(NativeAllocationChecker::allocation_allowed());
   void* result = malloc(size);
-  if (result == NULL) V8::FatalProcessOutOfMemory("Malloced operator new");
+  if (result == NULL) {
+    v8::internal::FatalProcessOutOfMemory("Malloced operator new");
+  }
   return result;
 }
 
@@ -47,7 +52,7 @@
 
 
 void Malloced::FatalProcessOutOfMemory() {
-  V8::FatalProcessOutOfMemory("Out of memory");
+  v8::internal::FatalProcessOutOfMemory("Out of memory");
 }
 
 
@@ -82,7 +87,7 @@
 char* StrDup(const char* str) {
   int length = StrLength(str);
   char* result = NewArray<char>(length + 1);
-  memcpy(result, str, length * kCharSize);
+  memcpy(result, str, length);
   result[length] = '\0';
   return result;
 }
@@ -92,7 +97,7 @@
   int length = StrLength(str);
   if (n < length) length = n;
   char* result = NewArray<char>(length + 1);
-  memcpy(result, str, length * kCharSize);
+  memcpy(result, str, length);
   result[length] = '\0';
   return result;
 }
@@ -124,6 +129,7 @@
   }
   ASSERT(free_list_.next_ != &free_list_);
   ASSERT(free_list_.previous_ != &free_list_);
+
   size = (size + kPointerSize - 1) & ~(kPointerSize - 1);
   // Search for exact fit.
   for (PreallocatedStorage* storage = free_list_.next_;
diff --git a/src/allocation.h b/src/allocation.h
index 70a3a03..6f4bd2f 100644
--- a/src/allocation.h
+++ b/src/allocation.h
@@ -31,6 +31,10 @@
 namespace v8 {
 namespace internal {
 
+// Called when allocation routines fail to allocate.
+// This function should not return, but should terminate the current
+// processing.
+void FatalProcessOutOfMemory(const char* message);
 
 // A class that controls whether allocation is allowed.  This is for
 // the C++ heap only!
diff --git a/src/api.cc b/src/api.cc
index 9da3346..19af866 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -115,7 +115,6 @@
 }
 
 
-
 static FatalErrorCallback& GetFatalErrorHandler() {
   if (exception_behavior == NULL) {
     exception_behavior = DefaultFatalErrorHandler;
@@ -124,6 +123,10 @@
 }
 
 
+void i::FatalProcessOutOfMemory(const char* location) {
+  i::V8::FatalProcessOutOfMemory(location, false);
+}
+
 
 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
 // The default fatal error handler is called and execution is stopped.
@@ -2448,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;
@@ -4666,9 +4678,11 @@
     case i::HeapGraphEdge::kContextVariable:
     case i::HeapGraphEdge::kInternal:
     case i::HeapGraphEdge::kProperty:
+    case i::HeapGraphEdge::kShortcut:
       return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
           edge->name())));
     case i::HeapGraphEdge::kElement:
+    case i::HeapGraphEdge::kHidden:
       return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
           edge->index())));
     default: UNREACHABLE();
@@ -4758,15 +4772,9 @@
 }
 
 
-int HeapGraphNode::GetReachableSize() const {
-  IsDeadCheck("v8::HeapSnapshot::GetReachableSize");
-  return ToInternal(this)->ReachableSize();
-}
-
-
-int HeapGraphNode::GetRetainedSize() const {
+int HeapGraphNode::GetRetainedSize(bool exact) const {
   IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
-  return ToInternal(this)->RetainedSize();
+  return ToInternal(this)->RetainedSize(exact);
 }
 
 
@@ -4809,6 +4817,12 @@
 }
 
 
+const HeapGraphNode* HeapGraphNode::GetDominatorNode() const {
+  IsDeadCheck("v8::HeapSnapshot::GetDominatorNode");
+  return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->dominator());
+}
+
+
 const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
   IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
   i::HeapSnapshotsDiff* diff =
diff --git a/src/apiutils.h b/src/apiutils.h
index 1313dda..9683aa4 100644
--- a/src/apiutils.h
+++ b/src/apiutils.h
@@ -58,6 +58,9 @@
   static v8::Arguments NewArguments(internal::Object** implicit_args,
                                     internal::Object** argv, int argc,
                                     bool is_construct_call) {
+    ASSERT(implicit_args[v8::Arguments::kCalleeIndex]->IsJSFunction());
+    ASSERT(implicit_args[v8::Arguments::kHolderIndex]->IsHeapObject());
+
     return v8::Arguments(implicit_args, argv, argc, is_construct_call);
   }
 
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 de3931c..ee4c9aa 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -219,6 +219,11 @@
 const DwVfpRegister d14 = { 14 };
 const DwVfpRegister d15 = { 15 };
 
+// VFP FPSCR constants.
+static const uint32_t kVFPExceptionMask = 0xf;
+static const uint32_t kVFPRoundingModeMask = 3 << 22;
+static const uint32_t kVFPFlushToZeroMask = 1 << 24;
+static const uint32_t kVFPRoundToMinusInfinityBits = 2 << 22;
 
 // Coprocessor register
 struct CRegister {
@@ -1074,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);
@@ -1146,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);
@@ -1163,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/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index b3b0766..76a610b 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -100,8 +100,9 @@
 
   // Create a new closure through the slower runtime call.
   __ bind(&gc);
-  __ Push(cp, r3);
-  __ TailCallRuntime(Runtime::kNewClosure, 2, 1);
+  __ LoadRoot(r4, Heap::kFalseValueRootIndex);
+  __ Push(cp, r3, r4);
+  __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
 }
 
 
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index d7fd9a4..27e14df 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -43,6 +43,7 @@
 #include "register-allocator-inl.h"
 #include "runtime.h"
 #include "scopes.h"
+#include "stub-cache.h"
 #include "virtual-frame-inl.h"
 #include "virtual-frame-arm-inl.h"
 
@@ -557,7 +558,7 @@
 
 void CodeGenerator::LoadGlobal() {
   Register reg = frame_->GetTOSRegister();
-  __ ldr(reg, GlobalObject());
+  __ ldr(reg, GlobalObjectOperand());
   frame_->EmitPush(reg);
 }
 
@@ -1891,18 +1892,15 @@
   frame_->SpillAll();
   Comment cmnt(masm_, "[ check stack");
   __ LoadRoot(ip, Heap::kStackLimitRootIndex);
-  // Put the lr setup instruction in the delay slot.  kInstrSize is added to
-  // the implicit 8 byte offset that always applies to operations with pc and
-  // gives a return address 12 bytes down.
-  masm_->add(lr, pc, Operand(Assembler::kInstrSize));
   masm_->cmp(sp, Operand(ip));
   StackCheckStub stub;
   // Call the stub if lower.
-  masm_->mov(pc,
+  masm_->mov(ip,
              Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()),
                      RelocInfo::CODE_TARGET),
              LeaveCC,
              lo);
+  masm_->Call(ip, lo);
 }
 
 
@@ -3105,10 +3103,13 @@
 
 
 void CodeGenerator::InstantiateFunction(
-    Handle<SharedFunctionInfo> function_info) {
+    Handle<SharedFunctionInfo> function_info,
+    bool pretenure) {
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() && function_info->num_literals() == 0) {
+  if (scope()->is_function_scope() &&
+      function_info->num_literals() == 0 &&
+      !pretenure) {
     FastNewClosureStub stub;
     frame_->EmitPush(Operand(function_info));
     frame_->SpillAll();
@@ -3118,7 +3119,10 @@
     // Create a new closure.
     frame_->EmitPush(cp);
     frame_->EmitPush(Operand(function_info));
-    frame_->CallRuntime(Runtime::kNewClosure, 2);
+    frame_->EmitPush(Operand(pretenure
+                             ? Factory::true_value()
+                             : Factory::false_value()));
+    frame_->CallRuntime(Runtime::kNewClosure, 3);
     frame_->EmitPush(r0);
   }
 }
@@ -3138,7 +3142,7 @@
     ASSERT(frame_->height() == original_height);
     return;
   }
-  InstantiateFunction(function_info);
+  InstantiateFunction(function_info, node->pretenure());
   ASSERT_EQ(original_height + 1, frame_->height());
 }
 
@@ -3149,7 +3153,7 @@
   int original_height = frame_->height();
 #endif
   Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
-  InstantiateFunction(node->shared_function_info());
+  InstantiateFunction(node->shared_function_info(), false);
   ASSERT_EQ(original_height + 1, frame_->height());
 }
 
@@ -4232,7 +4236,7 @@
     // Setup the name register and call the IC initialization code.
     __ mov(r2, Operand(var->name()));
     InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
-    Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
+    Handle<Code> stub = StubCache::ComputeCallInitialize(arg_count, in_loop);
     CodeForSourcePosition(node->position());
     frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
                            arg_count + 1);
@@ -4326,7 +4330,8 @@
         // Set the name register and call the IC initialization code.
         __ mov(r2, Operand(name));
         InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
-        Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
+        Handle<Code> stub =
+            StubCache::ComputeCallInitialize(arg_count, in_loop);
         CodeForSourcePosition(node->position());
         frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
         __ ldr(cp, frame_->Context());
@@ -4337,9 +4342,12 @@
       // -------------------------------------------
       // JavaScript example: 'array[index](1, 2, 3)'
       // -------------------------------------------
+
+      // Load the receiver and name of the function.
       Load(property->obj());
+      Load(property->key());
+
       if (property->is_synthetic()) {
-        Load(property->key());
         EmitKeyedLoad();
         // Put the function below the receiver.
         // Use the global receiver.
@@ -4349,21 +4357,28 @@
         CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position());
         frame_->EmitPush(r0);
       } else {
+        // Swap the name of the function and the receiver on the stack to follow
+        // the calling convention for call ICs.
+        Register key = frame_->PopToRegister();
+        Register receiver = frame_->PopToRegister(key);
+        frame_->EmitPush(key);
+        frame_->EmitPush(receiver);
+
         // Load the arguments.
         int arg_count = args->length();
         for (int i = 0; i < arg_count; i++) {
           Load(args->at(i));
         }
 
-        // Set the name register and call the IC initialization code.
-        Load(property->key());
-        frame_->SpillAll();
-        frame_->EmitPop(r2);  // Function name.
-
+        // Load the key into r2 and call the IC initialization code.
         InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
-        Handle<Code> stub = ComputeKeyedCallInitialize(arg_count, in_loop);
+        Handle<Code> stub =
+            StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
         CodeForSourcePosition(node->position());
+        frame_->SpillAll();
+        __ ldr(r2, frame_->ElementAt(arg_count + 1));
         frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
+        frame_->Drop();  // Drop the key still on the stack.
         __ ldr(cp, frame_->Context());
         frame_->EmitPush(r0);
       }
@@ -5135,11 +5150,11 @@
     __ b(eq, &false_result);
     __ ldr(scratch1_, FieldMemOperand(scratch1_, HeapObject::kMapOffset));
     __ ldr(scratch2_,
-           CodeGenerator::ContextOperand(cp, Context::GLOBAL_INDEX));
+           ContextOperand(cp, Context::GLOBAL_INDEX));
     __ ldr(scratch2_,
            FieldMemOperand(scratch2_, GlobalObject::kGlobalContextOffset));
     __ ldr(scratch2_,
-           CodeGenerator::ContextOperand(
+           ContextOperand(
                scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
     __ cmp(scratch1_, scratch2_);
     __ b(ne, &false_result);
@@ -5807,6 +5822,15 @@
 }
 
 
+void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 2);
+  Load(args->at(0));
+  Register value = frame_->PopToRegister();
+  __ LoadRoot(value, Heap::kUndefinedValueRootIndex);
+  frame_->EmitPush(value);
+}
+
+
 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
 #ifdef DEBUG
   int original_height = frame_->height();
@@ -5825,7 +5849,7 @@
     // Prepare stack for calling JS runtime function.
     // Push the builtins object found in the current global object.
     Register scratch = VirtualFrame::scratch0();
-    __ ldr(scratch, GlobalObject());
+    __ ldr(scratch, GlobalObjectOperand());
     Register builtins = frame_->GetTOSRegister();
     __ ldr(builtins, FieldMemOperand(scratch, GlobalObject::kBuiltinsOffset));
     frame_->EmitPush(builtins);
@@ -5843,7 +5867,7 @@
     // Call the JS runtime function.
     __ mov(r2, Operand(node->name()));
     InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
-    Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
+    Handle<Code> stub = StubCache::ComputeCallInitialize(arg_count, in_loop);
     frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
     __ ldr(cp, frame_->Context());
     frame_->EmitPush(r0);
@@ -6000,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();
@@ -6059,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.
@@ -6073,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) {
@@ -6084,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
@@ -6513,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_;
 };
 
 
@@ -6549,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.
@@ -6616,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
@@ -6673,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
@@ -6721,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
@@ -6739,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,
@@ -6749,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
@@ -6765,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();
@@ -6788,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 97e50b4..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
 
@@ -279,10 +271,6 @@
     return inlined_write_barrier_size_ + 4;
   }
 
-  static MemOperand ContextOperand(Register context, int index) {
-    return MemOperand(context, Context::SlotOffset(index));
-  }
-
  private:
   // Type of a member function that generates inline code for a native function.
   typedef void (CodeGenerator::*InlineFunctionGenerator)
@@ -349,10 +337,6 @@
                                                JumpTarget* slow);
 
   // Expressions
-  static MemOperand GlobalObject()  {
-    return ContextOperand(cp, Context::GLOBAL_INDEX);
-  }
-
   void LoadCondition(Expression* x,
                      JumpTarget* true_target,
                      JumpTarget* false_target,
@@ -452,16 +436,13 @@
   static Handle<Code> ComputeLazyCompile(int argc);
   void ProcessDeclarations(ZoneList<Declaration*>* declarations);
 
-  static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
-
-  static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
-
   // Declare global variables and functions in the given array of
   // name/value pairs.
   void DeclareGlobals(Handle<FixedArray> pairs);
 
   // Instantiate the function based on the shared function info.
-  void InstantiateFunction(Handle<SharedFunctionInfo> function_info);
+  void InstantiateFunction(Handle<SharedFunctionInfo> function_info,
+                           bool pretenure);
 
   // Support for type checks.
   void GenerateIsSmi(ZoneList<Expression*>* args);
@@ -540,6 +521,7 @@
 
   void GenerateHasCachedArrayIndex(ZoneList<Expression*>* args);
   void GenerateGetCachedArrayIndex(ZoneList<Expression*>* args);
+  void GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args);
 
   // Simple condition analysis.
   enum ConditionAnalysis {
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/disasm-arm.cc b/src/arm/disasm-arm.cc
index 4e7580f..297a2db 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -1046,6 +1046,7 @@
 // Dd = vdiv(Dn, Dm)
 // vcmp(Dd, Dm)
 // vmrs
+// vmsr
 // Dd = vsqrt(Dm)
 void Decoder::DecodeTypeVFP(Instr* instr) {
   ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
@@ -1111,16 +1112,22 @@
     if ((instr->VCField() == 0x0) &&
         (instr->VAField() == 0x0)) {
       DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
-    } else if ((instr->VLField() == 0x1) &&
-               (instr->VCField() == 0x0) &&
+    } else if ((instr->VCField() == 0x0) &&
                (instr->VAField() == 0x7) &&
                (instr->Bits(19, 16) == 0x1)) {
-      if (instr->Bits(15, 12) == 0xF)
-        Format(instr, "vmrs'cond APSR, FPSCR");
-      else
-        Unknown(instr);  // Not used by V8.
-    } else {
-      Unknown(instr);  // Not used by V8.
+      if (instr->VLField() == 0) {
+        if (instr->Bits(15, 12) == 0xF) {
+          Format(instr, "vmsr'cond FPSCR, APSR");
+        } else {
+          Format(instr, "vmsr'cond FPSCR, 'rt");
+        }
+      } else {
+        if (instr->Bits(15, 12) == 0xF) {
+          Format(instr, "vmrs'cond APSR, FPSCR");
+        } else {
+          Format(instr, "vmrs'cond 'rt, FPSCR");
+        }
+      }
     }
   }
 }
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index bf27d0c..f04015b 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -36,6 +36,7 @@
 #include "full-codegen.h"
 #include "parser.h"
 #include "scopes.h"
+#include "stub-cache.h"
 
 namespace v8 {
 namespace internal {
@@ -171,19 +172,16 @@
   }
 
   // Check the stack for overflow or break request.
-  // Put the lr setup instruction in the delay slot.  The kInstrSize is
-  // added to the implicit 8 byte offset that always applies to operations
-  // with pc and gives a return address 12 bytes down.
   { Comment cmnt(masm_, "[ Stack check");
     __ LoadRoot(r2, Heap::kStackLimitRootIndex);
-    __ add(lr, pc, Operand(Assembler::kInstrSize));
     __ cmp(sp, Operand(r2));
     StackCheckStub stub;
-    __ mov(pc,
+    __ mov(ip,
            Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()),
                    RelocInfo::CODE_TARGET),
            LeaveCC,
            lo);
+    __ Call(ip, lo);
   }
 
   if (FLAG_trace) {
@@ -862,18 +860,23 @@
 }
 
 
-void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
+void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
+                                       bool pretenure) {
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() && info->num_literals() == 0) {
+  if (scope()->is_function_scope() &&
+      info->num_literals() == 0 &&
+      !pretenure) {
     FastNewClosureStub stub;
     __ mov(r0, Operand(info));
     __ push(r0);
     __ CallStub(&stub);
   } else {
     __ mov(r0, Operand(info));
-    __ Push(cp, r0);
-    __ CallRuntime(Runtime::kNewClosure, 2);
+    __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex
+                              : Heap::kFalseValueRootIndex);
+    __ Push(cp, r0, r1);
+    __ CallRuntime(Runtime::kNewClosure, 3);
   }
   context()->Plug(r0);
 }
@@ -1019,7 +1022,7 @@
     __ bind(&fast);
   }
 
-  __ ldr(r0, CodeGenerator::GlobalObject());
+  __ ldr(r0, GlobalObjectOperand());
   __ mov(r2, Operand(slot->var()->name()));
   RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
       ? RelocInfo::CODE_TARGET
@@ -1040,7 +1043,7 @@
     Comment cmnt(masm_, "Global variable");
     // Use inline caching. Variable name is passed in r2 and the global
     // object (receiver) in r0.
-    __ ldr(r0, CodeGenerator::GlobalObject());
+    __ ldr(r0, GlobalObjectOperand());
     __ mov(r2, Operand(var->name()));
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
@@ -1514,7 +1517,7 @@
     // assignment.  Right-hand-side value is passed in r0, variable name in
     // r2, and the global object in r1.
     __ mov(r2, Operand(var->name()));
-    __ ldr(r1, CodeGenerator::GlobalObject());
+    __ ldr(r1, GlobalObjectOperand());
     Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
@@ -1698,7 +1701,7 @@
   SetSourcePosition(expr->position(), FORCED_POSITION);
   // Call the IC initialization code.
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
+  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
   EmitCallIC(ic, mode);
   // Restore context register.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -1709,6 +1712,15 @@
 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
                                             Expression* key,
                                             RelocInfo::Mode mode) {
+  // Load the key.
+  VisitForAccumulatorValue(key);
+
+  // Swap the name of the function and the receiver on the stack to follow
+  // the calling convention for call ICs.
+  __ pop(r1);
+  __ push(r0);
+  __ push(r1);
+
   // Code common for calls using the IC.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
@@ -1716,19 +1728,17 @@
     for (int i = 0; i < arg_count; i++) {
       VisitForStackValue(args->at(i));
     }
-    VisitForAccumulatorValue(key);
-    __ mov(r2, r0);
   }
   // Record source position for debugger.
   SetSourcePosition(expr->position(), FORCED_POSITION);
   // Call the IC initialization code.
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
-                                                              in_loop);
+  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
+  __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize));  // Key.
   EmitCallIC(ic, mode);
   // Restore context register.
   __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
-  context()->Plug(r0);
+  context()->DropAndPlug(1, r0);  // Drop the key still on the stack.
 }
 
 
@@ -1809,7 +1819,7 @@
     context()->DropAndPlug(1, r0);
   } else if (var != NULL && !var->is_this() && var->is_global()) {
     // Push global object as receiver for the call IC.
-    __ ldr(r0, CodeGenerator::GlobalObject());
+    __ ldr(r0, GlobalObjectOperand());
     __ push(r0);
     EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
   } else if (var != NULL && var->AsSlot() != NULL &&
@@ -1845,7 +1855,7 @@
       // Push function.
       __ push(r0);
       // Push global receiver.
-      __ ldr(r1, CodeGenerator::GlobalObject());
+      __ ldr(r1, GlobalObjectOperand());
       __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
       __ push(r1);
       __ bind(&call);
@@ -1879,7 +1889,7 @@
 
         Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
         EmitCallIC(ic, RelocInfo::CODE_TARGET);
-        __ ldr(r1, CodeGenerator::GlobalObject());
+        __ ldr(r1, GlobalObjectOperand());
         __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
         __ Push(r0, r1);  // Function, receiver.
         EmitCallWithStub(expr);
@@ -1902,7 +1912,7 @@
       VisitForStackValue(fun);
     }
     // Load global receiver object.
-    __ ldr(r1, CodeGenerator::GlobalObject());
+    __ ldr(r1, GlobalObjectOperand());
     __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
     __ push(r1);
     // Emit function call.
@@ -2767,6 +2777,13 @@
 }
 
 
+void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
+  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
+  context()->Plug(r0);
+  return;
+}
+
+
 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   Handle<String> name = expr->name();
   if (name->length() > 0 && name->Get(0) == '_') {
@@ -2780,7 +2797,7 @@
 
   if (expr->is_jsruntime()) {
     // Prepare for calling JS runtime function.
-    __ ldr(r0, CodeGenerator::GlobalObject());
+    __ ldr(r0, GlobalObjectOperand());
     __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
     __ push(r0);
   }
@@ -2794,8 +2811,7 @@
   if (expr->is_jsruntime()) {
     // Call the JS runtime function.
     __ mov(r2, Operand(expr->name()));
-    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
-                                                           NOT_IN_LOOP);
+    Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, NOT_IN_LOOP);
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
     // Restore context register.
     __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -2832,7 +2848,7 @@
           VisitForStackValue(prop->obj());
           VisitForStackValue(prop->key());
         } else if (var->is_global()) {
-          __ ldr(r1, CodeGenerator::GlobalObject());
+          __ ldr(r1, GlobalObjectOperand());
           __ mov(r0, Operand(var->name()));
           __ Push(r1, r0);
         } else {
@@ -3098,7 +3114,7 @@
   VariableProxy* proxy = expr->AsVariableProxy();
   if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
     Comment cmnt(masm_, "Global variable");
-    __ ldr(r0, CodeGenerator::GlobalObject());
+    __ ldr(r0, GlobalObjectOperand());
     __ mov(r2, Operand(proxy->name()));
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     // Use a regular load, not a contextual load, to avoid a reference
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 48a8059..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
@@ -727,6 +769,16 @@
 // -----------------------------------------------------------------------------
 // Static helper functions.
 
+static MemOperand ContextOperand(Register context, int index) {
+  return MemOperand(context, Context::SlotOffset(index));
+}
+
+
+static inline MemOperand GlobalObjectOperand()  {
+  return ContextOperand(cp, Context::GLOBAL_INDEX);
+}
+
+
 #ifdef GENERATED_CODE_COVERAGE
 #define CODE_COVERAGE_STRINGIFY(x) #x
 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 5e29c2e..0a5eac2 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -598,8 +598,8 @@
                                 int argc) {
   // Get the function and setup the context.
   JSFunction* function = optimization.constant_function();
-  __ mov(r7, Operand(Handle<JSFunction>(function)));
-  __ ldr(cp, FieldMemOperand(r7, JSFunction::kContextOffset));
+  __ mov(r5, Operand(Handle<JSFunction>(function)));
+  __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset));
 
   // Pass the additional arguments FastHandleApiCall expects.
   bool info_loaded = false;
@@ -607,18 +607,18 @@
   if (Heap::InNewSpace(callback)) {
     info_loaded = true;
     __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info()));
-    __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kCallbackOffset));
+    __ ldr(r7, FieldMemOperand(r0, CallHandlerInfo::kCallbackOffset));
   } else {
-    __ Move(r6, Handle<Object>(callback));
+    __ Move(r7, Handle<Object>(callback));
   }
   Object* call_data = optimization.api_call_info()->data();
   if (Heap::InNewSpace(call_data)) {
     if (!info_loaded) {
       __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info()));
     }
-    __ ldr(r5, FieldMemOperand(r0, CallHandlerInfo::kDataOffset));
+    __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset));
   } else {
-    __ Move(r5, Handle<Object>(call_data));
+    __ Move(r6, Handle<Object>(call_data));
   }
 
   __ add(sp, sp, Operand(1 * kPointerSize));
@@ -1082,10 +1082,9 @@
 
   // Push the arguments on the JS stack of the caller.
   __ push(receiver);  // Receiver.
-  __ push(reg);  // Holder.
-  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback data
-  __ ldr(reg, FieldMemOperand(ip, AccessorInfo::kDataOffset));
-  __ Push(ip, reg, name_reg);
+  __ mov(scratch3, Operand(Handle<AccessorInfo>(callback)));  // callback data
+  __ ldr(ip, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
+  __ Push(reg, ip, scratch3, name_reg);
 
   // Do tail-call to the runtime system.
   ExternalReference load_callback_property =
@@ -1208,15 +1207,15 @@
       // holder_reg is either receiver or scratch1.
       if (!receiver.is(holder_reg)) {
         ASSERT(scratch1.is(holder_reg));
-        __ Push(receiver, holder_reg, scratch2);
-        __ ldr(scratch1,
-               FieldMemOperand(holder_reg, AccessorInfo::kDataOffset));
-        __ Push(scratch1, name_reg);
+        __ Push(receiver, holder_reg);
+        __ ldr(scratch3,
+               FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
+        __ Push(scratch3, scratch2, name_reg);
       } else {
         __ push(receiver);
-        __ ldr(scratch1,
-               FieldMemOperand(holder_reg, AccessorInfo::kDataOffset));
-        __ Push(holder_reg, scratch2, scratch1, name_reg);
+        __ ldr(scratch3,
+               FieldMemOperand(scratch2, AccessorInfo::kDataOffset));
+        __ Push(holder_reg, scratch3, scratch2, name_reg);
       }
 
       ExternalReference ref =
@@ -1360,10 +1359,11 @@
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
   // -----------------------------------
 
-  // TODO(639): faster implementation.
-
   // If object is not an array, bail out to regular call.
   if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
 
@@ -1371,20 +1371,133 @@
 
   GenerateNameCheck(name, &miss);
 
+  Register receiver = r1;
+
   // Get the receiver from the stack
   const int argc = arguments().immediate();
-  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
 
   // Check that the receiver isn't a smi.
-  __ tst(r1, Operand(kSmiTagMask));
-  __ b(eq, &miss);
+  __ BranchOnSmi(receiver, &miss);
 
   // Check that the maps haven't changed.
-  CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss);
+  CheckPrototypes(JSObject::cast(object), receiver,
+                  holder, r3, r0, r4, name, &miss);
 
-  __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
-                               argc + 1,
-                               1);
+  if (argc == 0) {
+    // Nothing to do, just return the length.
+    __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+    __ Drop(argc + 1);
+    __ Ret();
+  } else {
+    Label call_builtin;
+
+    Register elements = r3;
+    Register end_elements = r5;
+
+    // Get the elements array of the object.
+    __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
+
+    // Check that the elements are in fast mode and writable.
+    __ CheckMap(elements, r0,
+                Heap::kFixedArrayMapRootIndex, &call_builtin, true);
+
+    if (argc == 1) {  // Otherwise fall through to call the builtin.
+      Label exit, with_write_barrier, attempt_to_grow_elements;
+
+      // Get the array's length into r0 and calculate new length.
+      __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      STATIC_ASSERT(kSmiTagSize == 1);
+      STATIC_ASSERT(kSmiTag == 0);
+      __ add(r0, r0, Operand(Smi::FromInt(argc)));
+
+      // Get the element's length.
+      __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
+
+      // Check if we could survive without allocation.
+      __ cmp(r0, r4);
+      __ b(gt, &attempt_to_grow_elements);
+
+      // Save new length.
+      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+
+      // Push the element.
+      __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
+      // We may need a register containing the address end_elements below,
+      // so write back the value in end_elements.
+      __ add(end_elements, elements,
+             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+      const int kEndElementsOffset =
+          FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
+      __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex));
+
+      // Check for a smi.
+      __ BranchOnNotSmi(r4, &with_write_barrier);
+      __ bind(&exit);
+      __ Drop(argc + 1);
+      __ Ret();
+
+      __ bind(&with_write_barrier);
+      __ InNewSpace(elements, r4, eq, &exit);
+      __ RecordWriteHelper(elements, end_elements, r4);
+      __ Drop(argc + 1);
+      __ Ret();
+
+      __ bind(&attempt_to_grow_elements);
+      // r0: array's length + 1.
+      // r4: elements' length.
+
+      if (!FLAG_inline_new) {
+        __ b(&call_builtin);
+      }
+
+      ExternalReference new_space_allocation_top =
+          ExternalReference::new_space_allocation_top_address();
+      ExternalReference new_space_allocation_limit =
+          ExternalReference::new_space_allocation_limit_address();
+
+      const int kAllocationDelta = 4;
+      // Load top and check if it is the end of elements.
+      __ add(end_elements, elements,
+             Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
+      __ add(end_elements, end_elements, Operand(kEndElementsOffset));
+      __ mov(r7, Operand(new_space_allocation_top));
+      __ ldr(r6, MemOperand(r7));
+      __ cmp(end_elements, r6);
+      __ b(ne, &call_builtin);
+
+      __ mov(r9, Operand(new_space_allocation_limit));
+      __ ldr(r9, MemOperand(r9));
+      __ add(r6, r6, Operand(kAllocationDelta * kPointerSize));
+      __ cmp(r6, r9);
+      __ b(hi, &call_builtin);
+
+      // We fit and could grow elements.
+      // Update new_space_allocation_top.
+      __ str(r6, MemOperand(r7));
+      // Push the argument.
+      __ ldr(r6, MemOperand(sp, (argc - 1) * kPointerSize));
+      __ str(r6, MemOperand(end_elements));
+      // Fill the rest with holes.
+      __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
+      for (int i = 1; i < kAllocationDelta; i++) {
+        __ str(r6, MemOperand(end_elements, i * kPointerSize));
+      }
+
+      // Update elements' and array's sizes.
+      __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
+      __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
+
+      // Elements are in new space, so write barrier is not required.
+      __ Drop(argc + 1);
+      __ Ret();
+    }
+    __ bind(&call_builtin);
+    __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
+                                 argc + 1,
+                                 1);
+  }
 
   // Handle call cache miss.
   __ bind(&miss);
@@ -1406,28 +1519,68 @@
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
   // -----------------------------------
 
-  // TODO(642): faster implementation.
-
   // If object is not an array, bail out to regular call.
   if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value();
 
-  Label miss;
+  Label miss, return_undefined, call_builtin;
+
+  Register receiver = r1;
+  Register elements = r3;
 
   GenerateNameCheck(name, &miss);
 
   // Get the receiver from the stack
   const int argc = arguments().immediate();
-  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+  __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
 
   // Check that the receiver isn't a smi.
-  __ tst(r1, Operand(kSmiTagMask));
-  __ b(eq, &miss);
+  __ BranchOnSmi(receiver, &miss);
 
   // Check that the maps haven't changed.
-  CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss);
+  CheckPrototypes(JSObject::cast(object),
+                  receiver, holder, elements, r4, r0, name, &miss);
 
+  // Get the elements array of the object.
+  __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
+
+  // Check that the elements are in fast mode and writable.
+  __ CheckMap(elements, r0, Heap::kFixedArrayMapRootIndex, &call_builtin, true);
+
+  // Get the array's length into r4 and calculate new length.
+  __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
+  __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC);
+  __ b(lt, &return_undefined);
+
+  // Get the last element.
+  __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
+  STATIC_ASSERT(kSmiTagSize == 1);
+  STATIC_ASSERT(kSmiTag == 0);
+  // We can't address the last element in one operation. Compute the more
+  // expensive shift first, and use an offset later on.
+  __ add(elements, elements, Operand(r4, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ ldr(r0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
+  __ cmp(r0, r6);
+  __ b(eq, &call_builtin);
+
+  // Set the array's length.
+  __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset));
+
+  // Fill with the hole.
+  __ str(r6, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag));
+  __ Drop(argc + 1);
+  __ Ret();
+
+  __ bind(&return_undefined);
+  __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
+  __ Drop(argc + 1);
+  __ Ret();
+
+  __ bind(&call_builtin);
   __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
                                argc + 1,
                                1);
@@ -1676,8 +1829,143 @@
                                                     JSGlobalPropertyCell* cell,
                                                     JSFunction* function,
                                                     String* name) {
-  // TODO(872): implement this.
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- r2                     : function name
+  //  -- lr                     : return address
+  //  -- sp[(argc - n - 1) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- sp[argc * 4]           : receiver
+  // -----------------------------------
+
+  if (!CpuFeatures::IsSupported(VFP3)) return Heap::undefined_value();
+  CpuFeatures::Scope scope_vfp3(VFP3);
+
+  const int argc = arguments().immediate();
+
+  // If the object is not a JSObject or we got an unexpected number of
+  // arguments, bail out to the regular call.
+  if (!object->IsJSObject() || argc != 1) return Heap::undefined_value();
+
+  Label miss, slow;
+  GenerateNameCheck(name, &miss);
+
+  if (cell == NULL) {
+    __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
+
+    STATIC_ASSERT(kSmiTag == 0);
+    __ BranchOnSmi(r1, &miss);
+
+    CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
+                    &miss);
+  } else {
+    ASSERT(cell->value() == function);
+    GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
+    GenerateLoadFunctionFromCell(cell, function, &miss);
+  }
+
+  // Load the (only) argument into r0.
+  __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
+
+  // If the argument is a smi, just return.
+  STATIC_ASSERT(kSmiTag == 0);
+  __ tst(r0, Operand(kSmiTagMask));
+  __ Drop(argc + 1, eq);
+  __ Ret(eq);
+
+  __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, true);
+
+  Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return;
+
+  // If vfp3 is enabled, we use the fpu rounding with the RM (round towards
+  // minus infinity) mode.
+
+  // Load the HeapNumber value.
+  // We will need access to the value in the core registers, so we load it
+  // with ldrd and move it to the fpu. It also spares a sub instruction for
+  // updating the HeapNumber value address, as vldr expects a multiple
+  // of 4 offset.
+  __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset));
+  __ vmov(d1, r4, r5);
+
+  // Backup FPSCR.
+  __ vmrs(r3);
+  // Set custom FPCSR:
+  //  - Set rounding mode to "Round towards Minus Infinity"
+  //    (ie bits [23:22] = 0b10).
+  //  - Clear vfp cumulative exception flags (bits [3:0]).
+  //  - Make sure Flush-to-zero mode control bit is unset (bit 22).
+  __ bic(r9, r3,
+      Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask));
+  __ orr(r9, r9, Operand(kVFPRoundToMinusInfinityBits));
+  __ vmsr(r9);
+
+  // Convert the argument to an integer.
+  __ vcvt_s32_f64(s0, d1, Assembler::FPSCRRounding, al);
+
+  // Use vcvt latency to start checking for special cases.
+  // Get the argument exponent and clear the sign bit.
+  __ bic(r6, r5, Operand(HeapNumber::kSignMask));
+  __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord));
+
+  // Retrieve FPSCR and check for vfp exceptions.
+  __ vmrs(r9);
+  __ tst(r9, Operand(kVFPExceptionMask));
+  __ b(&no_vfp_exception, eq);
+
+  // Check for NaN, Infinity, and -Infinity.
+  // They are invariant through a Math.Floor call, so just
+  // return the original argument.
+  __ sub(r7, r6, Operand(HeapNumber::kExponentMask
+        >> HeapNumber::kMantissaBitsInTopWord), SetCC);
+  __ b(&restore_fpscr_and_return, eq);
+  // We had an overflow or underflow in the conversion. Check if we
+  // have a big exponent.
+  __ cmp(r7, Operand(HeapNumber::kMantissaBits));
+  // If greater or equal, the argument is already round and in r0.
+  __ b(&restore_fpscr_and_return, ge);
+  __ b(&slow);
+
+  __ bind(&no_vfp_exception);
+  // Move the result back to general purpose register r0.
+  __ vmov(r0, s0);
+  // Check if the result fits into a smi.
+  __ add(r1, r0, Operand(0x40000000), SetCC);
+  __ b(&wont_fit_smi, mi);
+  // Tag the result.
+  STATIC_ASSERT(kSmiTag == 0);
+  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
+
+  // Check for -0.
+  __ cmp(r0, Operand(0));
+  __ b(&restore_fpscr_and_return, ne);
+  // r5 already holds the HeapNumber exponent.
+  __ tst(r5, Operand(HeapNumber::kSignMask));
+  // If our HeapNumber is negative it was -0, so load its address and return.
+  // Else r0 is loaded with 0, so we can also just return.
+  __ ldr(r0, MemOperand(sp, 0 * kPointerSize), ne);
+
+  __ bind(&restore_fpscr_and_return);
+  // Restore FPSCR and return.
+  __ vmsr(r3);
+  __ Drop(argc + 1);
+  __ Ret();
+
+  __ bind(&wont_fit_smi);
+  __ bind(&slow);
+  // Restore FPCSR and fall to slow case.
+  __ vmsr(r3);
+
+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
+  __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
+
+  __ bind(&miss);
+  // r2: function name.
+  MaybeObject* obj = GenerateMissBranch();
+  if (obj->IsFailure()) return obj;
+
+  // Return the generated code.
+  return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
 }
 
 
@@ -2537,7 +2825,7 @@
   //  -- r1    : receiver
   // -----------------------------------
   Label miss;
-  __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
+  __ IncrementCounter(&Counters::keyed_load_string_length, 1, r2, r3);
 
   // Check the key is the cached one.
   __ cmp(r0, Operand(Handle<String>(name)));
@@ -2545,7 +2833,7 @@
 
   GenerateLoadStringLength(masm(), r1, r2, r3, &miss);
   __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
+  __ DecrementCounter(&Counters::keyed_load_string_length, 1, r2, r3);
 
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
@@ -2553,13 +2841,23 @@
 }
 
 
-// TODO(1224671): implement the fast case.
 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
   // ----------- S t a t e -------------
   //  -- lr    : return address
   //  -- r0    : key
   //  -- r1    : receiver
   // -----------------------------------
+  Label miss;
+
+  __ IncrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3);
+
+  // Check the name hasn't changed.
+  __ cmp(r0, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
+  __ bind(&miss);
+  __ DecrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3);
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   return GetCode(CALLBACKS, name);
@@ -2604,8 +2902,7 @@
 }
 
 
-MaybeObject* ConstructStubCompiler::CompileConstructStub(
-    SharedFunctionInfo* shared) {
+MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
   // ----------- S t a t e -------------
   //  -- r0    : argc
   //  -- r1    : constructor
@@ -2689,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;
@@ -2713,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/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc
index da76edf..45f4876 100644
--- a/src/arm/virtual-frame-arm.cc
+++ b/src/arm/virtual-frame-arm.cc
@@ -245,18 +245,15 @@
     __ LoadRoot(r2, Heap::kStackLimitRootIndex);
   }
   // Check the stack for overflow or a break request.
-  // Put the lr setup instruction in the delay slot.  The kInstrSize is added
-  // to the implicit 8 byte offset that always applies to operations with pc
-  // and gives a return address 12 bytes down.
-  masm()->add(lr, pc, Operand(Assembler::kInstrSize));
   masm()->cmp(sp, Operand(r2));
   StackCheckStub stub;
   // Call the stub if lower.
-  masm()->mov(pc,
+  masm()->mov(ip,
               Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()),
                       RelocInfo::CODE_TARGET),
               LeaveCC,
               lo);
+  masm()->Call(ip, lo);
 }
 
 
diff --git a/src/array.js b/src/array.js
index b2ebece..5ecf5e3 100644
--- a/src/array.js
+++ b/src/array.js
@@ -364,6 +364,10 @@
   } else if (!IS_STRING(separator)) {
     separator = ToString(separator);
   }
+
+  var result = %_FastAsciiArrayJoin(this, separator);
+  if (typeof result != "undefined") return result;
+
   var length = TO_UINT32(this.length);
   return Join(this, length, separator, ConvertToString);
 }
diff --git a/src/ast.h b/src/ast.h
index 04c2977..0846dbc 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1416,7 +1416,8 @@
         contains_loops_(contains_loops),
         function_token_position_(RelocInfo::kNoPosition),
         inferred_name_(Heap::empty_string()),
-        try_full_codegen_(false) {
+        try_full_codegen_(false),
+        pretenure_(false) {
 #ifdef DEBUG
     already_compiled_ = false;
 #endif
@@ -1459,6 +1460,9 @@
   bool try_full_codegen() { return try_full_codegen_; }
   void set_try_full_codegen(bool flag) { try_full_codegen_ = flag; }
 
+  bool pretenure() { return pretenure_; }
+  void set_pretenure(bool value) { pretenure_ = value; }
+
 #ifdef DEBUG
   void mark_as_compiled() {
     ASSERT(!already_compiled_);
@@ -1482,6 +1486,7 @@
   int function_token_position_;
   Handle<String> inferred_name_;
   bool try_full_codegen_;
+  bool pretenure_;
 #ifdef DEBUG
   bool already_compiled_;
 #endif
diff --git a/src/bignum-dtoa.cc b/src/bignum-dtoa.cc
new file mode 100644
index 0000000..088dd79
--- /dev/null
+++ b/src/bignum-dtoa.cc
@@ -0,0 +1,655 @@
+// 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 <math.h>
+
+#include "v8.h"
+#include "bignum-dtoa.h"
+
+#include "bignum.h"
+#include "double.h"
+
+namespace v8 {
+namespace internal {
+
+static int NormalizedExponent(uint64_t significand, int exponent) {
+  ASSERT(significand != 0);
+  while ((significand & Double::kHiddenBit) == 0) {
+    significand = significand << 1;
+    exponent = exponent - 1;
+  }
+  return exponent;
+}
+
+
+// Forward declarations:
+// Returns an estimation of k such that 10^(k-1) <= v < 10^k.
+static int EstimatePower(int exponent);
+// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
+// and denominator.
+static void InitialScaledStartValues(double v,
+                                     int estimated_power,
+                                     bool need_boundary_deltas,
+                                     Bignum* numerator,
+                                     Bignum* denominator,
+                                     Bignum* delta_minus,
+                                     Bignum* delta_plus);
+// Multiplies numerator/denominator so that its values lies in the range 1-10.
+// Returns decimal_point s.t.
+//  v = numerator'/denominator' * 10^(decimal_point-1)
+//     where numerator' and denominator' are the values of numerator and
+//     denominator after the call to this function.
+static void FixupMultiply10(int estimated_power, bool is_even,
+                            int* decimal_point,
+                            Bignum* numerator, Bignum* denominator,
+                            Bignum* delta_minus, Bignum* delta_plus);
+// Generates digits from the left to the right and stops when the generated
+// digits yield the shortest decimal representation of v.
+static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
+                                   Bignum* delta_minus, Bignum* delta_plus,
+                                   bool is_even,
+                                   Vector<char> buffer, int* length);
+// Generates 'requested_digits' after the decimal point.
+static void BignumToFixed(int requested_digits, int* decimal_point,
+                          Bignum* numerator, Bignum* denominator,
+                          Vector<char>(buffer), int* length);
+// Generates 'count' digits of numerator/denominator.
+// Once 'count' digits have been produced rounds the result depending on the
+// remainder (remainders of exactly .5 round upwards). Might update the
+// decimal_point when rounding up (for example for 0.9999).
+static void GenerateCountedDigits(int count, int* decimal_point,
+                                  Bignum* numerator, Bignum* denominator,
+                                  Vector<char>(buffer), int* length);
+
+
+void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
+                Vector<char> buffer, int* length, int* decimal_point) {
+  ASSERT(v > 0);
+  ASSERT(!Double(v).IsSpecial());
+  uint64_t significand = Double(v).Significand();
+  bool is_even = (significand & 1) == 0;
+  int exponent = Double(v).Exponent();
+  int normalized_exponent = NormalizedExponent(significand, exponent);
+  // estimated_power might be too low by 1.
+  int estimated_power = EstimatePower(normalized_exponent);
+
+  // Shortcut for Fixed.
+  // The requested digits correspond to the digits after the point. If the
+  // number is much too small, then there is no need in trying to get any
+  // digits.
+  if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
+    buffer[0] = '\0';
+    *length = 0;
+    // Set decimal-point to -requested_digits. This is what Gay does.
+    // Note that it should not have any effect anyways since the string is
+    // empty.
+    *decimal_point = -requested_digits;
+    return;
+  }
+
+  Bignum numerator;
+  Bignum denominator;
+  Bignum delta_minus;
+  Bignum delta_plus;
+  // Make sure the bignum can grow large enough. The smallest double equals
+  // 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
+  // The maximum double is 1.7976931348623157e308 which needs fewer than
+  // 308*4 binary digits.
+  ASSERT(Bignum::kMaxSignificantBits >= 324*4);
+  bool need_boundary_deltas = (mode == BIGNUM_DTOA_SHORTEST);
+  InitialScaledStartValues(v, estimated_power, need_boundary_deltas,
+                           &numerator, &denominator,
+                           &delta_minus, &delta_plus);
+  // We now have v = (numerator / denominator) * 10^estimated_power.
+  FixupMultiply10(estimated_power, is_even, decimal_point,
+                  &numerator, &denominator,
+                  &delta_minus, &delta_plus);
+  // We now have v = (numerator / denominator) * 10^(decimal_point-1), and
+  //  1 <= (numerator + delta_plus) / denominator < 10
+  switch (mode) {
+    case BIGNUM_DTOA_SHORTEST:
+      GenerateShortestDigits(&numerator, &denominator,
+                             &delta_minus, &delta_plus,
+                             is_even, buffer, length);
+      break;
+    case BIGNUM_DTOA_FIXED:
+      BignumToFixed(requested_digits, decimal_point,
+                    &numerator, &denominator,
+                    buffer, length);
+      break;
+    case BIGNUM_DTOA_PRECISION:
+      GenerateCountedDigits(requested_digits, decimal_point,
+                            &numerator, &denominator,
+                            buffer, length);
+      break;
+    default:
+      UNREACHABLE();
+  }
+  buffer[*length] = '\0';
+}
+
+
+// The procedure starts generating digits from the left to the right and stops
+// when the generated digits yield the shortest decimal representation of v. A
+// decimal representation of v is a number lying closer to v than to any other
+// double, so it converts to v when read.
+//
+// This is true if d, the decimal representation, is between m- and m+, the
+// upper and lower boundaries. d must be strictly between them if !is_even.
+//           m- := (numerator - delta_minus) / denominator
+//           m+ := (numerator + delta_plus) / denominator
+//
+// Precondition: 0 <= (numerator+delta_plus) / denominator < 10.
+//   If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit
+//   will be produced. This should be the standard precondition.
+static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
+                                   Bignum* delta_minus, Bignum* delta_plus,
+                                   bool is_even,
+                                   Vector<char> buffer, int* length) {
+  // Small optimization: if delta_minus and delta_plus are the same just reuse
+  // one of the two bignums.
+  if (Bignum::Equal(*delta_minus, *delta_plus)) {
+    delta_plus = delta_minus;
+  }
+  *length = 0;
+  while (true) {
+    uint16_t digit;
+    digit = numerator->DivideModuloIntBignum(*denominator);
+    ASSERT(digit <= 9);  // digit is a uint16_t and therefore always positive.
+    // digit = numerator / denominator (integer division).
+    // numerator = numerator % denominator.
+    buffer[(*length)++] = digit + '0';
+
+    // Can we stop already?
+    // If the remainder of the division is less than the distance to the lower
+    // boundary we can stop. In this case we simply round down (discarding the
+    // remainder).
+    // Similarly we test if we can round up (using the upper boundary).
+    bool in_delta_room_minus;
+    bool in_delta_room_plus;
+    if (is_even) {
+      in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
+    } else {
+      in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
+    }
+    if (is_even) {
+      in_delta_room_plus =
+          Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
+    } else {
+      in_delta_room_plus =
+          Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
+    }
+    if (!in_delta_room_minus && !in_delta_room_plus) {
+      // Prepare for next iteration.
+      numerator->Times10();
+      delta_minus->Times10();
+      // We optimized delta_plus to be equal to delta_minus (if they share the
+      // same value). So don't multiply delta_plus if they point to the same
+      // object.
+      if (delta_minus != delta_plus) {
+        delta_plus->Times10();
+      }
+    } else if (in_delta_room_minus && in_delta_room_plus) {
+      // Let's see if 2*numerator < denominator.
+      // If yes, then the next digit would be < 5 and we can round down.
+      int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
+      if (compare < 0) {
+        // Remaining digits are less than .5. -> Round down (== do nothing).
+      } else if (compare > 0) {
+        // Remaining digits are more than .5 of denominator. -> Round up.
+        // Note that the last digit could not be a '9' as otherwise the whole
+        // loop would have stopped earlier.
+        // We still have an assert here in case the preconditions were not
+        // satisfied.
+        ASSERT(buffer[(*length) - 1] != '9');
+        buffer[(*length) - 1]++;
+      } else {
+        // Halfway case.
+        // TODO(floitsch): need a way to solve half-way cases.
+        //   For now let's round towards even (since this is what Gay seems to
+        //   do).
+
+        if ((buffer[(*length) - 1] - '0') % 2 == 0) {
+          // Round down => Do nothing.
+        } else {
+          ASSERT(buffer[(*length) - 1] != '9');
+          buffer[(*length) - 1]++;
+        }
+      }
+      return;
+    } else if (in_delta_room_minus) {
+      // Round down (== do nothing).
+      return;
+    } else {  // in_delta_room_plus
+      // Round up.
+      // Note again that the last digit could not be '9' since this would have
+      // stopped the loop earlier.
+      // We still have an ASSERT here, in case the preconditions were not
+      // satisfied.
+      ASSERT(buffer[(*length) -1] != '9');
+      buffer[(*length) - 1]++;
+      return;
+    }
+  }
+}
+
+
+// Let v = numerator / denominator < 10.
+// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
+// from left to right. Once 'count' digits have been produced we decide wether
+// to round up or down. Remainders of exactly .5 round upwards. Numbers such
+// as 9.999999 propagate a carry all the way, and change the
+// exponent (decimal_point), when rounding upwards.
+static void GenerateCountedDigits(int count, int* decimal_point,
+                                  Bignum* numerator, Bignum* denominator,
+                                  Vector<char>(buffer), int* length) {
+  ASSERT(count >= 0);
+  for (int i = 0; i < count - 1; ++i) {
+    uint16_t digit;
+    digit = numerator->DivideModuloIntBignum(*denominator);
+    ASSERT(digit <= 9);  // digit is a uint16_t and therefore always positive.
+    // digit = numerator / denominator (integer division).
+    // numerator = numerator % denominator.
+    buffer[i] = digit + '0';
+    // Prepare for next iteration.
+    numerator->Times10();
+  }
+  // Generate the last digit.
+  uint16_t digit;
+  digit = numerator->DivideModuloIntBignum(*denominator);
+  if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
+    digit++;
+  }
+  buffer[count - 1] = digit + '0';
+  // Correct bad digits (in case we had a sequence of '9's). Propagate the
+  // carry until we hat a non-'9' or til we reach the first digit.
+  for (int i = count - 1; i > 0; --i) {
+    if (buffer[i] != '0' + 10) break;
+    buffer[i] = '0';
+    buffer[i - 1]++;
+  }
+  if (buffer[0] == '0' + 10) {
+    // Propagate a carry past the top place.
+    buffer[0] = '1';
+    (*decimal_point)++;
+  }
+  *length = count;
+}
+
+
+// Generates 'requested_digits' after the decimal point. It might omit
+// trailing '0's. If the input number is too small then no digits at all are
+// generated (ex.: 2 fixed digits for 0.00001).
+//
+// Input verifies:  1 <= (numerator + delta) / denominator < 10.
+static void BignumToFixed(int requested_digits, int* decimal_point,
+                          Bignum* numerator, Bignum* denominator,
+                          Vector<char>(buffer), int* length) {
+  // Note that we have to look at more than just the requested_digits, since
+  // a number could be rounded up. Example: v=0.5 with requested_digits=0.
+  // Even though the power of v equals 0 we can't just stop here.
+  if (-(*decimal_point) > requested_digits) {
+    // The number is definitively too small.
+    // Ex: 0.001 with requested_digits == 1.
+    // Set decimal-point to -requested_digits. This is what Gay does.
+    // Note that it should not have any effect anyways since the string is
+    // empty.
+    *decimal_point = -requested_digits;
+    *length = 0;
+    return;
+  } else if (-(*decimal_point) == requested_digits) {
+    // We only need to verify if the number rounds down or up.
+    // Ex: 0.04 and 0.06 with requested_digits == 1.
+    ASSERT(*decimal_point == -requested_digits);
+    // Initially the fraction lies in range (1, 10]. Multiply the denominator
+    // by 10 so that we can compare more easily.
+    denominator->Times10();
+    if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
+      // If the fraction is >= 0.5 then we have to include the rounded
+      // digit.
+      buffer[0] = '1';
+      *length = 1;
+      (*decimal_point)++;
+    } else {
+      // Note that we caught most of similar cases earlier.
+      *length = 0;
+    }
+    return;
+  } else {
+    // The requested digits correspond to the digits after the point.
+    // The variable 'needed_digits' includes the digits before the point.
+    int needed_digits = (*decimal_point) + requested_digits;
+    GenerateCountedDigits(needed_digits, decimal_point,
+                          numerator, denominator,
+                          buffer, length);
+  }
+}
+
+
+// Returns an estimation of k such that 10^(k-1) <= v < 10^k where
+// v = f * 2^exponent and 2^52 <= f < 2^53.
+// v is hence a normalized double with the given exponent. The output is an
+// approximation for the exponent of the decimal approimation .digits * 10^k.
+//
+// The result might undershoot by 1 in which case 10^k <= v < 10^k+1.
+// Note: this property holds for v's upper boundary m+ too.
+//    10^k <= m+ < 10^k+1.
+//   (see explanation below).
+//
+// Examples:
+//  EstimatePower(0)   => 16
+//  EstimatePower(-52) => 0
+//
+// Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0.
+static int EstimatePower(int exponent) {
+  // This function estimates log10 of v where v = f*2^e (with e == exponent).
+  // Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)).
+  // Note that f is bounded by its container size. Let p = 53 (the double's
+  // significand size). Then 2^(p-1) <= f < 2^p.
+  //
+  // Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close
+  // to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)).
+  // The computed number undershoots by less than 0.631 (when we compute log3
+  // and not log10).
+  //
+  // Optimization: since we only need an approximated result this computation
+  // can be performed on 64 bit integers. On x86/x64 architecture the speedup is
+  // not really measurable, though.
+  //
+  // Since we want to avoid overshooting we decrement by 1e10 so that
+  // floating-point imprecisions don't affect us.
+  //
+  // Explanation for v's boundary m+: the computation takes advantage of
+  // the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement
+  // (even for denormals where the delta can be much more important).
+
+  const double k1Log10 = 0.30102999566398114;  // 1/lg(10)
+
+  // For doubles len(f) == 53 (don't forget the hidden bit).
+  const int kSignificandSize = 53;
+  double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
+  return static_cast<int>(estimate);
+}
+
+
+// See comments for InitialScaledStartValues.
+static void InitialScaledStartValuesPositiveExponent(
+    double v, int estimated_power, bool need_boundary_deltas,
+    Bignum* numerator, Bignum* denominator,
+    Bignum* delta_minus, Bignum* delta_plus) {
+  // A positive exponent implies a positive power.
+  ASSERT(estimated_power >= 0);
+  // Since the estimated_power is positive we simply multiply the denominator
+  // by 10^estimated_power.
+
+  // numerator = v.
+  numerator->AssignUInt64(Double(v).Significand());
+  numerator->ShiftLeft(Double(v).Exponent());
+  // denominator = 10^estimated_power.
+  denominator->AssignPowerUInt16(10, estimated_power);
+
+  if (need_boundary_deltas) {
+    // Introduce a common denominator so that the deltas to the boundaries are
+    // integers.
+    denominator->ShiftLeft(1);
+    numerator->ShiftLeft(1);
+    // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
+    // denominator (of 2) delta_plus equals 2^e.
+    delta_plus->AssignUInt16(1);
+    delta_plus->ShiftLeft(Double(v).Exponent());
+    // Same for delta_minus (with adjustments below if f == 2^p-1).
+    delta_minus->AssignUInt16(1);
+    delta_minus->ShiftLeft(Double(v).Exponent());
+
+    // If the significand (without the hidden bit) is 0, then the lower
+    // boundary is closer than just half a ulp (unit in the last place).
+    // There is only one exception: if the next lower number is a denormal then
+    // the distance is 1 ulp. This cannot be the case for exponent >= 0 (but we
+    // have to test it in the other function where exponent < 0).
+    uint64_t v_bits = Double(v).AsUint64();
+    if ((v_bits & Double::kSignificandMask) == 0) {
+      // The lower boundary is closer at half the distance of "normal" numbers.
+      // Increase the common denominator and adapt all but the delta_minus.
+      denominator->ShiftLeft(1);  // *2
+      numerator->ShiftLeft(1);    // *2
+      delta_plus->ShiftLeft(1);   // *2
+    }
+  }
+}
+
+
+// See comments for InitialScaledStartValues
+static void InitialScaledStartValuesNegativeExponentPositivePower(
+    double v, int estimated_power, bool need_boundary_deltas,
+    Bignum* numerator, Bignum* denominator,
+    Bignum* delta_minus, Bignum* delta_plus) {
+  uint64_t significand = Double(v).Significand();
+  int exponent = Double(v).Exponent();
+  // v = f * 2^e with e < 0, and with estimated_power >= 0.
+  // This means that e is close to 0 (have a look at how estimated_power is
+  // computed).
+
+  // numerator = significand
+  //  since v = significand * 2^exponent this is equivalent to
+  //  numerator = v * / 2^-exponent
+  numerator->AssignUInt64(significand);
+  // denominator = 10^estimated_power * 2^-exponent (with exponent < 0)
+  denominator->AssignPowerUInt16(10, estimated_power);
+  denominator->ShiftLeft(-exponent);
+
+  if (need_boundary_deltas) {
+    // Introduce a common denominator so that the deltas to the boundaries are
+    // integers.
+    denominator->ShiftLeft(1);
+    numerator->ShiftLeft(1);
+    // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
+    // denominator (of 2) delta_plus equals 2^e.
+    // Given that the denominator already includes v's exponent the distance
+    // to the boundaries is simply 1.
+    delta_plus->AssignUInt16(1);
+    // Same for delta_minus (with adjustments below if f == 2^p-1).
+    delta_minus->AssignUInt16(1);
+
+    // If the significand (without the hidden bit) is 0, then the lower
+    // boundary is closer than just one ulp (unit in the last place).
+    // There is only one exception: if the next lower number is a denormal
+    // then the distance is 1 ulp. Since the exponent is close to zero
+    // (otherwise estimated_power would have been negative) this cannot happen
+    // here either.
+    uint64_t v_bits = Double(v).AsUint64();
+    if ((v_bits & Double::kSignificandMask) == 0) {
+      // The lower boundary is closer at half the distance of "normal" numbers.
+      // Increase the denominator and adapt all but the delta_minus.
+      denominator->ShiftLeft(1);  // *2
+      numerator->ShiftLeft(1);    // *2
+      delta_plus->ShiftLeft(1);   // *2
+    }
+  }
+}
+
+
+// See comments for InitialScaledStartValues
+static void InitialScaledStartValuesNegativeExponentNegativePower(
+    double v, int estimated_power, bool need_boundary_deltas,
+    Bignum* numerator, Bignum* denominator,
+    Bignum* delta_minus, Bignum* delta_plus) {
+  const uint64_t kMinimalNormalizedExponent =
+      V8_2PART_UINT64_C(0x00100000, 00000000);
+  uint64_t significand = Double(v).Significand();
+  int exponent = Double(v).Exponent();
+  // Instead of multiplying the denominator with 10^estimated_power we
+  // multiply all values (numerator and deltas) by 10^-estimated_power.
+
+  // Use numerator as temporary container for power_ten.
+  Bignum* power_ten = numerator;
+  power_ten->AssignPowerUInt16(10, -estimated_power);
+
+  if (need_boundary_deltas) {
+    // Since power_ten == numerator we must make a copy of 10^estimated_power
+    // before we complete the computation of the numerator.
+    // delta_plus = delta_minus = 10^estimated_power
+    delta_plus->AssignBignum(*power_ten);
+    delta_minus->AssignBignum(*power_ten);
+  }
+
+  // numerator = significand * 2 * 10^-estimated_power
+  //  since v = significand * 2^exponent this is equivalent to
+  // numerator = v * 10^-estimated_power * 2 * 2^-exponent.
+  // Remember: numerator has been abused as power_ten. So no need to assign it
+  //  to itself.
+  ASSERT(numerator == power_ten);
+  numerator->MultiplyByUInt64(significand);
+
+  // denominator = 2 * 2^-exponent with exponent < 0.
+  denominator->AssignUInt16(1);
+  denominator->ShiftLeft(-exponent);
+
+  if (need_boundary_deltas) {
+    // Introduce a common denominator so that the deltas to the boundaries are
+    // integers.
+    numerator->ShiftLeft(1);
+    denominator->ShiftLeft(1);
+    // With this shift the boundaries have their correct value, since
+    // delta_plus = 10^-estimated_power, and
+    // delta_minus = 10^-estimated_power.
+    // These assignments have been done earlier.
+
+    // The special case where the lower boundary is twice as close.
+    // This time we have to look out for the exception too.
+    uint64_t v_bits = Double(v).AsUint64();
+    if ((v_bits & Double::kSignificandMask) == 0 &&
+        // The only exception where a significand == 0 has its boundaries at
+        // "normal" distances:
+        (v_bits & Double::kExponentMask) != kMinimalNormalizedExponent) {
+      numerator->ShiftLeft(1);    // *2
+      denominator->ShiftLeft(1);  // *2
+      delta_plus->ShiftLeft(1);   // *2
+    }
+  }
+}
+
+
+// Let v = significand * 2^exponent.
+// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
+// and denominator. The functions GenerateShortestDigits and
+// GenerateCountedDigits will then convert this ratio to its decimal
+// representation d, with the required accuracy.
+// Then d * 10^estimated_power is the representation of v.
+// (Note: the fraction and the estimated_power might get adjusted before
+// generating the decimal representation.)
+//
+// The initial start values consist of:
+//  - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.
+//  - a scaled (common) denominator.
+//  optionally (used by GenerateShortestDigits to decide if it has the shortest
+//  decimal converting back to v):
+//  - v - m-: the distance to the lower boundary.
+//  - m+ - v: the distance to the upper boundary.
+//
+// v, m+, m-, and therefore v - m- and m+ - v all share the same denominator.
+//
+// Let ep == estimated_power, then the returned values will satisfy:
+//  v / 10^ep = numerator / denominator.
+//  v's boundarys m- and m+:
+//    m- / 10^ep == v / 10^ep - delta_minus / denominator
+//    m+ / 10^ep == v / 10^ep + delta_plus / denominator
+//  Or in other words:
+//    m- == v - delta_minus * 10^ep / denominator;
+//    m+ == v + delta_plus * 10^ep / denominator;
+//
+// Since 10^(k-1) <= v < 10^k    (with k == estimated_power)
+//  or       10^k <= v < 10^(k+1)
+//  we then have 0.1 <= numerator/denominator < 1
+//           or    1 <= numerator/denominator < 10
+//
+// It is then easy to kickstart the digit-generation routine.
+//
+// The boundary-deltas are only filled if need_boundary_deltas is set.
+static void InitialScaledStartValues(double v,
+                                     int estimated_power,
+                                     bool need_boundary_deltas,
+                                     Bignum* numerator,
+                                     Bignum* denominator,
+                                     Bignum* delta_minus,
+                                     Bignum* delta_plus) {
+  if (Double(v).Exponent() >= 0) {
+    InitialScaledStartValuesPositiveExponent(
+        v, estimated_power, need_boundary_deltas,
+        numerator, denominator, delta_minus, delta_plus);
+  } else if (estimated_power >= 0) {
+    InitialScaledStartValuesNegativeExponentPositivePower(
+        v, estimated_power, need_boundary_deltas,
+        numerator, denominator, delta_minus, delta_plus);
+  } else {
+    InitialScaledStartValuesNegativeExponentNegativePower(
+        v, estimated_power, need_boundary_deltas,
+        numerator, denominator, delta_minus, delta_plus);
+  }
+}
+
+
+// This routine multiplies numerator/denominator so that its values lies in the
+// range 1-10. That is after a call to this function we have:
+//    1 <= (numerator + delta_plus) /denominator < 10.
+// Let numerator the input before modification and numerator' the argument
+// after modification, then the output-parameter decimal_point is such that
+//  numerator / denominator * 10^estimated_power ==
+//    numerator' / denominator' * 10^(decimal_point - 1)
+// In some cases estimated_power was too low, and this is already the case. We
+// then simply adjust the power so that 10^(k-1) <= v < 10^k (with k ==
+// estimated_power) but do not touch the numerator or denominator.
+// Otherwise the routine multiplies the numerator and the deltas by 10.
+static void FixupMultiply10(int estimated_power, bool is_even,
+                            int* decimal_point,
+                            Bignum* numerator, Bignum* denominator,
+                            Bignum* delta_minus, Bignum* delta_plus) {
+  bool in_range;
+  if (is_even) {
+    // For IEEE doubles half-way cases (in decimal system numbers ending with 5)
+    // are rounded to the closest floating-point number with even significand.
+    in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
+  } else {
+    in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
+  }
+  if (in_range) {
+    // Since numerator + delta_plus >= denominator we already have
+    // 1 <= numerator/denominator < 10. Simply update the estimated_power.
+    *decimal_point = estimated_power + 1;
+  } else {
+    *decimal_point = estimated_power;
+    numerator->Times10();
+    if (Bignum::Equal(*delta_minus, *delta_plus)) {
+      delta_minus->Times10();
+      delta_plus->AssignBignum(*delta_minus);
+    } else {
+      delta_minus->Times10();
+      delta_plus->Times10();
+    }
+  }
+}
+
+} }  // namespace v8::internal
diff --git a/src/bignum-dtoa.h b/src/bignum-dtoa.h
new file mode 100644
index 0000000..ea1acbb
--- /dev/null
+++ b/src/bignum-dtoa.h
@@ -0,0 +1,81 @@
+// 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_BIGNUM_DTOA_H_
+#define V8_BIGNUM_DTOA_H_
+
+namespace v8 {
+namespace internal {
+
+enum BignumDtoaMode {
+  // Return the shortest correct representation.
+  // For example the output of 0.299999999999999988897 is (the less accurate but
+  // correct) 0.3.
+  BIGNUM_DTOA_SHORTEST,
+  // Return a fixed number of digits after the decimal point.
+  // For instance fixed(0.1, 4) becomes 0.1000
+  // If the input number is big, the output will be big.
+  BIGNUM_DTOA_FIXED,
+  // Return a fixed number of digits, no matter what the exponent is.
+  BIGNUM_DTOA_PRECISION
+};
+
+// Converts the given double 'v' to ascii.
+// The result should be interpreted as buffer * 10^(point-length).
+// The buffer will be null-terminated.
+//
+// The input v must be > 0 and different from NaN, and Infinity.
+//
+// The output depends on the given mode:
+//  - SHORTEST: produce the least amount of digits for which the internal
+//   identity requirement is still satisfied. If the digits are printed
+//   (together with the correct exponent) then reading this number will give
+//   'v' again. The buffer will choose the representation that is closest to
+//   'v'. If there are two at the same distance, than the number is round up.
+//   In this mode the 'requested_digits' parameter is ignored.
+//  - FIXED: produces digits necessary to print a given number with
+//   'requested_digits' digits after the decimal point. The produced digits
+//   might be too short in which case the caller has to fill the gaps with '0's.
+//   Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
+//   Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns
+//     buffer="2", point=0.
+//   Note: the length of the returned buffer has no meaning wrt the significance
+//   of its digits. That is, just because it contains '0's does not mean that
+//   any other digit would not satisfy the internal identity requirement.
+//  - PRECISION: produces 'requested_digits' where the first digit is not '0'.
+//   Even though the length of produced digits usually equals
+//   'requested_digits', the function is allowed to return fewer digits, in
+//   which case the caller has to fill the missing digits with '0's.
+//   Halfway cases are again rounded up.
+// 'BignumDtoa' expects the given buffer to be big enough to hold all digits
+// and a terminating null-character.
+void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
+                Vector<char> buffer, int* length, int* point);
+
+} }  // namespace v8::internal
+
+#endif  // V8_BIGNUM_DTOA_H_
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 0e49966..f60a975 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -39,6 +39,8 @@
 #include "objects-visiting.h"
 #include "snapshot.h"
 #include "stub-cache.h"
+#include "extensions/externalize-string-extension.h"
+#include "extensions/gc-extension.h"
 
 namespace v8 {
 namespace internal {
@@ -137,6 +139,8 @@
 
 void Bootstrapper::Initialize(bool create_heap_objects) {
   extensions_cache.Initialize(create_heap_objects);
+  GCExtension::Register();
+  ExternalizeStringExtension::Register();
 }
 
 
diff --git a/src/builtins.cc b/src/builtins.cc
index aede302..e88ef6f 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -1081,29 +1081,22 @@
   ASSERT(!CalledAsConstructor());
   const bool is_construct = false;
 
-  // We expect four more arguments: function, callback, call data, and holder.
+  // We expect four more arguments: callback, function, call data, and holder.
   const int args_length = args.length() - 4;
   ASSERT(args_length >= 0);
 
-  Handle<JSFunction> function = args.at<JSFunction>(args_length);
-  Object* callback_obj = args[args_length + 1];
-  Handle<Object> data = args.at<Object>(args_length + 2);
-  Handle<JSObject> checked_holder = args.at<JSObject>(args_length + 3);
-
-#ifdef DEBUG
-  VerifyTypeCheck(checked_holder, function);
-#endif
-
-  CustomArguments custom;
-  v8::ImplementationUtilities::PrepareArgumentsData(custom.end(),
-      *data, *function, *checked_holder);
+  Object* callback_obj = args[args_length];
 
   v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
-      custom.end(),
+      &args[args_length + 1],
       &args[0] - 1,
       args_length - 1,
       is_construct);
 
+#ifdef DEBUG
+  VerifyTypeCheck(Utils::OpenHandle(*new_args.Holder()),
+                  Utils::OpenHandle(*new_args.Callee()));
+#endif
   HandleScope scope;
   Object* result;
   v8::Handle<v8::Value> value;
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 e070477..d49f97f 100644
--- a/src/checks.h
+++ b/src/checks.h
@@ -30,10 +30,7 @@
 
 #include <string.h>
 
-#include "../include/v8stdint.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.
@@ -224,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)
 
@@ -309,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/code-stubs.cc b/src/code-stubs.cc
index 787ec2a..8b9198f 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -37,7 +37,6 @@
 namespace internal {
 
 bool CodeStub::FindCodeInCache(Code** code_out) {
-  if (has_custom_cache()) return GetCustomCache(code_out);
   int index = Heap::code_stubs()->FindEntry(GetKey());
   if (index != NumberDictionary::kNotFound) {
     *code_out = Code::cast(Heap::code_stubs()->ValueAt(index));
@@ -105,17 +104,14 @@
     Handle<Code> new_object = Factory::NewCode(desc, flags, masm.CodeObject());
     RecordCodeGeneration(*new_object, &masm);
 
-    if (has_custom_cache()) {
-      SetCustomCache(*new_object);
-    } else {
-      // Update the dictionary and the root in Heap.
-      Handle<NumberDictionary> dict =
-          Factory::DictionaryAtNumberPut(
-              Handle<NumberDictionary>(Heap::code_stubs()),
-              GetKey(),
-              new_object);
-      Heap::public_set_code_stubs(*dict);
-    }
+    // Update the dictionary and the root in Heap.
+    Handle<NumberDictionary> dict =
+        Factory::DictionaryAtNumberPut(
+            Handle<NumberDictionary>(Heap::code_stubs()),
+            GetKey(),
+            new_object);
+    Heap::public_set_code_stubs(*dict);
+
     code = *new_object;
   }
 
@@ -147,15 +143,11 @@
     code = Code::cast(new_object);
     RecordCodeGeneration(code, &masm);
 
-    if (has_custom_cache()) {
-      SetCustomCache(code);
-    } else {
-      // Try to update the code cache but do not fail if unable.
-      MaybeObject* maybe_new_object =
-          Heap::code_stubs()->AtNumberPut(GetKey(), code);
-      if (maybe_new_object->ToObject(&new_object)) {
-        Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
-      }
+    // Try to update the code cache but do not fail if unable.
+    MaybeObject* maybe_new_object =
+        Heap::code_stubs()->AtNumberPut(GetKey(), code);
+    if (maybe_new_object->ToObject(&new_object)) {
+      Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
     }
   }
 
diff --git a/src/code-stubs.h b/src/code-stubs.h
index ec64353..b156647 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -124,12 +124,6 @@
 
   virtual ~CodeStub() {}
 
-  // Override these methods to provide a custom caching mechanism for
-  // an individual type of code stub.
-  virtual bool GetCustomCache(Code** code_out) { return false; }
-  virtual void SetCustomCache(Code* value) { }
-  virtual bool has_custom_cache() { return false; }
-
  protected:
   static const int kMajorBits = 5;
   static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
@@ -524,58 +518,6 @@
 };
 
 
-class ApiGetterEntryStub : public CodeStub {
- public:
-  ApiGetterEntryStub(Handle<AccessorInfo> info,
-                     ApiFunction* fun)
-      : info_(info),
-        fun_(fun) { }
-  void Generate(MacroAssembler* masm);
-  virtual bool has_custom_cache() { return true; }
-  virtual bool GetCustomCache(Code** code_out);
-  virtual void SetCustomCache(Code* value);
-
-  static const int kStackSpace = 5;
-  static const int kArgc = 2;
- private:
-  Handle<AccessorInfo> info() { return info_; }
-  ApiFunction* fun() { return fun_; }
-  Major MajorKey() { return NoCache; }
-  int MinorKey() { return 0; }
-  const char* GetName() { return "ApiGetterEntryStub"; }
-  // The accessor info associated with the function.
-  Handle<AccessorInfo> info_;
-  // The function to be called.
-  ApiFunction* fun_;
-};
-
-
-class ApiCallEntryStub : public CodeStub {
- public:
-  ApiCallEntryStub(Handle<CallHandlerInfo> info,
-                   ApiFunction* fun)
-      : info_(info),
-        fun_(fun) { }
-  void Generate(MacroAssembler* masm);
-  virtual bool has_custom_cache() { return true; }
-  virtual bool GetCustomCache(Code** code_out);
-  virtual void SetCustomCache(Code* value);
-
-  static const int kStackSpace = 0;
-  static const int kArgc = 5;
- private:
-  Handle<CallHandlerInfo> info() { return info_; }
-  ApiFunction* fun() { return fun_; }
-  Major MajorKey() { return NoCache; }
-  int MinorKey() { return 0; }
-  const char* GetName() { return "ApiCallEntryStub"; }
-  // The call handler info associated with the function.
-  Handle<CallHandlerInfo> info_;
-  // The function to be called.
-  ApiFunction* fun_;
-};
-
-
 class JSEntryStub : public CodeStub {
  public:
   JSEntryStub() { }
diff --git a/src/codegen.cc b/src/codegen.cc
index e954dd6..fb8c5cd 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -252,39 +252,6 @@
 #endif
 
 
-Handle<Code> CodeGenerator::ComputeCallInitialize(
-    int argc,
-    InLoopFlag in_loop) {
-  if (in_loop == IN_LOOP) {
-    // Force the creation of the corresponding stub outside loops,
-    // because it may be used when clearing the ICs later - it is
-    // possible for a series of IC transitions to lose the in-loop
-    // information, and the IC clearing code can't generate a stub
-    // that it needs so we need to ensure it is generated already.
-    ComputeCallInitialize(argc, NOT_IN_LOOP);
-  }
-  CALL_HEAP_FUNCTION(
-      StubCache::ComputeCallInitialize(argc, in_loop, Code::CALL_IC),
-      Code);
-}
-
-
-Handle<Code> CodeGenerator::ComputeKeyedCallInitialize(
-    int argc,
-    InLoopFlag in_loop) {
-  if (in_loop == IN_LOOP) {
-    // Force the creation of the corresponding stub outside loops,
-    // because it may be used when clearing the ICs later - it is
-    // possible for a series of IC transitions to lose the in-loop
-    // information, and the IC clearing code can't generate a stub
-    // that it needs so we need to ensure it is generated already.
-    ComputeKeyedCallInitialize(argc, NOT_IN_LOOP);
-  }
-  CALL_HEAP_FUNCTION(
-      StubCache::ComputeCallInitialize(argc, in_loop, Code::KEYED_CALL_IC),
-      Code);
-}
-
 void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
   int length = declarations->length();
   int globals = 0;
@@ -482,35 +449,4 @@
 }
 
 
-// Implementation of CodeStub::GetCustomCache.
-static bool GetCustomCacheHelper(Object* cache, Code** code_out) {
-  if (cache->IsUndefined()) {
-    return false;
-  } else {
-    *code_out = Code::cast(cache);
-    return true;
-  }
-}
-
-
-bool ApiGetterEntryStub::GetCustomCache(Code** code_out) {
-  return GetCustomCacheHelper(info()->load_stub_cache(), code_out);
-}
-
-
-void ApiGetterEntryStub::SetCustomCache(Code* value) {
-  info()->set_load_stub_cache(value);
-}
-
-
-bool ApiCallEntryStub::GetCustomCache(Code** code_out) {
-  return GetCustomCacheHelper(info()->call_stub_cache(), code_out);
-}
-
-
-void ApiCallEntryStub::SetCustomCache(Code* value) {
-  info()->set_call_stub_cache(value);
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/codegen.h b/src/codegen.h
index 8f923dd..66300d6 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -58,8 +58,6 @@
 //   Generate
 //   ComputeLazyCompile
 //   BuildFunctionInfo
-//   ComputeCallInitialize
-//   ComputeCallInitializeInLoop
 //   ProcessDeclarations
 //   DeclareGlobals
 //   CheckForInlineRuntimeCall
diff --git a/src/conversions.cc b/src/conversions.cc
index 4cc6744..a954d6c 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -33,22 +33,12 @@
 #include "conversions-inl.h"
 #include "dtoa.h"
 #include "factory.h"
-#include "scanner.h"
+#include "scanner-base.h"
 #include "strtod.h"
 
 namespace v8 {
 namespace internal {
 
-int HexValue(uc32 c) {
-  if ('0' <= c && c <= '9')
-    return c - '0';
-  if ('a' <= c && c <= 'f')
-    return c - 'a' + 10;
-  if ('A' <= c && c <= 'F')
-    return c - 'A' + 10;
-  return -1;
-}
-
 namespace {
 
 // C++-style iterator adaptor for StringInputBuffer
@@ -121,7 +111,7 @@
 template <class Iterator, class EndMark>
 static inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
   while (*current != end) {
-    if (!Scanner::kIsWhiteSpace.get(**current)) return true;
+    if (!ScannerConstants::kIsWhiteSpace.get(**current)) return true;
     ++*current;
   }
   return false;
@@ -458,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;
   }
 
@@ -654,7 +644,7 @@
   buffer[buffer_pos] = '\0';
 
   double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
-  return sign? -converted: converted;
+  return sign ? -converted : converted;
 }
 
 
@@ -711,11 +701,6 @@
 }
 
 
-extern "C" char* dtoa(double d, int mode, int ndigits,
-                      int* decpt, int* sign, char** rve);
-
-extern "C" void freedtoa(char* s);
-
 const char* DoubleToCString(double v, Vector<char> buffer) {
   StringBuilder builder(buffer.start(), buffer.length());
 
@@ -739,21 +724,13 @@
     default: {
       int decimal_point;
       int sign;
-      char* decimal_rep;
-      bool used_gay_dtoa = false;
       const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
-      char v8_dtoa_buffer[kV8DtoaBufferCapacity];
+      char decimal_rep[kV8DtoaBufferCapacity];
       int length;
 
-      if (DoubleToAscii(v, DTOA_SHORTEST, 0,
-                        Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
-                        &sign, &length, &decimal_point)) {
-        decimal_rep = v8_dtoa_buffer;
-      } else {
-        decimal_rep = dtoa(v, 0, 0, &decimal_point, &sign, NULL);
-        used_gay_dtoa = true;
-        length = StrLength(decimal_rep);
-      }
+      DoubleToAscii(v, DTOA_SHORTEST, 0,
+                    Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
+                    &sign, &length, &decimal_point);
 
       if (sign) builder.AddCharacter('-');
 
@@ -787,8 +764,6 @@
         if (exponent < 0) exponent = -exponent;
         builder.AddFormatted("%d", exponent);
       }
-
-      if (used_gay_dtoa) freedtoa(decimal_rep);
     }
   }
   return builder.Finalize();
@@ -845,11 +820,9 @@
       kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
   char decimal_rep[kDecimalRepCapacity];
   int decimal_rep_length;
-  bool status = DoubleToAscii(value, DTOA_FIXED, f,
-                              Vector<char>(decimal_rep, kDecimalRepCapacity),
-                              &sign, &decimal_rep_length, &decimal_point);
-  USE(status);
-  ASSERT(status);
+  DoubleToAscii(value, DTOA_FIXED, f,
+                Vector<char>(decimal_rep, kDecimalRepCapacity),
+                &sign, &decimal_rep_length, &decimal_point);
 
   // Create a representation that is padded with zeros if needed.
   int zero_prefix_length = 0;
@@ -935,8 +908,6 @@
   // Find a sufficiently precise decimal representation of n.
   int decimal_point;
   int sign;
-  char* decimal_rep = NULL;
-  bool used_gay_dtoa = false;
   // f corresponds to the digits after the point. There is always one digit
   // before the point. The number of requested_digits equals hence f + 1.
   // And we have to add one character for the null-terminator.
@@ -944,31 +915,18 @@
   // Make sure that the buffer is big enough, even if we fall back to the
   // shortest representation (which happens when f equals -1).
   ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
-  char v8_dtoa_buffer[kV8DtoaBufferCapacity];
+  char decimal_rep[kV8DtoaBufferCapacity];
   int decimal_rep_length;
 
   if (f == -1) {
-    if (DoubleToAscii(value, DTOA_SHORTEST, 0,
-                      Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
-                      &sign, &decimal_rep_length, &decimal_point)) {
-      f = decimal_rep_length - 1;
-      decimal_rep = v8_dtoa_buffer;
-    } else {
-      decimal_rep = dtoa(value, 0, 0, &decimal_point, &sign, NULL);
-      decimal_rep_length = StrLength(decimal_rep);
-      f = decimal_rep_length - 1;
-      used_gay_dtoa = true;
-    }
+    DoubleToAscii(value, DTOA_SHORTEST, 0,
+                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
+                  &sign, &decimal_rep_length, &decimal_point);
+    f = decimal_rep_length - 1;
   } else {
-    if (DoubleToAscii(value, DTOA_PRECISION, f + 1,
-                      Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
-                      &sign, &decimal_rep_length, &decimal_point)) {
-      decimal_rep = v8_dtoa_buffer;
-    } else {
-      decimal_rep = dtoa(value, 2, f + 1, &decimal_point, &sign, NULL);
-      decimal_rep_length = StrLength(decimal_rep);
-      used_gay_dtoa = true;
-    }
+    DoubleToAscii(value, DTOA_PRECISION, f + 1,
+                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
+                  &sign, &decimal_rep_length, &decimal_point);
   }
   ASSERT(decimal_rep_length > 0);
   ASSERT(decimal_rep_length <= f + 1);
@@ -977,10 +935,6 @@
   char* result =
       CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
 
-  if (used_gay_dtoa) {
-    freedtoa(decimal_rep);
-  }
-
   return result;
 }
 
@@ -1000,22 +954,14 @@
   // Find a sufficiently precise decimal representation of n.
   int decimal_point;
   int sign;
-  char* decimal_rep = NULL;
-  bool used_gay_dtoa = false;
   // Add one for the terminating null character.
   const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
-  char v8_dtoa_buffer[kV8DtoaBufferCapacity];
+  char decimal_rep[kV8DtoaBufferCapacity];
   int decimal_rep_length;
 
-  if (DoubleToAscii(value, DTOA_PRECISION, p,
-                    Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
-                    &sign, &decimal_rep_length, &decimal_point)) {
-    decimal_rep = v8_dtoa_buffer;
-  } else {
-    decimal_rep = dtoa(value, 2, p, &decimal_point, &sign, NULL);
-    decimal_rep_length = StrLength(decimal_rep);
-    used_gay_dtoa = true;
-  }
+  DoubleToAscii(value, DTOA_PRECISION, p,
+                Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
+                &sign, &decimal_rep_length, &decimal_point);
   ASSERT(decimal_rep_length <= p);
 
   int exponent = decimal_point - 1;
@@ -1059,9 +1005,6 @@
     result = builder.Finalize();
   }
 
-  if (used_gay_dtoa) {
-    freedtoa(decimal_rep);
-  }
   return result;
 }
 
diff --git a/src/conversions.h b/src/conversions.h
index 9e32a0c..312e6ae 100644
--- a/src/conversions.h
+++ b/src/conversions.h
@@ -75,11 +75,6 @@
 }
 
 
-// Returns the value (0 .. 15) of a hexadecimal character c.
-// If c is not a legal hexadecimal character, returns a value < 0.
-int HexValue(uc32 c);
-
-
 // Enumeration for allowing octals and ignoring junk when converting
 // strings to numbers.
 enum ConversionFlags {
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 cae9b08..40e56f3 100644
--- a/src/dateparser.h
+++ b/src/dateparser.h
@@ -28,7 +28,8 @@
 #ifndef V8_DATEPARSER_H_
 #define V8_DATEPARSER_H_
 
-#include "scanner.h"
+#include "char-predicates-inl.h"
+#include "scanner-base.h"
 
 namespace v8 {
 namespace internal {
@@ -86,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.
@@ -99,10 +112,20 @@
     }
 
     // The skip methods return whether they actually skipped something.
-    bool Skip(uint32_t c) { return ch_ == c ?  (Next(), true) : false; }
+    bool Skip(uint32_t c) {
+      if (ch_ == c) {
+        Next();
+        return true;
+      }
+      return false;
+    }
 
     bool SkipWhiteSpace() {
-      return Scanner::kIsWhiteSpace.get(ch_) ? (Next(), true) : false;
+      if (ScannerConstants::kIsWhiteSpace.get(ch_)) {
+        Next();
+        return true;
+      }
+      return false;
     }
 
     bool SkipParentheses() {
diff --git a/src/dtoa-config.c b/src/dtoa-config.c
deleted file mode 100644
index 9c5ee33..0000000
--- a/src/dtoa-config.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2007-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.
- */
-
-/**
- * Dtoa needs to have a particular environment set up for it so
- * instead of using it directly you should use this file.
- *
- * The way it works is that when you link with it, its definitions
- * of dtoa, strtod etc. override the default ones.  So if you fail
- * to link with this library everything will still work, it's just
- * subtly wrong.
- */
-
-#if !(defined(__APPLE__) && defined(__MACH__)) && \
-    !defined(WIN32) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && \
-    !defined(__sun)
-#include <endian.h>
-#endif
-#include <math.h>
-#include <float.h>
-
-/* The floating point word order on ARM is big endian when floating point
- * emulation is used, even if the byte order is little endian */
-#if !(defined(__APPLE__) && defined(__MACH__)) && !defined(WIN32) && \
-    !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sun) && \
-    __FLOAT_WORD_ORDER == __BIG_ENDIAN
-#define  IEEE_MC68k
-#else
-#define  IEEE_8087
-#endif
-
-#define __MATH_H__
-#if defined(__APPLE__) && defined(__MACH__) || defined(__FreeBSD__) || \
-    defined(__OpenBSD__) || defined(__sun)
-/* stdlib.h on FreeBSD and Apple's 10.5 and later SDKs will mangle the
- * name of strtod.  If it's included after strtod is redefined as
- * gay_strtod, it will mangle the name of gay_strtod, which is
- * unwanted. */
-#include <stdlib.h>
-
-#endif
-/* stdlib.h on Windows adds __declspec(dllimport) to all functions when using
- * the DLL version of the CRT (compiling with /MD or /MDd). If stdlib.h is
- * included after strtod is redefined as gay_strtod, it will add
- * __declspec(dllimport) to gay_strtod, which causes the compilation of
- * gay_strtod in dtoa.c to fail.
-*/
-#if defined(WIN32) && defined(_DLL)
-#include "stdlib.h"
-#endif
-
-/* For MinGW, turn on __NO_ISOCEXT so that its strtod doesn't get added */
-#ifdef __MINGW32__
-#define __NO_ISOCEXT
-#endif  /* __MINGW32__ */
-
-/* On 64-bit systems, we need to make sure that a Long is only 32 bits. */
-#ifdef V8_TARGET_ARCH_X64
-#define Long int
-#endif /* V8_TARGET_ARCH_X64 */
-
-/* Make sure we use the David M. Gay version of strtod(). On Linux, we
- * cannot use the same name (maybe the function does not have weak
- * linkage?). */
-#define strtod gay_strtod
-#include "third_party/dtoa/dtoa.c"
diff --git a/src/dtoa.cc b/src/dtoa.cc
index f4141eb..b857a5d 100644
--- a/src/dtoa.cc
+++ b/src/dtoa.cc
@@ -30,6 +30,7 @@
 #include "v8.h"
 #include "dtoa.h"
 
+#include "bignum-dtoa.h"
 #include "double.h"
 #include "fast-dtoa.h"
 #include "fixed-dtoa.h"
@@ -37,7 +38,19 @@
 namespace v8 {
 namespace internal {
 
-bool DoubleToAscii(double v, DtoaMode mode, int requested_digits,
+static BignumDtoaMode DtoaToBignumDtoaMode(DtoaMode dtoa_mode) {
+  switch (dtoa_mode) {
+    case DTOA_SHORTEST:  return BIGNUM_DTOA_SHORTEST;
+    case DTOA_FIXED:     return BIGNUM_DTOA_FIXED;
+    case DTOA_PRECISION: return BIGNUM_DTOA_PRECISION;
+    default:
+      UNREACHABLE();
+      return BIGNUM_DTOA_SHORTEST;  // To silence compiler.
+  }
+}
+
+
+void DoubleToAscii(double v, DtoaMode mode, int requested_digits,
                    Vector<char> buffer, int* sign, int* length, int* point) {
   ASSERT(!Double(v).IsSpecial());
   ASSERT(mode == DTOA_SHORTEST || requested_digits >= 0);
@@ -54,25 +67,37 @@
     buffer[1] = '\0';
     *length = 1;
     *point = 1;
-    return true;
+    return;
   }
 
   if (mode == DTOA_PRECISION && requested_digits == 0) {
     buffer[0] = '\0';
     *length = 0;
-    return true;
+    return;
   }
 
+  bool fast_worked;
   switch (mode) {
     case DTOA_SHORTEST:
-      return FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, length, point);
+      fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, length, point);
+      break;
     case DTOA_FIXED:
-      return FastFixedDtoa(v, requested_digits, buffer, length, point);
+      fast_worked = FastFixedDtoa(v, requested_digits, buffer, length, point);
+      break;
     case DTOA_PRECISION:
-      return FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
-                      buffer, length, point);
+      fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
+                             buffer, length, point);
+      break;
+    default:
+      UNREACHABLE();
+      fast_worked = false;
   }
-  return false;
+  if (fast_worked) return;
+
+  // If the fast dtoa didn't succeed use the slower bignum version.
+  BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
+  BignumDtoa(v, bignum_mode, requested_digits, buffer, length, point);
+  buffer[*length] = '\0';
 }
 
 } }  // namespace v8::internal
diff --git a/src/dtoa.h b/src/dtoa.h
index be0d545..b3e79af 100644
--- a/src/dtoa.h
+++ b/src/dtoa.h
@@ -32,13 +32,15 @@
 namespace internal {
 
 enum DtoaMode {
-  // 0.9999999999999999 becomes 0.1
+  // Return the shortest correct representation.
+  // For example the output of 0.299999999999999988897 is (the less accurate but
+  // correct) 0.3.
   DTOA_SHORTEST,
-  // Fixed number of digits after the decimal point.
+  // Return a fixed number of digits after the decimal point.
   // For instance fixed(0.1, 4) becomes 0.1000
   // If the input number is big, the output will be big.
   DTOA_FIXED,
-  // Fixed number of digits (independent of the decimal point).
+  // Return a fixed number of digits, no matter what the exponent is.
   DTOA_PRECISION
 };
 
@@ -72,8 +74,10 @@
 //   which case the caller has to fill the missing digits with '0's.
 //   Halfway cases are again rounded away from 0.
 // 'DoubleToAscii' expects the given buffer to be big enough to hold all digits
-// and a terminating null-character.
-bool DoubleToAscii(double v, DtoaMode mode, int requested_digits,
+// and a terminating null-character. In SHORTEST-mode it expects a buffer of
+// at least kBase10MaximalLength + 1. Otherwise, the size of the output is
+// limited to requested_digits digits plus the null terminator.
+void DoubleToAscii(double v, DtoaMode mode, int requested_digits,
                    Vector<char> buffer, int* sign, int* length, int* point);
 
 } }  // namespace v8::internal
diff --git a/src/execution.cc b/src/execution.cc
index 885bf63..691d569 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -700,135 +700,4 @@
   return Heap::undefined_value();
 }
 
-// --- G C   E x t e n s i o n ---
-
-const char* const GCExtension::kSource = "native function gc();";
-
-
-v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
-    v8::Handle<v8::String> str) {
-  return v8::FunctionTemplate::New(GCExtension::GC);
-}
-
-
-v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
-  // All allocation spaces other than NEW_SPACE have the same effect.
-  Heap::CollectAllGarbage(false);
-  return v8::Undefined();
-}
-
-
-static GCExtension gc_extension;
-static v8::DeclareExtension gc_extension_declaration(&gc_extension);
-
-
-// --- E x t e r n a l i z e S t r i n g   E x t e n s i o n ---
-
-
-template <typename Char, typename Base>
-class SimpleStringResource : public Base {
- public:
-  // Takes ownership of |data|.
-  SimpleStringResource(Char* data, size_t length)
-      : data_(data),
-        length_(length) {}
-
-  virtual ~SimpleStringResource() { delete[] data_; }
-
-  virtual const Char* data() const { return data_; }
-
-  virtual size_t length() const { return length_; }
-
- private:
-  Char* const data_;
-  const size_t length_;
-};
-
-
-typedef SimpleStringResource<char, v8::String::ExternalAsciiStringResource>
-    SimpleAsciiStringResource;
-typedef SimpleStringResource<uc16, v8::String::ExternalStringResource>
-    SimpleTwoByteStringResource;
-
-
-const char* const ExternalizeStringExtension::kSource =
-    "native function externalizeString();"
-    "native function isAsciiString();";
-
-
-v8::Handle<v8::FunctionTemplate> ExternalizeStringExtension::GetNativeFunction(
-    v8::Handle<v8::String> str) {
-  if (strcmp(*v8::String::AsciiValue(str), "externalizeString") == 0) {
-    return v8::FunctionTemplate::New(ExternalizeStringExtension::Externalize);
-  } else {
-    ASSERT(strcmp(*v8::String::AsciiValue(str), "isAsciiString") == 0);
-    return v8::FunctionTemplate::New(ExternalizeStringExtension::IsAscii);
-  }
-}
-
-
-v8::Handle<v8::Value> ExternalizeStringExtension::Externalize(
-    const v8::Arguments& args) {
-  if (args.Length() < 1 || !args[0]->IsString()) {
-    return v8::ThrowException(v8::String::New(
-        "First parameter to externalizeString() must be a string."));
-  }
-  bool force_two_byte = false;
-  if (args.Length() >= 2) {
-    if (args[1]->IsBoolean()) {
-      force_two_byte = args[1]->BooleanValue();
-    } else {
-      return v8::ThrowException(v8::String::New(
-          "Second parameter to externalizeString() must be a boolean."));
-    }
-  }
-  bool result = false;
-  Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
-  if (string->IsExternalString()) {
-    return v8::ThrowException(v8::String::New(
-        "externalizeString() can't externalize twice."));
-  }
-  if (string->IsAsciiRepresentation() && !force_two_byte) {
-    char* data = new char[string->length()];
-    String::WriteToFlat(*string, data, 0, string->length());
-    SimpleAsciiStringResource* resource = new SimpleAsciiStringResource(
-        data, string->length());
-    result = string->MakeExternal(resource);
-    if (result && !string->IsSymbol()) {
-      i::ExternalStringTable::AddString(*string);
-    }
-    if (!result) delete resource;
-  } else {
-    uc16* data = new uc16[string->length()];
-    String::WriteToFlat(*string, data, 0, string->length());
-    SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
-        data, string->length());
-    result = string->MakeExternal(resource);
-    if (result && !string->IsSymbol()) {
-      i::ExternalStringTable::AddString(*string);
-    }
-    if (!result) delete resource;
-  }
-  if (!result) {
-    return v8::ThrowException(v8::String::New("externalizeString() failed."));
-  }
-  return v8::Undefined();
-}
-
-
-v8::Handle<v8::Value> ExternalizeStringExtension::IsAscii(
-    const v8::Arguments& args) {
-  if (args.Length() != 1 || !args[0]->IsString()) {
-    return v8::ThrowException(v8::String::New(
-        "isAsciiString() requires a single string argument."));
-  }
-  return Utils::OpenHandle(*args[0].As<v8::String>())->IsAsciiRepresentation() ?
-      v8::True() : v8::False();
-}
-
-
-static ExternalizeStringExtension externalize_extension;
-static v8::DeclareExtension externalize_extension_declaration(
-    &externalize_extension);
-
 } }  // namespace v8::internal
diff --git a/src/execution.h b/src/execution.h
index 5547803..a2ddc41 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -189,6 +189,9 @@
   static uintptr_t climit() {
     return thread_local_.climit_;
   }
+  static uintptr_t real_climit() {
+    return thread_local_.real_climit_;
+  }
   static uintptr_t jslimit() {
     return thread_local_.jslimit_;
   }
@@ -313,29 +316,6 @@
   }
 };
 
-
-class GCExtension : public v8::Extension {
- public:
-  GCExtension() : v8::Extension("v8/gc", kSource) {}
-  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
-      v8::Handle<v8::String> name);
-  static v8::Handle<v8::Value> GC(const v8::Arguments& args);
- private:
-  static const char* const kSource;
-};
-
-
-class ExternalizeStringExtension : public v8::Extension {
- public:
-  ExternalizeStringExtension() : v8::Extension("v8/externalize", kSource) {}
-  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
-      v8::Handle<v8::String> name);
-  static v8::Handle<v8::Value> Externalize(const v8::Arguments& args);
-  static v8::Handle<v8::Value> IsAscii(const v8::Arguments& args);
- private:
-  static const char* const kSource;
-};
-
 } }  // namespace v8::internal
 
 #endif  // V8_EXECUTION_H_
diff --git a/src/extensions/externalize-string-extension.cc b/src/extensions/externalize-string-extension.cc
new file mode 100644
index 0000000..8b4bdbd
--- /dev/null
+++ b/src/extensions/externalize-string-extension.cc
@@ -0,0 +1,141 @@
+// 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 "externalize-string-extension.h"
+
+namespace v8 {
+namespace internal {
+
+template <typename Char, typename Base>
+class SimpleStringResource : public Base {
+ public:
+  // Takes ownership of |data|.
+  SimpleStringResource(Char* data, size_t length)
+      : data_(data),
+        length_(length) {}
+
+  virtual ~SimpleStringResource() { delete[] data_; }
+
+  virtual const Char* data() const { return data_; }
+
+  virtual size_t length() const { return length_; }
+
+ private:
+  Char* const data_;
+  const size_t length_;
+};
+
+
+typedef SimpleStringResource<char, v8::String::ExternalAsciiStringResource>
+    SimpleAsciiStringResource;
+typedef SimpleStringResource<uc16, v8::String::ExternalStringResource>
+    SimpleTwoByteStringResource;
+
+
+const char* const ExternalizeStringExtension::kSource =
+    "native function externalizeString();"
+    "native function isAsciiString();";
+
+
+v8::Handle<v8::FunctionTemplate> ExternalizeStringExtension::GetNativeFunction(
+    v8::Handle<v8::String> str) {
+  if (strcmp(*v8::String::AsciiValue(str), "externalizeString") == 0) {
+    return v8::FunctionTemplate::New(ExternalizeStringExtension::Externalize);
+  } else {
+    ASSERT(strcmp(*v8::String::AsciiValue(str), "isAsciiString") == 0);
+    return v8::FunctionTemplate::New(ExternalizeStringExtension::IsAscii);
+  }
+}
+
+
+v8::Handle<v8::Value> ExternalizeStringExtension::Externalize(
+    const v8::Arguments& args) {
+  if (args.Length() < 1 || !args[0]->IsString()) {
+    return v8::ThrowException(v8::String::New(
+        "First parameter to externalizeString() must be a string."));
+  }
+  bool force_two_byte = false;
+  if (args.Length() >= 2) {
+    if (args[1]->IsBoolean()) {
+      force_two_byte = args[1]->BooleanValue();
+    } else {
+      return v8::ThrowException(v8::String::New(
+          "Second parameter to externalizeString() must be a boolean."));
+    }
+  }
+  bool result = false;
+  Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
+  if (string->IsExternalString()) {
+    return v8::ThrowException(v8::String::New(
+        "externalizeString() can't externalize twice."));
+  }
+  if (string->IsAsciiRepresentation() && !force_two_byte) {
+    char* data = new char[string->length()];
+    String::WriteToFlat(*string, data, 0, string->length());
+    SimpleAsciiStringResource* resource = new SimpleAsciiStringResource(
+        data, string->length());
+    result = string->MakeExternal(resource);
+    if (result && !string->IsSymbol()) {
+      i::ExternalStringTable::AddString(*string);
+    }
+    if (!result) delete resource;
+  } else {
+    uc16* data = new uc16[string->length()];
+    String::WriteToFlat(*string, data, 0, string->length());
+    SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
+        data, string->length());
+    result = string->MakeExternal(resource);
+    if (result && !string->IsSymbol()) {
+      i::ExternalStringTable::AddString(*string);
+    }
+    if (!result) delete resource;
+  }
+  if (!result) {
+    return v8::ThrowException(v8::String::New("externalizeString() failed."));
+  }
+  return v8::Undefined();
+}
+
+
+v8::Handle<v8::Value> ExternalizeStringExtension::IsAscii(
+    const v8::Arguments& args) {
+  if (args.Length() != 1 || !args[0]->IsString()) {
+    return v8::ThrowException(v8::String::New(
+        "isAsciiString() requires a single string argument."));
+  }
+  return Utils::OpenHandle(*args[0].As<v8::String>())->IsAsciiRepresentation() ?
+      v8::True() : v8::False();
+}
+
+
+void ExternalizeStringExtension::Register() {
+  static ExternalizeStringExtension externalize_extension;
+  static v8::DeclareExtension externalize_extension_declaration(
+      &externalize_extension);
+}
+
+} }  // namespace v8::internal
diff --git a/src/extensions/externalize-string-extension.h b/src/extensions/externalize-string-extension.h
new file mode 100644
index 0000000..b97b496
--- /dev/null
+++ b/src/extensions/externalize-string-extension.h
@@ -0,0 +1,50 @@
+// 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_EXTENSIONS_EXTERNALIZE_STRING_EXTENSION_H_
+#define V8_EXTENSIONS_EXTERNALIZE_STRING_EXTENSION_H_
+
+#include "v8.h"
+
+namespace v8 {
+namespace internal {
+
+class ExternalizeStringExtension : public v8::Extension {
+ public:
+  ExternalizeStringExtension() : v8::Extension("v8/externalize", kSource) {}
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+      v8::Handle<v8::String> name);
+  static v8::Handle<v8::Value> Externalize(const v8::Arguments& args);
+  static v8::Handle<v8::Value> IsAscii(const v8::Arguments& args);
+  static void Register();
+ private:
+  static const char* const kSource;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_EXTENSIONS_EXTERNALIZE_STRING_EXTENSION_H_
diff --git a/src/extensions/gc-extension.cc b/src/extensions/gc-extension.cc
new file mode 100644
index 0000000..b8f081c
--- /dev/null
+++ b/src/extensions/gc-extension.cc
@@ -0,0 +1,54 @@
+// 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 "gc-extension.h"
+
+namespace v8 {
+namespace internal {
+
+const char* const GCExtension::kSource = "native function gc();";
+
+
+v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
+    v8::Handle<v8::String> str) {
+  return v8::FunctionTemplate::New(GCExtension::GC);
+}
+
+
+v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
+  // All allocation spaces other than NEW_SPACE have the same effect.
+  Heap::CollectAllGarbage(false);
+  return v8::Undefined();
+}
+
+
+void GCExtension::Register() {
+  static GCExtension gc_extension;
+  static v8::DeclareExtension gc_extension_declaration(&gc_extension);
+}
+
+} }  // namespace v8::internal
diff --git a/src/extensions/gc-extension.h b/src/extensions/gc-extension.h
new file mode 100644
index 0000000..06ea4ed
--- /dev/null
+++ b/src/extensions/gc-extension.h
@@ -0,0 +1,49 @@
+// 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_EXTENSIONS_GC_EXTENSION_H_
+#define V8_EXTENSIONS_GC_EXTENSION_H_
+
+#include "v8.h"
+
+namespace v8 {
+namespace internal {
+
+class GCExtension : public v8::Extension {
+ public:
+  GCExtension() : v8::Extension("v8/gc", kSource) {}
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+      v8::Handle<v8::String> name);
+  static v8::Handle<v8::Value> GC(const v8::Arguments& args);
+  static void Register();
+ private:
+  static const char* const kSource;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_EXTENSIONS_GC_EXTENSION_H_
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index c770e18..a890f15 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -301,11 +301,6 @@
 }
 
 
-MemOperand FullCodeGenerator::ContextOperand(Register context, int index) {
-  return CodeGenerator::ContextOperand(context, index);
-}
-
-
 int FullCodeGenerator::SlotOffset(Slot* slot) {
   ASSERT(slot != NULL);
   // Offset is negative because higher indexes are at lower addresses.
@@ -887,12 +882,12 @@
   Visit(stmt->body());
 
   // Check stack before looping.
+  __ bind(loop_statement.continue_target());
   __ StackLimitCheck(&stack_limit_hit);
   __ bind(&stack_check_success);
 
   // Record the position of the do while condition and make sure it is
   // possible to break on the condition.
-  __ bind(loop_statement.continue_target());
   SetExpressionPosition(stmt->cond(), stmt->condition_position());
   VisitForControl(stmt->cond(),
                   &body,
@@ -1173,14 +1168,14 @@
     SetStackOverflow();
     return;
   }
-  EmitNewClosure(function_info);
+  EmitNewClosure(function_info, expr->pretenure());
 }
 
 
 void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
     SharedFunctionInfoLiteral* expr) {
   Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
-  EmitNewClosure(expr->shared_function_info());
+  EmitNewClosure(expr->shared_function_info(), false);
 }
 
 
diff --git a/src/full-codegen.h b/src/full-codegen.h
index a3270aa..97a56bd 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -348,7 +348,7 @@
 
   // Platform-specific support for allocating a new closure based on
   // the given function info.
-  void EmitNewClosure(Handle<SharedFunctionInfo> info);
+  void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure);
 
   // Platform-specific support for compiling assignments.
 
@@ -464,9 +464,6 @@
   // in v8::internal::Context.
   void LoadContextField(Register dst, int context_index);
 
-  // Create an operand for a context field.
-  MemOperand ContextOperand(Register context, int context_index);
-
   // AST node visit functions.
 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
   AST_NODE_LIST(DECLARE_VISIT)
diff --git a/src/globals.h b/src/globals.h
index a74b6c7..88c3e78 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2009 the V8 project authors. All rights reserved.
+// 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:
@@ -193,9 +193,10 @@
 
 const int kCharSize     = sizeof(char);      // NOLINT
 const int kShortSize    = sizeof(short);     // NOLINT
+const int kIntSize      = sizeof(int);       // NOLINT
 const int kDoubleSize   = sizeof(double);    // NOLINT
 const int kIntptrSize   = sizeof(intptr_t);  // NOLINT
-// kIntSize and kPointerSize are defined in include/v8.h.
+const int kPointerSize  = sizeof(void*);     // NOLINT
 
 #if V8_HOST_ARCH_64_BIT
 const int kPointerSizeLog2 = 3;
@@ -207,38 +208,6 @@
 const uintptr_t kUintptrAllBitsSet = 0xFFFFFFFFu;
 #endif
 
-// Mask for the sign bit in a smi.
-const intptr_t kSmiSignMask = kIntptrSignBit;
-
-const int kObjectAlignmentBits = kPointerSizeLog2;
-const intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
-const intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
-
-// Desired alignment for pointers.
-const intptr_t kPointerAlignment = (1 << kPointerSizeLog2);
-const intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
-
-// Desired alignment for maps.
-#if V8_HOST_ARCH_64_BIT
-const intptr_t kMapAlignmentBits = kObjectAlignmentBits;
-#else
-const intptr_t kMapAlignmentBits = kObjectAlignmentBits + 3;
-#endif
-const intptr_t kMapAlignment = (1 << kMapAlignmentBits);
-const intptr_t kMapAlignmentMask = kMapAlignment - 1;
-
-// Desired alignment for generated code is 32 bytes (to improve cache line
-// utilization).
-const int kCodeAlignmentBits = 5;
-const intptr_t kCodeAlignment = 1 << kCodeAlignmentBits;
-const intptr_t kCodeAlignmentMask = kCodeAlignment - 1;
-
-// Tag information for Failure.
-const int kFailureTag = 3;
-const int kFailureTagSize = 2;
-const intptr_t kFailureTagMask = (1 << kFailureTagSize) - 1;
-
-
 const int kBitsPerByte = 8;
 const int kBitsPerByteLog2 = 3;
 const int kBitsPerPointer = kPointerSize * kBitsPerByte;
@@ -254,364 +223,6 @@
 const int kBinary32MantissaBits = 23;
 const int kBinary32ExponentShift = 23;
 
-// Zap-value: The value used for zapping dead objects.
-// Should be a recognizable hex value tagged as a heap object pointer.
-#ifdef V8_HOST_ARCH_64_BIT
-const Address kZapValue =
-    reinterpret_cast<Address>(V8_UINT64_C(0xdeadbeedbeadbeed));
-const Address kHandleZapValue =
-    reinterpret_cast<Address>(V8_UINT64_C(0x1baddead0baddead));
-const Address kFromSpaceZapValue =
-    reinterpret_cast<Address>(V8_UINT64_C(0x1beefdad0beefdad));
-const uint64_t kDebugZapValue = 0xbadbaddbbadbaddb;
-#else
-const Address kZapValue = reinterpret_cast<Address>(0xdeadbeed);
-const Address kHandleZapValue = reinterpret_cast<Address>(0xbaddead);
-const Address kFromSpaceZapValue = reinterpret_cast<Address>(0xbeefdad);
-const uint32_t kDebugZapValue = 0xbadbaddb;
-#endif
-
-
-// Number of bits to represent the page size for paged spaces. The value of 13
-// gives 8K bytes per page.
-const int kPageSizeBits = 13;
-
-// On Intel architecture, cache line size is 64 bytes.
-// On ARM it may be less (32 bytes), but as far this constant is
-// used for aligning data, it doesn't hurt to align on a greater value.
-const int kProcessorCacheLineSize = 64;
-
-// Constants relevant to double precision floating point numbers.
-
-// Quiet NaNs have bits 51 to 62 set, possibly the sign bit, and no
-// other bits set.
-const uint64_t kQuietNaNMask = static_cast<uint64_t>(0xfff) << 51;
-// If looking only at the top 32 bits, the QNaN mask is bits 19 to 30.
-const uint32_t kQuietNaNHighBitsMask = 0xfff << (51 - 32);
-
-
-// -----------------------------------------------------------------------------
-// Forward declarations for frequently used classes
-// (sorted alphabetically)
-
-class AccessorInfo;
-class Allocation;
-class Arguments;
-class Assembler;
-class AssertNoAllocation;
-class BreakableStatement;
-class Code;
-class CodeGenerator;
-class CodeStub;
-class Context;
-class Debug;
-class Debugger;
-class DebugInfo;
-class Descriptor;
-class DescriptorArray;
-class Expression;
-class ExternalReference;
-class FixedArray;
-class FunctionEntry;
-class FunctionLiteral;
-class FunctionTemplateInfo;
-class NumberDictionary;
-class StringDictionary;
-class FreeStoreAllocationPolicy;
-template <typename T> class Handle;
-class Heap;
-class HeapObject;
-class IC;
-class InterceptorInfo;
-class IterationStatement;
-class JSArray;
-class JSFunction;
-class JSObject;
-class LargeObjectSpace;
-template <typename T, class P = FreeStoreAllocationPolicy> class List;
-class LookupResult;
-class MacroAssembler;
-class Map;
-class MapSpace;
-class MarkCompactCollector;
-class NewSpace;
-class NodeVisitor;
-class Object;
-class MaybeObject;
-class OldSpace;
-class Property;
-class Proxy;
-class RegExpNode;
-struct RegExpCompileData;
-class RegExpTree;
-class RegExpCompiler;
-class RegExpVisitor;
-class Scope;
-template<class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
-class SerializedScopeInfo;
-class Script;
-class Slot;
-class Smi;
-template <typename Config, class Allocator = FreeStoreAllocationPolicy>
-    class SplayTree;
-class Statement;
-class String;
-class Struct;
-class SwitchStatement;
-class AstVisitor;
-class Variable;
-class VariableProxy;
-class RelocInfo;
-class Deserializer;
-class MessageLocation;
-class ObjectGroup;
-class TickSample;
-class VirtualMemory;
-class Mutex;
-
-typedef bool (*WeakSlotCallback)(Object** pointer);
-
-// -----------------------------------------------------------------------------
-// Miscellaneous
-
-// NOTE: SpaceIterator depends on AllocationSpace enumeration values being
-// consecutive.
-enum AllocationSpace {
-  NEW_SPACE,            // Semispaces collected with copying collector.
-  OLD_POINTER_SPACE,    // May contain pointers to new space.
-  OLD_DATA_SPACE,       // Must not have pointers to new space.
-  CODE_SPACE,           // No pointers to new space, marked executable.
-  MAP_SPACE,            // Only and all map objects.
-  CELL_SPACE,           // Only and all cell objects.
-  LO_SPACE,             // Promoted large objects.
-
-  FIRST_SPACE = NEW_SPACE,
-  LAST_SPACE = LO_SPACE,
-  FIRST_PAGED_SPACE = OLD_POINTER_SPACE,
-  LAST_PAGED_SPACE = CELL_SPACE
-};
-const int kSpaceTagSize = 3;
-const int kSpaceTagMask = (1 << kSpaceTagSize) - 1;
-
-
-// A flag that indicates whether objects should be pretenured when
-// allocated (allocated directly into the old generation) or not
-// (allocated in the young generation if the object size and type
-// allows).
-enum PretenureFlag { NOT_TENURED, TENURED };
-
-enum GarbageCollector { SCAVENGER, MARK_COMPACTOR };
-
-enum Executability { NOT_EXECUTABLE, EXECUTABLE };
-
-enum VisitMode { VISIT_ALL, VISIT_ALL_IN_SCAVENGE, VISIT_ONLY_STRONG };
-
-// Flag indicating whether code is built into the VM (one of the natives files).
-enum NativesFlag { NOT_NATIVES_CODE, NATIVES_CODE };
-
-
-// A CodeDesc describes a buffer holding instructions and relocation
-// information. The instructions start at the beginning of the buffer
-// and grow forward, the relocation information starts at the end of
-// the buffer and grows backward.
-//
-//  |<--------------- buffer_size ---------------->|
-//  |<-- instr_size -->|        |<-- reloc_size -->|
-//  +==================+========+==================+
-//  |   instructions   |  free  |    reloc info    |
-//  +==================+========+==================+
-//  ^
-//  |
-//  buffer
-
-struct CodeDesc {
-  byte* buffer;
-  int buffer_size;
-  int instr_size;
-  int reloc_size;
-  Assembler* origin;
-};
-
-
-// Callback function on object slots, used for iterating heap object slots in
-// HeapObjects, global pointers to heap objects, etc. The callback allows the
-// callback function to change the value of the slot.
-typedef void (*ObjectSlotCallback)(HeapObject** pointer);
-
-
-// Callback function used for iterating objects in heap spaces,
-// for example, scanning heap objects.
-typedef int (*HeapObjectCallback)(HeapObject* obj);
-
-
-// Callback function used for checking constraints when copying/relocating
-// objects. Returns true if an object can be copied/relocated from its
-// old_addr to a new_addr.
-typedef bool (*ConstraintCallback)(Address new_addr, Address old_addr);
-
-
-// Callback function on inline caches, used for iterating over inline caches
-// in compiled code.
-typedef void (*InlineCacheCallback)(Code* code, Address ic);
-
-
-// State for inline cache call sites. Aliased as IC::State.
-enum InlineCacheState {
-  // Has never been executed.
-  UNINITIALIZED,
-  // Has been executed but monomorhic state has been delayed.
-  PREMONOMORPHIC,
-  // Has been executed and only one receiver type has been seen.
-  MONOMORPHIC,
-  // Like MONOMORPHIC but check failed due to prototype.
-  MONOMORPHIC_PROTOTYPE_FAILURE,
-  // Multiple receiver types have been seen.
-  MEGAMORPHIC,
-  // Special states for debug break or step in prepare stubs.
-  DEBUG_BREAK,
-  DEBUG_PREPARE_STEP_IN
-};
-
-
-enum InLoopFlag {
-  NOT_IN_LOOP,
-  IN_LOOP
-};
-
-
-enum CallFunctionFlags {
-  NO_CALL_FUNCTION_FLAGS = 0,
-  RECEIVER_MIGHT_BE_VALUE = 1 << 0  // Receiver might not be a JSObject.
-};
-
-
-enum InlineCacheHolderFlag {
-  OWN_MAP,  // For fast properties objects.
-  PROTOTYPE_MAP  // For slow properties objects (except GlobalObjects).
-};
-
-
-// Type of properties.
-// Order of properties is significant.
-// Must fit in the BitField PropertyDetails::TypeField.
-// A copy of this is in mirror-debugger.js.
-enum PropertyType {
-  NORMAL              = 0,  // only in slow mode
-  FIELD               = 1,  // only in fast mode
-  CONSTANT_FUNCTION   = 2,  // only in fast mode
-  CALLBACKS           = 3,
-  INTERCEPTOR         = 4,  // only in lookup results, not in descriptors.
-  MAP_TRANSITION      = 5,  // only in fast mode
-  CONSTANT_TRANSITION = 6,  // only in fast mode
-  NULL_DESCRIPTOR     = 7,  // only in fast mode
-  // All properties before MAP_TRANSITION are real.
-  FIRST_PHANTOM_PROPERTY_TYPE = MAP_TRANSITION,
-  // There are no IC stubs for NULL_DESCRIPTORS. Therefore,
-  // NULL_DESCRIPTOR can be used as the type flag for IC stubs for
-  // nonexistent properties.
-  NONEXISTENT = NULL_DESCRIPTOR
-};
-
-
-// Whether to remove map transitions and constant transitions from a
-// DescriptorArray.
-enum TransitionFlag {
-  REMOVE_TRANSITIONS,
-  KEEP_TRANSITIONS
-};
-
-
-// Union used for fast testing of specific double values.
-union DoubleRepresentation {
-  double  value;
-  int64_t bits;
-  DoubleRepresentation(double x) { value = x; }
-};
-
-
-// Union used for customized checking of the IEEE double types
-// inlined within v8 runtime, rather than going to the underlying
-// platform headers and libraries
-union IeeeDoubleLittleEndianArchType {
-  double d;
-  struct {
-    unsigned int man_low  :32;
-    unsigned int man_high :20;
-    unsigned int exp      :11;
-    unsigned int sign     :1;
-  } bits;
-};
-
-
-union IeeeDoubleBigEndianArchType {
-  double d;
-  struct {
-    unsigned int sign     :1;
-    unsigned int exp      :11;
-    unsigned int man_high :20;
-    unsigned int man_low  :32;
-  } bits;
-};
-
-
-// AccessorCallback
-struct AccessorDescriptor {
-  MaybeObject* (*getter)(Object* object, void* data);
-  MaybeObject* (*setter)(JSObject* object, Object* value, void* data);
-  void* data;
-};
-
-
-// Logging and profiling.
-// A StateTag represents a possible state of the VM.  When compiled with
-// ENABLE_VMSTATE_TRACKING, the logger maintains a stack of these.
-// Creating a VMState object enters a state by pushing on the stack, and
-// destroying a VMState object leaves a state by popping the current state
-// from the stack.
-
-#define STATE_TAG_LIST(V) \
-  V(JS)                   \
-  V(GC)                   \
-  V(COMPILER)             \
-  V(OTHER)                \
-  V(EXTERNAL)
-
-enum StateTag {
-#define DEF_STATE_TAG(name) name,
-  STATE_TAG_LIST(DEF_STATE_TAG)
-#undef DEF_STATE_TAG
-  // Pseudo-types.
-  state_tag_count
-};
-
-
-// -----------------------------------------------------------------------------
-// Macros
-
-// Testers for test.
-
-#define HAS_SMI_TAG(value) \
-  ((reinterpret_cast<intptr_t>(value) & kSmiTagMask) == kSmiTag)
-
-#define HAS_FAILURE_TAG(value) \
-  ((reinterpret_cast<intptr_t>(value) & kFailureTagMask) == kFailureTag)
-
-// OBJECT_POINTER_ALIGN returns the value aligned as a HeapObject pointer
-#define OBJECT_POINTER_ALIGN(value)                             \
-  (((value) + kObjectAlignmentMask) & ~kObjectAlignmentMask)
-
-// POINTER_SIZE_ALIGN returns the value aligned as a pointer.
-#define POINTER_SIZE_ALIGN(value)                               \
-  (((value) + kPointerAlignmentMask) & ~kPointerAlignmentMask)
-
-// MAP_POINTER_ALIGN returns the value aligned as a map pointer.
-#define MAP_POINTER_ALIGN(value)                                \
-  (((value) + kMapAlignmentMask) & ~kMapAlignmentMask)
-
-// CODE_POINTER_ALIGN returns the value aligned as a generated code segment.
-#define CODE_POINTER_ALIGN(value)                               \
-  (((value) + kCodeAlignmentMask) & ~kCodeAlignmentMask)
-
 // The expression OFFSET_OF(type, field) computes the byte-offset
 // of the specified field relative to the containing type. This
 // corresponds to 'offsetof' (in stddef.h), except that it doesn't
@@ -668,26 +279,6 @@
   DISALLOW_COPY_AND_ASSIGN(TypeName)
 
 
-// Support for tracking C++ memory allocation.  Insert TRACK_MEMORY("Fisk")
-// inside a C++ class and new and delete will be overloaded so logging is
-// performed.
-// This file (globals.h) is included before log.h, so we use direct calls to
-// the Logger rather than the LOG macro.
-#ifdef DEBUG
-#define TRACK_MEMORY(name) \
-  void* operator new(size_t size) { \
-    void* result = ::operator new(size); \
-    Logger::NewEvent(name, result, size); \
-    return result; \
-  } \
-  void operator delete(void* object) { \
-    Logger::DeleteEvent(name, object); \
-    ::operator delete(object); \
-  }
-#else
-#define TRACK_MEMORY(name)
-#endif
-
 // Define used for helping GCC to make better inlining. Don't bother for debug
 // builds. On GCC 3.4.5 using __attribute__((always_inline)) causes compilation
 // errors in debug build.
@@ -711,20 +302,12 @@
 #define MUST_USE_RESULT
 #endif
 
+// -----------------------------------------------------------------------------
+// Forward declarations for frequently used classes
+// (sorted alphabetically)
 
-// Feature flags bit positions. They are mostly based on the CPUID spec.
-// (We assign CPUID itself to one of the currently reserved bits --
-// feel free to change this if needed.)
-// On X86/X64, values below 32 are bits in EDX, values above 32 are bits in ECX.
-enum CpuFeature { SSE4_1 = 32 + 19,  // x86
-                  SSE3 = 32 + 0,     // x86
-                  SSE2 = 26,   // x86
-                  CMOV = 15,   // x86
-                  RDTSC = 4,   // x86
-                  CPUID = 10,  // x86
-                  VFP3 = 1,    // ARM
-                  ARMv7 = 2,   // ARM
-                  SAHF = 0};   // x86
+class FreeStoreAllocationPolicy;
+template <typename T, class P = FreeStoreAllocationPolicy> class List;
 
 } }  // namespace v8::internal
 
diff --git a/src/handles.cc b/src/handles.cc
index 7a46bc3..37a5011 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -37,6 +37,7 @@
 #include "global-handles.h"
 #include "natives.h"
 #include "runtime.h"
+#include "string-search.h"
 #include "stub-cache.h"
 
 namespace v8 {
@@ -142,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.
@@ -499,48 +500,59 @@
 
   Handle<FixedArray> array = CalculateLineEnds(src, true);
 
+  if (*array != Heap::empty_fixed_array()) {
+    array->set_map(Heap::fixed_cow_array_map());
+  }
+
   script->set_line_ends(*array);
   ASSERT(script->line_ends()->IsFixedArray());
 }
 
 
-Handle<FixedArray> CalculateLineEnds(Handle<String> src,
-                                     bool with_imaginary_last_new_line) {
-  const int src_len = src->length();
-  Handle<String> new_line = Factory::NewStringFromAscii(CStrVector("\n"));
+template <typename SourceChar>
+static void CalculateLineEnds(List<int>* line_ends,
+                              Vector<const SourceChar> src,
+                              bool with_last_line) {
+  const int src_len = src.length();
+  StringSearch<char, SourceChar> search(CStrVector("\n"));
 
-  // Pass 1: Identify line count.
-  int line_count = 0;
+  // Find and record line ends.
   int position = 0;
   while (position != -1 && position < src_len) {
-    position = Runtime::StringMatch(src, new_line, position);
+    position = search.Search(src, position);
     if (position != -1) {
+      line_ends->Add(position);
       position++;
-    }
-    if (position != -1) {
-      line_count++;
-    } else if (with_imaginary_last_new_line) {
+    } else if (with_last_line) {
       // Even if the last line misses a line end, it is counted.
-      line_count++;
+      line_ends->Add(src_len);
+      return;
     }
   }
+}
 
-  // Pass 2: Fill in line ends positions
+
+Handle<FixedArray> CalculateLineEnds(Handle<String> src,
+                                     bool with_last_line) {
+  src = FlattenGetString(src);
+  // Rough estimate of line count based on a roughly estimated average
+  // length of (unpacked) code.
+  int line_count_estimate = src->length() >> 4;
+  List<int> line_ends(line_count_estimate);
+  {
+    AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid.
+    // Dispatch on type of strings.
+    if (src->IsAsciiRepresentation()) {
+      CalculateLineEnds(&line_ends, src->ToAsciiVector(), with_last_line);
+    } else {
+      CalculateLineEnds(&line_ends, src->ToUC16Vector(), with_last_line);
+    }
+  }
+  int line_count = line_ends.length();
   Handle<FixedArray> array = Factory::NewFixedArray(line_count);
-  int array_index = 0;
-  position = 0;
-  while (position != -1 && position < src_len) {
-    position = Runtime::StringMatch(src, new_line, position);
-    if (position != -1) {
-      array->set(array_index++, Smi::FromInt(position++));
-    } else if (with_imaginary_last_new_line) {
-      // If the script does not end with a line ending add the final end
-      // position as just past the last line ending.
-      array->set(array_index++, Smi::FromInt(src_len));
-    }
+  for (int i = 0; i < line_count; i++) {
+    array->set(i, Smi::FromInt(line_ends[i]));
   }
-  ASSERT(array_index == line_count);
-
   return array;
 }
 
@@ -552,11 +564,11 @@
   FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
   const int line_ends_len = line_ends_array->length();
 
-  if (!line_ends_len)
-    return -1;
+  if (!line_ends_len) return -1;
 
-  if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos)
+  if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
     return script->line_offset()->value();
+  }
 
   int left = 0;
   int right = line_ends_len;
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 e47d66f..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),
@@ -788,15 +789,13 @@
 void AggregatedHeapSnapshotGenerator::CollectStats(HeapObject* obj) {
   InstanceType type = obj->map()->instance_type();
   ASSERT(0 <= type && type <= LAST_TYPE);
-  if (!FreeListNode::IsFreeListNode(obj)) {
-    agg_snapshot_->info()[type].increment_number(1);
-    agg_snapshot_->info()[type].increment_bytes(obj->Size());
-  }
+  agg_snapshot_->info()[type].increment_number(1);
+  agg_snapshot_->info()[type].increment_bytes(obj->Size());
 }
 
 
 void AggregatedHeapSnapshotGenerator::GenerateSnapshot() {
-  HeapIterator iterator;
+  HeapIterator iterator(HeapIterator::kPreciseFiltering);
   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
     CollectStats(obj);
     agg_snapshot_->js_cons_profile()->CollectStats(obj);
@@ -888,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);
   }
 }
@@ -929,10 +929,16 @@
   void Call(const JSObjectsCluster& cluster,
             const NumberAndSizeInfo& number_and_size) {
     int child_index, retainer_index;
-    map_->CountReference(ClusterAsHeapObject(cluster), child_,
-                         &child_index, &retainer_index);
-    map_->Map(ClusterAsHeapObject(cluster))->SetElementReference(
-        child_index, number_and_size.number(), child_entry_, retainer_index);
+    map_->CountReference(ClusterAsHeapObject(cluster),
+                         child_,
+                         &child_index,
+                         &retainer_index);
+    map_->Map(ClusterAsHeapObject(cluster))->SetIndexedReference(
+        HeapGraphEdge::kElement,
+        child_index,
+        number_and_size.number(),
+        child_entry_,
+        retainer_index);
   }
 
  private:
@@ -1044,7 +1050,7 @@
     if (agg_snapshot_->info()[i].bytes() > 0) {
       AddEntryFromAggregatedSnapshot(snapshot,
                                      &root_child_index,
-                                     HeapEntry::kInternal,
+                                     HeapEntry::kHidden,
                                      agg_snapshot_->info()[i].name(),
                                      agg_snapshot_->info()[i].number(),
                                      agg_snapshot_->info()[i].bytes(),
@@ -1060,6 +1066,8 @@
 
   // Fill up references.
   IterateRetainers<AllocatingRetainersIterator>(&entries_map);
+
+  snapshot->SetDominatorsToSelf();
 }
 
 
diff --git a/src/heap.cc b/src/heap.cc
index 134f40e..26859d7 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -38,7 +38,7 @@
 #include "mark-compact.h"
 #include "natives.h"
 #include "objects-visiting.h"
-#include "scanner.h"
+#include "scanner-base.h"
 #include "scopeinfo.h"
 #include "snapshot.h"
 #include "v8threads.h"
@@ -79,25 +79,34 @@
 // semispace_size_ should be a power of 2 and old_generation_size_ should be
 // a multiple of Page::kPageSize.
 #if defined(ANDROID)
-int Heap::max_semispace_size_  = 2*MB;
+static const int default_max_semispace_size_  = 2*MB;
 intptr_t Heap::max_old_generation_size_ = 192*MB;
 int Heap::initial_semispace_size_ = 128*KB;
 intptr_t Heap::code_range_size_ = 0;
 intptr_t Heap::max_executable_size_ = max_old_generation_size_;
 #elif defined(V8_TARGET_ARCH_X64)
-int Heap::max_semispace_size_  = 16*MB;
+static const int default_max_semispace_size_  = 16*MB;
 intptr_t Heap::max_old_generation_size_ = 1*GB;
 int Heap::initial_semispace_size_ = 1*MB;
 intptr_t Heap::code_range_size_ = 512*MB;
 intptr_t Heap::max_executable_size_ = 256*MB;
 #else
-int Heap::max_semispace_size_  = 8*MB;
+static const int default_max_semispace_size_  = 8*MB;
 intptr_t Heap::max_old_generation_size_ = 512*MB;
 int Heap::initial_semispace_size_ = 512*KB;
 intptr_t Heap::code_range_size_ = 0;
 intptr_t Heap::max_executable_size_ = 128*MB;
 #endif
 
+// Allow build-time customization of the max semispace size. Building
+// V8 with snapshots and a non-default max semispace size is much
+// easier if you can define it as part of the build environment.
+#if defined(V8_MAX_SEMISPACE_SIZE)
+int Heap::max_semispace_size_ = V8_MAX_SEMISPACE_SIZE;
+#else
+int Heap::max_semispace_size_ = default_max_semispace_size_;
+#endif
+
 // The snapshot semispace size will be the default semispace size if
 // snapshotting is used and will be the requested semispace size as
 // set up by ConfigureHeap otherwise.
@@ -395,7 +404,7 @@
   intptr_t total = 0;
   AllSpaces spaces;
   for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
-    total += space->Size();
+    total += space->SizeOfObjects();
   }
   return total;
 }
@@ -3240,7 +3249,8 @@
   const uc32 kMaxSupportedChar = 0xFFFF;
   // Count the number of characters in the UTF-8 string and check if
   // it is an ASCII string.
-  Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
+  Access<ScannerConstants::Utf8Decoder>
+      decoder(ScannerConstants::utf8_decoder());
   decoder->Reset(string.start(), string.length());
   int chars = 0;
   bool is_ascii = true;
@@ -4399,13 +4409,10 @@
       MemoryAllocator::Size() + MemoryAllocator::Available();
   *stats->os_error = OS::GetLastError();
   if (take_snapshot) {
-    HeapIterator iterator;
+    HeapIterator iterator(HeapIterator::kPreciseFiltering);
     for (HeapObject* obj = iterator.next();
          obj != NULL;
          obj = iterator.next()) {
-      // Note: snapshot won't be precise because IsFreeListNode returns true
-      // for any bytearray.
-      if (FreeListNode::IsFreeListNode(obj)) continue;
       InstanceType type = obj->map()->instance_type();
       ASSERT(0 <= type && type <= LAST_TYPE);
       stats->objects_per_type[type]++;
@@ -4760,7 +4767,17 @@
 }
 
 
-SpaceIterator::SpaceIterator() : current_space_(FIRST_SPACE), iterator_(NULL) {
+SpaceIterator::SpaceIterator()
+    : current_space_(FIRST_SPACE),
+      iterator_(NULL),
+      size_func_(NULL) {
+}
+
+
+SpaceIterator::SpaceIterator(HeapObjectCallback size_func)
+    : current_space_(FIRST_SPACE),
+      iterator_(NULL),
+      size_func_(size_func) {
 }
 
 
@@ -4798,25 +4815,25 @@
 
   switch (current_space_) {
     case NEW_SPACE:
-      iterator_ = new SemiSpaceIterator(Heap::new_space());
+      iterator_ = new SemiSpaceIterator(Heap::new_space(), size_func_);
       break;
     case OLD_POINTER_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::old_pointer_space());
+      iterator_ = new HeapObjectIterator(Heap::old_pointer_space(), size_func_);
       break;
     case OLD_DATA_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::old_data_space());
+      iterator_ = new HeapObjectIterator(Heap::old_data_space(), size_func_);
       break;
     case CODE_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::code_space());
+      iterator_ = new HeapObjectIterator(Heap::code_space(), size_func_);
       break;
     case MAP_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::map_space());
+      iterator_ = new HeapObjectIterator(Heap::map_space(), size_func_);
       break;
     case CELL_SPACE:
-      iterator_ = new HeapObjectIterator(Heap::cell_space());
+      iterator_ = new HeapObjectIterator(Heap::cell_space(), size_func_);
       break;
     case LO_SPACE:
-      iterator_ = new LargeObjectIterator(Heap::lo_space());
+      iterator_ = new LargeObjectIterator(Heap::lo_space(), size_func_);
       break;
   }
 
@@ -4826,7 +4843,54 @@
 }
 
 
-HeapIterator::HeapIterator() {
+class FreeListNodesFilter {
+ public:
+  FreeListNodesFilter() {
+    MarkFreeListNodes();
+  }
+
+  inline bool IsFreeListNode(HeapObject* object) {
+    if (object->IsMarked()) {
+      object->ClearMark();
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+ private:
+  void MarkFreeListNodes() {
+    Heap::old_pointer_space()->MarkFreeListNodes();
+    Heap::old_data_space()->MarkFreeListNodes();
+    MarkCodeSpaceFreeListNodes();
+    Heap::map_space()->MarkFreeListNodes();
+    Heap::cell_space()->MarkFreeListNodes();
+  }
+
+  void MarkCodeSpaceFreeListNodes() {
+    // For code space, using FreeListNode::IsFreeListNode is OK.
+    HeapObjectIterator iter(Heap::code_space());
+    for (HeapObject* obj = iter.next_object();
+         obj != NULL;
+         obj = iter.next_object()) {
+      if (FreeListNode::IsFreeListNode(obj)) obj->SetMark();
+    }
+  }
+
+  AssertNoAllocation no_alloc;
+};
+
+
+HeapIterator::HeapIterator()
+    : filtering_(HeapIterator::kNoFiltering),
+      filter_(NULL) {
+  Init();
+}
+
+
+HeapIterator::HeapIterator(HeapIterator::FreeListNodesFiltering filtering)
+    : filtering_(filtering),
+      filter_(NULL) {
   Init();
 }
 
@@ -4838,20 +4902,44 @@
 
 void HeapIterator::Init() {
   // Start the iteration.
-  space_iterator_ = new SpaceIterator();
+  if (filtering_ == kPreciseFiltering) {
+    filter_ = new FreeListNodesFilter;
+    space_iterator_ =
+        new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject);
+  } else {
+    space_iterator_ = new SpaceIterator;
+  }
   object_iterator_ = space_iterator_->next();
 }
 
 
 void HeapIterator::Shutdown() {
+#ifdef DEBUG
+  // Assert that in precise mode we have iterated through all
+  // objects. Otherwise, heap will be left in an inconsistent state.
+  if (filtering_ == kPreciseFiltering) {
+    ASSERT(object_iterator_ == NULL);
+  }
+#endif
   // Make sure the last iterator is deallocated.
   delete space_iterator_;
   space_iterator_ = NULL;
   object_iterator_ = NULL;
+  delete filter_;
+  filter_ = NULL;
 }
 
 
 HeapObject* HeapIterator::next() {
+  if (filter_ == NULL) return NextObject();
+
+  HeapObject* obj = NextObject();
+  while (obj != NULL && filter_->IsFreeListNode(obj)) obj = NextObject();
+  return obj;
+}
+
+
+HeapObject* HeapIterator::NextObject() {
   // No iterator means we are done.
   if (object_iterator_ == NULL) return NULL;
 
diff --git a/src/heap.h b/src/heap.h
index c37ced3..93caf3b 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1558,6 +1558,7 @@
 class SpaceIterator : public Malloced {
  public:
   SpaceIterator();
+  explicit SpaceIterator(HeapObjectCallback size_func);
   virtual ~SpaceIterator();
 
   bool has_next();
@@ -1568,17 +1569,31 @@
 
   int current_space_;  // from enum AllocationSpace.
   ObjectIterator* iterator_;  // object iterator for the current space.
+  HeapObjectCallback size_func_;
 };
 
 
-// A HeapIterator provides iteration over the whole heap It aggregates a the
-// specific iterators for the different spaces as these can only iterate over
-// one space only.
+// A HeapIterator provides iteration over the whole heap. It
+// aggregates the specific iterators for the different spaces as
+// these can only iterate over one space only.
+//
+// HeapIterator can skip free list nodes (that is, de-allocated heap
+// objects that still remain in the heap). As implementation of free
+// nodes filtering uses GC marks, it can't be used during MS/MC GC
+// phases. Also, it is forbidden to interrupt iteration in this mode,
+// as this will leave heap objects marked (and thus, unusable).
+class FreeListNodesFilter;
 
 class HeapIterator BASE_EMBEDDED {
  public:
-  explicit HeapIterator();
-  virtual ~HeapIterator();
+  enum FreeListNodesFiltering {
+    kNoFiltering,
+    kPreciseFiltering
+  };
+
+  HeapIterator();
+  explicit HeapIterator(FreeListNodesFiltering filtering);
+  ~HeapIterator();
 
   HeapObject* next();
   void reset();
@@ -1586,10 +1601,12 @@
  private:
   // Perform the initialization.
   void Init();
-
   // Perform all necessary shutdown (destruction) work.
   void Shutdown();
+  HeapObject* NextObject();
 
+  FreeListNodesFiltering filtering_;
+  FreeListNodesFilter* filter_;
   // Space iterator for iterating all the spaces.
   SpaceIterator* space_iterator_;
   // Object iterator for the space currently being iterated.
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index a7d658b..5975ad2 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -80,8 +80,9 @@
   __ pop(edx);
   __ push(esi);
   __ push(edx);
+  __ push(Immediate(Factory::false_value()));
   __ push(ecx);  // Restore return address.
-  __ TailCallRuntime(Runtime::kNewClosure, 2, 1);
+  __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
 }
 
 
@@ -3058,35 +3059,6 @@
 }
 
 
-void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
-  __ PrepareCallApiFunction(kStackSpace, kArgc);
-  STATIC_ASSERT(kArgc == 2);
-  __ mov(ApiParameterOperand(0), ebx);  // name.
-  __ mov(ApiParameterOperand(1), eax);  // arguments pointer.
-  __ CallApiFunctionAndReturn(fun(), kArgc);
-}
-
-
-void ApiCallEntryStub::Generate(MacroAssembler* masm) {
-  __ PrepareCallApiFunction(kStackSpace, kArgc);
-  STATIC_ASSERT(kArgc == 5);
-
-  // Allocate the v8::Arguments structure in the arguments' space since
-  // it's not controlled by GC.
-  __ mov(ApiParameterOperand(1), eax);  // v8::Arguments::implicit_args_.
-  __ mov(ApiParameterOperand(2), ebx);  // v8::Arguments::values_.
-  __ mov(ApiParameterOperand(3), edx);  // v8::Arguments::length_.
-  // v8::Arguments::is_construct_call_.
-  __ mov(ApiParameterOperand(4), Immediate(0));
-
-  // v8::InvocationCallback's argument.
-  __ lea(eax, ApiParameterOperand(1));
-  __ mov(ApiParameterOperand(0), eax);
-
-  __ CallApiFunctionAndReturn(fun(), kArgc);
-}
-
-
 void CEntryStub::GenerateCore(MacroAssembler* masm,
                               Label* throw_normal_exception,
                               Label* throw_termination_exception,
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 6f4ef87..f5ab357 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -154,7 +154,7 @@
       safe_int32_mode_enabled_(true),
       function_return_is_shadowed_(false),
       in_spilled_code_(false),
-      jit_cookie_((FLAG_mask_constants_with_cookie) ? V8::Random() : 0) {
+      jit_cookie_((FLAG_mask_constants_with_cookie) ? V8::RandomPrivate() : 0) {
 }
 
 
@@ -686,10 +686,10 @@
 
 void CodeGenerator::LoadGlobal() {
   if (in_spilled_code()) {
-    frame_->EmitPush(GlobalObject());
+    frame_->EmitPush(GlobalObjectOperand());
   } else {
     Result temp = allocator_->Allocate();
-    __ mov(temp.reg(), GlobalObject());
+    __ mov(temp.reg(), GlobalObjectOperand());
     frame_->Push(&temp);
   }
 }
@@ -698,7 +698,7 @@
 void CodeGenerator::LoadGlobalReceiver() {
   Result temp = allocator_->Allocate();
   Register reg = temp.reg();
-  __ mov(reg, GlobalObject());
+  __ mov(reg, GlobalObjectOperand());
   __ mov(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset));
   frame_->Push(&temp);
 }
@@ -4897,7 +4897,8 @@
 
 
 Result CodeGenerator::InstantiateFunction(
-    Handle<SharedFunctionInfo> function_info) {
+    Handle<SharedFunctionInfo> function_info,
+    bool pretenure) {
   // The inevitable call will sync frame elements to memory anyway, so
   // we do it eagerly to allow us to push the arguments directly into
   // place.
@@ -4905,7 +4906,9 @@
 
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() && function_info->num_literals() == 0) {
+  if (scope()->is_function_scope() &&
+      function_info->num_literals() == 0 &&
+      !pretenure) {
     FastNewClosureStub stub;
     frame()->EmitPush(Immediate(function_info));
     return frame()->CallStub(&stub, 1);
@@ -4914,7 +4917,10 @@
     // shared function info.
     frame()->EmitPush(esi);
     frame()->EmitPush(Immediate(function_info));
-    return frame()->CallRuntime(Runtime::kNewClosure, 2);
+    frame()->EmitPush(Immediate(pretenure
+                                ? Factory::true_value()
+                                : Factory::false_value()));
+    return frame()->CallRuntime(Runtime::kNewClosure, 3);
   }
 }
 
@@ -4930,7 +4936,7 @@
     SetStackOverflow();
     return;
   }
-  Result result = InstantiateFunction(function_info);
+  Result result = InstantiateFunction(function_info, node->pretenure());
   frame()->Push(&result);
 }
 
@@ -4939,7 +4945,7 @@
     SharedFunctionInfoLiteral* node) {
   ASSERT(!in_safe_int32_mode());
   Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
-  Result result = InstantiateFunction(node->shared_function_info());
+  Result result = InstantiateFunction(node->shared_function_info(), false);
   frame()->Push(&result);
 }
 
@@ -6294,6 +6300,18 @@
         // Push the receiver onto the frame.
         Load(property->obj());
 
+        // Load the name of the function.
+        Load(property->key());
+
+        // Swap the name of the function and the receiver on the stack to follow
+        // the calling convention for call ICs.
+        Result key = frame_->Pop();
+        Result receiver = frame_->Pop();
+        frame_->Push(&key);
+        frame_->Push(&receiver);
+        key.Unuse();
+        receiver.Unuse();
+
         // Load the arguments.
         int arg_count = args->length();
         for (int i = 0; i < arg_count; i++) {
@@ -6301,15 +6319,14 @@
           frame_->SpillTop();
         }
 
-        // Load the name of the function.
-        Load(property->key());
-
-        // Call the IC initialization code.
+        // Place the key on top of stack and call the IC initialization code.
+        frame_->PushElementAt(arg_count + 1);
         CodeForSourcePosition(node->position());
         Result result =
             frame_->CallKeyedCallIC(RelocInfo::CODE_TARGET,
                                     arg_count,
                                     loop_nesting());
+        frame_->Drop();  // Drop the key still on the stack.
         frame_->RestoreContextRegister();
         frame_->Push(&result);
       }
@@ -6631,6 +6648,190 @@
 }
 
 
+void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 2);
+  Load(args->at(1));
+  Load(args->at(0));
+  Result array_result = frame_->Pop();
+  array_result.ToRegister(eax);
+  frame_->SpillAll();
+
+  Label bailout;
+  Label done;
+  // All aliases of the same register have disjoint lifetimes.
+  Register array = eax;
+  Register result_pos = no_reg;
+
+  Register index = edi;
+
+  Register current_string_length = ecx;  // Will be ecx when live.
+
+  Register current_string = edx;
+
+  Register scratch = ebx;
+
+  Register scratch_2 = esi;
+  Register new_padding_chars = scratch_2;
+
+  Operand separator = Operand(esp, 4 * kPointerSize);  // Already pushed.
+  Operand elements = Operand(esp, 3 * kPointerSize);
+  Operand result = Operand(esp, 2 * kPointerSize);
+  Operand padding_chars = Operand(esp, 1 * kPointerSize);
+  Operand array_length = Operand(esp, 0);
+  __ sub(Operand(esp), Immediate(4 * kPointerSize));
+
+  // Check that eax is a JSArray
+  __ test(array, Immediate(kSmiTagMask));
+  __ j(zero, &bailout);
+  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
+  __ j(not_equal, &bailout);
+
+  // Check that the array has fast elements.
+  __ test_b(FieldOperand(scratch, Map::kBitField2Offset),
+            1 << Map::kHasFastElements);
+  __ j(zero, &bailout);
+
+  // If the array is empty, return the empty string.
+  __ mov(scratch, FieldOperand(array, JSArray::kLengthOffset));
+  __ sar(scratch, 1);
+  Label non_trivial;
+  __ j(not_zero, &non_trivial);
+  __ mov(result, Factory::empty_string());
+  __ jmp(&done);
+
+  __ bind(&non_trivial);
+  __ mov(array_length, scratch);
+
+  __ mov(scratch, FieldOperand(array, JSArray::kElementsOffset));
+  __ mov(elements, scratch);
+
+  // End of array's live range.
+  result_pos = array;
+  array = no_reg;
+
+
+  // Check that the separator is a flat ascii string.
+  __ mov(current_string, separator);
+  __ test(current_string, Immediate(kSmiTagMask));
+  __ j(zero, &bailout);
+  __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset));
+  __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
+  __ and_(scratch, Immediate(
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
+  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
+  __ j(not_equal, &bailout);
+  // If the separator is the empty string, replace it with NULL.
+  // The test for NULL is quicker than the empty string test, in a loop.
+  __ cmp(FieldOperand(current_string, SeqAsciiString::kLengthOffset),
+         Immediate(0));
+  Label separator_checked;
+  __ j(not_zero, &separator_checked);
+  __ mov(separator, Immediate(0));
+  __ bind(&separator_checked);
+
+  // Check that elements[0] is a flat ascii string, and copy it in new space.
+  __ mov(scratch, elements);
+  __ mov(current_string, FieldOperand(scratch, FixedArray::kHeaderSize));
+  __ test(current_string, Immediate(kSmiTagMask));
+  __ j(zero, &bailout);
+  __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset));
+  __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
+  __ and_(scratch, Immediate(
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
+  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
+  __ j(not_equal, &bailout);
+
+  // Allocate space to copy it.  Round up the size to the alignment granularity.
+  __ mov(current_string_length,
+         FieldOperand(current_string, String::kLengthOffset));
+  __ shr(current_string_length, 1);
+
+  // Live registers and stack values:
+  //   current_string_length: length of elements[0].
+
+  // New string result in new space = elements[0]
+  __ AllocateAsciiString(result_pos, current_string_length, scratch_2,
+                         index, no_reg, &bailout);
+  __ mov(result, result_pos);
+
+  // Adjust current_string_length to include padding bytes at end of string.
+  // Keep track of the number of padding bytes.
+  __ mov(new_padding_chars, current_string_length);
+  __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask));
+  __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask));
+  __ sub(new_padding_chars, Operand(current_string_length));
+  __ neg(new_padding_chars);
+  __ mov(padding_chars, new_padding_chars);
+
+  Label copy_loop_1_done;
+  Label copy_loop_1;
+  __ test(current_string_length, Operand(current_string_length));
+  __ j(zero, &copy_loop_1_done);
+  __ bind(&copy_loop_1);
+  __ sub(Operand(current_string_length), Immediate(kPointerSize));
+  __ mov(scratch, FieldOperand(current_string, current_string_length,
+                               times_1, SeqAsciiString::kHeaderSize));
+  __ mov(FieldOperand(result_pos, current_string_length,
+                      times_1, SeqAsciiString::kHeaderSize),
+         scratch);
+  __ j(not_zero, &copy_loop_1);
+  __ bind(&copy_loop_1_done);
+
+  __ mov(index, Immediate(1));
+  // Loop condition: while (index < length).
+  Label loop;
+  __ bind(&loop);
+  __ cmp(index, array_length);
+  __ j(greater_equal, &done);
+
+  // If the separator is the empty string, signalled by NULL, skip it.
+  Label separator_done;
+  __ mov(current_string, separator);
+  __ test(current_string, Operand(current_string));
+  __ j(zero, &separator_done);
+
+  // Append separator to result.  It is known to be a flat ascii string.
+  __ AppendStringToTopOfNewSpace(current_string, current_string_length,
+                                 result_pos, scratch, scratch_2, result,
+                                 padding_chars, &bailout);
+  __ bind(&separator_done);
+
+  // Add next element of array to the end of the result.
+  // Get current_string = array[index].
+  __ mov(scratch, elements);
+  __ mov(current_string, FieldOperand(scratch, index,
+                                      times_pointer_size,
+                                      FixedArray::kHeaderSize));
+  // If current != flat ascii string drop result, return undefined.
+  __ test(current_string, Immediate(kSmiTagMask));
+  __ j(zero, &bailout);
+  __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset));
+  __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
+  __ and_(scratch, Immediate(
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
+  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
+  __ j(not_equal, &bailout);
+
+  // Append current to the result.
+  __ AppendStringToTopOfNewSpace(current_string, current_string_length,
+                                 result_pos, scratch, scratch_2, result,
+                                 padding_chars, &bailout);
+  __ add(Operand(index), Immediate(1));
+  __ jmp(&loop);  // End while (index < length).
+
+  __ bind(&bailout);
+  __ mov(result, Factory::undefined_value());
+  __ bind(&done);
+  __ mov(eax, result);
+  // Drop temp values from the stack, and restore context register.
+  __ add(Operand(esp), Immediate(4 * kPointerSize));
+
+  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  frame_->Drop(1);
+  frame_->Push(&array_result);
+}
+
+
 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 1);
   Load(args->at(0));
@@ -6778,8 +6979,8 @@
     __ mov(scratch2_,
            FieldOperand(scratch2_, GlobalObject::kGlobalContextOffset));
     __ cmp(scratch1_,
-           CodeGenerator::ContextOperand(
-               scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
+           ContextOperand(scratch2_,
+                          Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
     __ j(not_equal, &false_result);
     // Set the bit in the map to indicate that it has been checked safe for
     // default valueOf and set true result.
@@ -7934,7 +8135,7 @@
     // Push the builtins object found in the current global object.
     Result temp = allocator()->Allocate();
     ASSERT(temp.is_valid());
-    __ mov(temp.reg(), GlobalObject());
+    __ mov(temp.reg(), GlobalObjectOperand());
     __ mov(temp.reg(), FieldOperand(temp.reg(), GlobalObject::kBuiltinsOffset));
     frame_->Push(&temp);
   }
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index 5a12e10..d1a2036 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -352,10 +352,6 @@
     return FieldOperand(array, index_as_smi, times_half_pointer_size, offset);
   }
 
-  static Operand ContextOperand(Register context, int index) {
-    return Operand(context, Context::SlotOffset(index));
-  }
-
  private:
   // Type of a member function that generates inline code for a native function.
   typedef void (CodeGenerator::*InlineFunctionGenerator)
@@ -441,10 +437,6 @@
                                             JumpTarget* slow);
 
   // Expressions
-  static Operand GlobalObject() {
-    return ContextOperand(esi, Context::GLOBAL_INDEX);
-  }
-
   void LoadCondition(Expression* expr,
                      ControlDestination* destination,
                      bool force_control);
@@ -628,16 +620,13 @@
 
   void ProcessDeclarations(ZoneList<Declaration*>* declarations);
 
-  static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
-
-  static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
-
   // Declare global variables and functions in the given array of
   // name/value pairs.
   void DeclareGlobals(Handle<FixedArray> pairs);
 
   // Instantiate the function based on the shared function info.
-  Result InstantiateFunction(Handle<SharedFunctionInfo> function_info);
+  Result InstantiateFunction(Handle<SharedFunctionInfo> function_info,
+                             bool pretenure);
 
   // Support for types.
   void GenerateIsSmi(ZoneList<Expression*>* args);
@@ -722,6 +711,7 @@
 
   void GenerateHasCachedArrayIndex(ZoneList<Expression*>* args);
   void GenerateGetCachedArrayIndex(ZoneList<Expression*>* args);
+  void GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args);
 
   // Simple condition analysis.
   enum ConditionAnalysis {
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 1ea719d..3adc48a 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -36,6 +36,7 @@
 #include "full-codegen.h"
 #include "parser.h"
 #include "scopes.h"
+#include "stub-cache.h"
 
 namespace v8 {
 namespace internal {
@@ -879,17 +880,23 @@
 }
 
 
-void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
+void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
+                                       bool pretenure) {
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() && info->num_literals() == 0) {
+  if (scope()->is_function_scope() &&
+      info->num_literals() == 0 &&
+      !pretenure) {
     FastNewClosureStub stub;
     __ push(Immediate(info));
     __ CallStub(&stub);
   } else {
     __ push(esi);
     __ push(Immediate(info));
-    __ CallRuntime(Runtime::kNewClosure, 2);
+    __ push(Immediate(pretenure
+                      ? Factory::true_value()
+                      : Factory::false_value()));
+    __ CallRuntime(Runtime::kNewClosure, 3);
   }
   context()->Plug(eax);
 }
@@ -954,7 +961,7 @@
 
   // All extension objects were empty and it is safe to use a global
   // load IC call.
-  __ mov(eax, CodeGenerator::GlobalObject());
+  __ mov(eax, GlobalObjectOperand());
   __ mov(ecx, slot->var()->name());
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
@@ -1057,7 +1064,7 @@
     Comment cmnt(masm_, "Global variable");
     // Use inline caching. Variable name is passed in ecx and the global
     // object on the stack.
-    __ mov(eax, CodeGenerator::GlobalObject());
+    __ mov(eax, GlobalObjectOperand());
     __ mov(ecx, var->name());
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
@@ -1834,7 +1841,7 @@
     // assignment.  Right-hand-side value is passed in eax, variable name in
     // ecx, and the global object on the stack.
     __ mov(ecx, var->name());
-    __ mov(edx, CodeGenerator::GlobalObject());
+    __ mov(edx, GlobalObjectOperand());
     Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
@@ -2005,7 +2012,7 @@
   // Record source position of the IC call.
   SetSourcePosition(expr->position(), FORCED_POSITION);
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
+  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
   EmitCallIC(ic, mode);
   // Restore context register.
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
@@ -2016,25 +2023,32 @@
 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
                                             Expression* key,
                                             RelocInfo::Mode mode) {
-  // Code common for calls using the IC.
+  // Load the key.
+  VisitForAccumulatorValue(key);
+
+  // Swap the name of the function and the receiver on the stack to follow
+  // the calling convention for call ICs.
+  __ pop(ecx);
+  __ push(eax);
+  __ push(ecx);
+
+  // Load the arguments.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
   { PreserveStatementPositionScope scope(masm()->positions_recorder());
     for (int i = 0; i < arg_count; i++) {
       VisitForStackValue(args->at(i));
     }
-    VisitForAccumulatorValue(key);
-    __ mov(ecx, eax);
   }
   // Record source position of the IC call.
   SetSourcePosition(expr->position(), FORCED_POSITION);
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(
-      arg_count, in_loop);
+  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
+  __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize));  // Key.
   EmitCallIC(ic, mode);
   // Restore context register.
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  context()->Plug(eax);
+  context()->DropAndPlug(1, eax);  // Drop the key still on the stack.
 }
 
 
@@ -2109,7 +2123,7 @@
     context()->DropAndPlug(1, eax);
   } else if (var != NULL && !var->is_this() && var->is_global()) {
     // Push global object as receiver for the call IC.
-    __ push(CodeGenerator::GlobalObject());
+    __ push(GlobalObjectOperand());
     EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
   } else if (var != NULL && var->AsSlot() != NULL &&
              var->AsSlot()->type() == Slot::LOOKUP) {
@@ -2144,7 +2158,7 @@
       // Push function.
       __ push(eax);
       // Push global receiver.
-      __ mov(ebx, CodeGenerator::GlobalObject());
+      __ mov(ebx, GlobalObjectOperand());
       __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
       __ bind(&call);
     }
@@ -2178,7 +2192,7 @@
         // Push result (function).
         __ push(eax);
         // Push Global receiver.
-        __ mov(ecx, CodeGenerator::GlobalObject());
+        __ mov(ecx, GlobalObjectOperand());
         __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
         EmitCallWithStub(expr);
       } else {
@@ -2199,7 +2213,7 @@
       VisitForStackValue(fun);
     }
     // Load global receiver object.
-    __ mov(ebx, CodeGenerator::GlobalObject());
+    __ mov(ebx, GlobalObjectOperand());
     __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
     // Emit function call.
     EmitCallWithStub(expr);
@@ -3076,6 +3090,190 @@
 }
 
 
+void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
+  Label bailout;
+  Label done;
+
+  ASSERT(args->length() == 2);
+  // We will leave the separator on the stack until the end of the function.
+  VisitForStackValue(args->at(1));
+  // Load this to eax (= array)
+  VisitForAccumulatorValue(args->at(0));
+
+  // All aliases of the same register have disjoint lifetimes.
+  Register array = eax;
+  Register result_pos = no_reg;
+
+  Register index = edi;
+
+  Register current_string_length = ecx;  // Will be ecx when live.
+
+  Register current_string = edx;
+
+  Register scratch = ebx;
+
+  Register scratch_2 = esi;
+  Register new_padding_chars = scratch_2;
+
+  Operand separator = Operand(esp, 4 * kPointerSize);  // Already pushed.
+  Operand elements = Operand(esp, 3 * kPointerSize);
+  Operand result = Operand(esp, 2 * kPointerSize);
+  Operand padding_chars = Operand(esp, 1 * kPointerSize);
+  Operand array_length = Operand(esp, 0);
+  __ sub(Operand(esp), Immediate(4 * kPointerSize));
+
+
+  // Check that eax is a JSArray
+  __ test(array, Immediate(kSmiTagMask));
+  __ j(zero, &bailout);
+  __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
+  __ j(not_equal, &bailout);
+
+  // Check that the array has fast elements.
+  __ test_b(FieldOperand(scratch, Map::kBitField2Offset),
+            1 << Map::kHasFastElements);
+  __ j(zero, &bailout);
+
+  // If the array is empty, return the empty string.
+  __ mov(scratch, FieldOperand(array, JSArray::kLengthOffset));
+  __ sar(scratch, 1);
+  Label non_trivial;
+  __ j(not_zero, &non_trivial);
+  __ mov(result, Factory::empty_string());
+  __ jmp(&done);
+
+  __ bind(&non_trivial);
+  __ mov(array_length, scratch);
+
+  __ mov(scratch, FieldOperand(array, JSArray::kElementsOffset));
+  __ mov(elements, scratch);
+
+  // End of array's live range.
+  result_pos = array;
+  array = no_reg;
+
+
+  // Check that the separator is a flat ascii string.
+  __ mov(current_string, separator);
+  __ test(current_string, Immediate(kSmiTagMask));
+  __ j(zero, &bailout);
+  __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset));
+  __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
+  __ and_(scratch, Immediate(
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
+  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
+  __ j(not_equal, &bailout);
+  // If the separator is the empty string, replace it with NULL.
+  // The test for NULL is quicker than the empty string test, in a loop.
+  __ cmp(FieldOperand(current_string, SeqAsciiString::kLengthOffset),
+         Immediate(0));
+  Label separator_checked;
+  __ j(not_zero, &separator_checked);
+  __ mov(separator, Immediate(0));
+  __ bind(&separator_checked);
+
+  // Check that elements[0] is a flat ascii string, and copy it in new space.
+  __ mov(scratch, elements);
+  __ mov(current_string, FieldOperand(scratch, FixedArray::kHeaderSize));
+  __ test(current_string, Immediate(kSmiTagMask));
+  __ j(zero, &bailout);
+  __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset));
+  __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
+  __ and_(scratch, Immediate(
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
+  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
+  __ j(not_equal, &bailout);
+
+  // Allocate space to copy it.  Round up the size to the alignment granularity.
+  __ mov(current_string_length,
+         FieldOperand(current_string, String::kLengthOffset));
+  __ shr(current_string_length, 1);
+
+  // Live registers and stack values:
+  //   current_string_length: length of elements[0].
+
+  // New string result in new space = elements[0]
+  __ AllocateAsciiString(result_pos, current_string_length, scratch_2,
+                         index, no_reg, &bailout);
+  __ mov(result, result_pos);
+
+  // Adjust current_string_length to include padding bytes at end of string.
+  // Keep track of the number of padding bytes.
+  __ mov(new_padding_chars, current_string_length);
+  __ add(Operand(current_string_length), Immediate(kObjectAlignmentMask));
+  __ and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask));
+  __ sub(new_padding_chars, Operand(current_string_length));
+  __ neg(new_padding_chars);
+  __ mov(padding_chars, new_padding_chars);
+
+  Label copy_loop_1_done;
+  Label copy_loop_1;
+  __ test(current_string_length, Operand(current_string_length));
+  __ j(zero, &copy_loop_1_done);
+  __ bind(&copy_loop_1);
+  __ sub(Operand(current_string_length), Immediate(kPointerSize));
+  __ mov(scratch, FieldOperand(current_string, current_string_length,
+                               times_1, SeqAsciiString::kHeaderSize));
+  __ mov(FieldOperand(result_pos, current_string_length,
+                      times_1, SeqAsciiString::kHeaderSize),
+         scratch);
+  __ j(not_zero, &copy_loop_1);
+  __ bind(&copy_loop_1_done);
+
+  __ mov(index, Immediate(1));
+  // Loop condition: while (index < length).
+  Label loop;
+  __ bind(&loop);
+  __ cmp(index, array_length);
+  __ j(greater_equal, &done);
+
+  // If the separator is the empty string, signalled by NULL, skip it.
+  Label separator_done;
+  __ mov(current_string, separator);
+  __ test(current_string, Operand(current_string));
+  __ j(zero, &separator_done);
+
+  // Append separator to result.  It is known to be a flat ascii string.
+  __ AppendStringToTopOfNewSpace(current_string, current_string_length,
+                                 result_pos, scratch, scratch_2, result,
+                                 padding_chars, &bailout);
+  __ bind(&separator_done);
+
+  // Add next element of array to the end of the result.
+  // Get current_string = array[index].
+  __ mov(scratch, elements);
+  __ mov(current_string, FieldOperand(scratch, index,
+                                      times_pointer_size,
+                                      FixedArray::kHeaderSize));
+  // If current != flat ascii string drop result, return undefined.
+  __ test(current_string, Immediate(kSmiTagMask));
+  __ j(zero, &bailout);
+  __ mov(scratch, FieldOperand(current_string, HeapObject::kMapOffset));
+  __ mov_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
+  __ and_(scratch, Immediate(
+      kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
+  __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
+  __ j(not_equal, &bailout);
+
+  // Append current to the result.
+  __ AppendStringToTopOfNewSpace(current_string, current_string_length,
+                                 result_pos, scratch, scratch_2, result,
+                                 padding_chars, &bailout);
+  __ add(Operand(index), Immediate(1));
+  __ jmp(&loop);  // End while (index < length).
+
+  __ bind(&bailout);
+  __ mov(result, Factory::undefined_value());
+  __ bind(&done);
+  __ mov(eax, result);
+  // Drop temp values from the stack, and restore context register.
+  __ add(Operand(esp), Immediate(5 * kPointerSize));
+
+  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  context()->Plug(eax);
+}
+
+
 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   Handle<String> name = expr->name();
   if (name->length() > 0 && name->Get(0) == '_') {
@@ -3089,7 +3287,7 @@
 
   if (expr->is_jsruntime()) {
     // Prepare for calling JS runtime function.
-    __ mov(eax, CodeGenerator::GlobalObject());
+    __ mov(eax, GlobalObjectOperand());
     __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
   }
 
@@ -3103,7 +3301,7 @@
     // Call the JS runtime function via a call IC.
     __ Set(ecx, Immediate(expr->name()));
     InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
+    Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
     // Restore context register.
     __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
@@ -3140,7 +3338,7 @@
           VisitForStackValue(prop->obj());
           VisitForStackValue(prop->key());
         } else if (var->is_global()) {
-          __ push(CodeGenerator::GlobalObject());
+          __ push(GlobalObjectOperand());
           __ push(Immediate(var->name()));
         } else {
           // Non-global variable.  Call the runtime to look up the context
@@ -3418,7 +3616,7 @@
 
   if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
     Comment cmnt(masm_, "Global variable");
-    __ mov(eax, CodeGenerator::GlobalObject());
+    __ mov(eax, GlobalObjectOperand());
     __ mov(ecx, Immediate(proxy->name()));
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     // Use a regular load, not a contextual load, to avoid a reference
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index b72f4df..cbf93dd 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -392,13 +392,8 @@
 }
 
 
-void MacroAssembler::EnterApiExitFrame(int stack_space,
-                                       int argc) {
+void MacroAssembler::EnterApiExitFrame(int argc) {
   EnterExitFramePrologue();
-
-  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
-  lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset));
-
   EnterExitFrameEpilogue(argc);
 }
 
@@ -411,6 +406,13 @@
   // Pop the arguments and the receiver from the caller stack.
   lea(esp, Operand(esi, 1 * kPointerSize));
 
+  // Push the return address to get ready to return.
+  push(ecx);
+
+  LeaveExitFrameEpilogue();
+}
+
+void MacroAssembler::LeaveExitFrameEpilogue() {
   // Restore current context from top and clear it in debug mode.
   ExternalReference context_address(Top::k_context_address);
   mov(esi, Operand::StaticVariable(context_address));
@@ -418,15 +420,20 @@
   mov(Operand::StaticVariable(context_address), Immediate(0));
 #endif
 
-  // Push the return address to get ready to return.
-  push(ecx);
-
   // Clear the top frame.
   ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
   mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
 }
 
 
+void MacroAssembler::LeaveApiExitFrame() {
+  mov(esp, Operand(ebp));
+  pop(ebp);
+
+  LeaveExitFrameEpilogue();
+}
+
+
 void MacroAssembler::PushTryHandler(CodeLocation try_location,
                                     HandlerType type) {
   // Adjust this code if not the case.
@@ -530,7 +537,6 @@
 
 
 void MacroAssembler::LoadAllocationTopHelper(Register result,
-                                             Register result_end,
                                              Register scratch,
                                              AllocationFlags flags) {
   ExternalReference new_space_allocation_top =
@@ -552,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));
   }
@@ -601,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;
 
@@ -657,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 =
@@ -698,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 =
@@ -882,6 +887,57 @@
       Immediate(Factory::cons_ascii_string_map()));
 }
 
+// All registers must be distinct.  Only current_string needs valid contents
+// on entry.  All registers may be invalid on exit.  result_operand is
+// unchanged, padding_chars is updated correctly.
+void MacroAssembler::AppendStringToTopOfNewSpace(
+    Register current_string,  // Tagged pointer to string to copy.
+    Register current_string_length,
+    Register result_pos,
+    Register scratch,
+    Register new_padding_chars,
+    Operand operand_result,
+    Operand operand_padding_chars,
+    Label* bailout) {
+  mov(current_string_length,
+      FieldOperand(current_string, String::kLengthOffset));
+  shr(current_string_length, 1);
+  sub(current_string_length, operand_padding_chars);
+  mov(new_padding_chars, current_string_length);
+  add(Operand(current_string_length), Immediate(kObjectAlignmentMask));
+  and_(Operand(current_string_length), Immediate(~kObjectAlignmentMask));
+  sub(new_padding_chars, Operand(current_string_length));
+  neg(new_padding_chars);
+  // We need an allocation even if current_string_length is 0, to fetch
+  // result_pos.  Consider using a faster fetch of result_pos in that case.
+  AllocateInNewSpace(current_string_length, result_pos, scratch, no_reg,
+                     bailout, NO_ALLOCATION_FLAGS);
+  sub(result_pos, operand_padding_chars);
+  mov(operand_padding_chars, new_padding_chars);
+
+  Register scratch_2 = new_padding_chars;  // Used to compute total length.
+  // Copy string to the end of result.
+  mov(current_string_length,
+      FieldOperand(current_string, String::kLengthOffset));
+  mov(scratch, operand_result);
+  mov(scratch_2, current_string_length);
+  add(scratch_2, FieldOperand(scratch, String::kLengthOffset));
+  mov(FieldOperand(scratch, String::kLengthOffset), scratch_2);
+  shr(current_string_length, 1);
+  lea(current_string,
+      FieldOperand(current_string, SeqAsciiString::kHeaderSize));
+  // Loop condition: while (--current_string_length >= 0).
+  Label copy_loop;
+  Label copy_loop_entry;
+  jmp(&copy_loop_entry);
+  bind(&copy_loop);
+  mov_b(scratch, Operand(current_string, current_string_length, times_1, 0));
+  mov_b(Operand(result_pos, current_string_length, times_1, 0), scratch);
+  bind(&copy_loop_entry);
+  sub(Operand(current_string_length), Immediate(1));
+  j(greater_equal, &copy_loop);
+}
+
 
 void MacroAssembler::NegativeZeroTest(CodeGenerator* cgen,
                                       Register result,
@@ -1110,6 +1166,17 @@
 }
 
 
+MaybeObject* MacroAssembler::TryTailCallExternalReference(
+    const ExternalReference& ext, int num_arguments, int result_size) {
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // smarter.
+  Set(eax, Immediate(num_arguments));
+  return TryJumpToExternalReference(ext);
+}
+
+
 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
                                      int num_arguments,
                                      int result_size) {
@@ -1117,6 +1184,14 @@
 }
 
 
+MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid,
+                                                int num_arguments,
+                                                int result_size) {
+  return TryTailCallExternalReference(
+      ExternalReference(fid), num_arguments, result_size);
+}
+
+
 // If true, a Handle<T> passed by value is passed and returned by
 // using the location_ field directly.  If false, it is passed and
 // returned as a pointer to a handle.
@@ -1132,20 +1207,15 @@
 }
 
 
-void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) {
+void MacroAssembler::PrepareCallApiFunction(int argc, Register scratch) {
   if (kPassHandlesDirectly) {
-    EnterApiExitFrame(stack_space, argc);
+    EnterApiExitFrame(argc);
     // When handles as passed directly we don't have to allocate extra
     // space for and pass an out parameter.
   } else {
     // We allocate two additional slots: return value and pointer to it.
-    EnterApiExitFrame(stack_space, argc + 2);
-  }
-}
+    EnterApiExitFrame(argc + 2);
 
-
-void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function, int argc) {
-  if (!kPassHandlesDirectly) {
     // The argument slots are filled as follows:
     //
     //   n + 1: output cell
@@ -1157,11 +1227,19 @@
     // Note that this is one more "argument" than the function expects
     // so the out cell will have to be popped explicitly after returning
     // from the function. The out cell contains Handle.
-    lea(eax, Operand(esp, (argc + 1) * kPointerSize));  // pointer to out cell.
-    mov(Operand(esp, 0 * kPointerSize), eax);  // output.
-    mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0));  // out cell.
-  }
 
+    // pointer to out cell.
+    lea(scratch, Operand(esp, (argc + 1) * kPointerSize));
+    mov(Operand(esp, 0 * kPointerSize), scratch);  // output.
+    if (FLAG_debug_code) {
+      mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0));  // out cell.
+    }
+  }
+}
+
+
+MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
+                                                         int stack_space) {
   ExternalReference next_address =
       ExternalReference::handle_scope_next_address();
   ExternalReference limit_address =
@@ -1210,10 +1288,14 @@
   cmp(Operand::StaticVariable(scheduled_exception_address),
          Immediate(Factory::the_hole_value()));
   j(not_equal, &promote_scheduled_exception, not_taken);
-  LeaveExitFrame();
-  ret(0);
+  LeaveApiExitFrame();
+  ret(stack_space * kPointerSize);
   bind(&promote_scheduled_exception);
-  TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
+  MaybeObject* result =
+      TryTailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
+  if (result->IsFailure()) {
+    return result;
+  }
   bind(&empty_handle);
   // It was zero; the result is undefined.
   mov(eax, Factory::undefined_value());
@@ -1227,6 +1309,8 @@
   call(Operand(eax));
   mov(eax, edi);
   jmp(&leave_exit_frame);
+
+  return result;
 }
 
 
@@ -1238,6 +1322,15 @@
 }
 
 
+MaybeObject* MacroAssembler::TryJumpToExternalReference(
+    const ExternalReference& ext) {
+  // Set the entry point and jump to the C entry runtime stub.
+  mov(ebx, Immediate(ext));
+  CEntryStub ces(1);
+  return TryTailCallStub(&ces);
+}
+
+
 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
                                     const ParameterCount& actual,
                                     Handle<Code> code_constant,
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index d65eebb..d208dbe 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -123,13 +123,17 @@
   // to the first argument in register esi.
   void EnterExitFrame();
 
-  void EnterApiExitFrame(int stack_space, int argc);
+  void EnterApiExitFrame(int argc);
 
   // Leave the current exit frame. Expects the return value in
   // register eax:edx (untouched) and the pointer to the first
   // argument in register esi.
   void LeaveExitFrame();
 
+  // Leave the current exit frame. Expects the return value in
+  // register eax (untouched).
+  void LeaveApiExitFrame();
+
   // Find the function context up the context chain.
   void LoadContext(Register dst, int context_chain_length);
 
@@ -375,6 +379,23 @@
                                Register scratch2,
                                Label* gc_required);
 
+  // All registers must be distinct.  Only current_string needs valid contents
+  // on entry.  All registers may be invalid on exit.  result_operand is
+  // unchanged, padding_chars is updated correctly.
+  // The top of new space must contain a sequential ascii string with
+  // padding_chars bytes free in its top word.  The sequential ascii string
+  // current_string is concatenated to it, allocating the necessary amount
+  // of new memory.
+  void AppendStringToTopOfNewSpace(
+      Register current_string,  // Tagged pointer to string to copy.
+      Register current_string_length,
+      Register result_pos,
+      Register scratch,
+      Register new_padding_chars,
+      Operand operand_result,
+      Operand operand_padding_chars,
+      Label* bailout);
+
   // ---------------------------------------------------------------------------
   // Support functions.
 
@@ -460,11 +481,23 @@
                                  int num_arguments,
                                  int result_size);
 
+  // Tail call of a runtime routine (jump). Try to generate the code if
+  // necessary. Do not perform a GC but instead return a retry after GC failure.
+  MUST_USE_RESULT MaybeObject* TryTailCallExternalReference(
+      const ExternalReference& ext, int num_arguments, int result_size);
+
   // Convenience function: tail call a runtime routine (jump).
   void TailCallRuntime(Runtime::FunctionId fid,
                        int num_arguments,
                        int result_size);
 
+  // Convenience function: tail call a runtime routine (jump). Try to generate
+  // the code if necessary. Do not perform a GC but instead return a retry after
+  // GC failure.
+  MUST_USE_RESULT MaybeObject* TryTailCallRuntime(Runtime::FunctionId fid,
+                                                  int num_arguments,
+                                                  int result_size);
+
   // Before calling a C-function from generated code, align arguments on stack.
   // After aligning the frame, arguments must be stored in esp[0], esp[4],
   // etc., not pushed. The argument count assumes all arguments are word sized.
@@ -485,17 +518,22 @@
   // Prepares stack to put arguments (aligns and so on). Reserves
   // space for return value if needed (assumes the return value is a handle).
   // Uses callee-saved esi to restore stack state after call. Arguments must be
-  // stored in ApiParameterOperand(0), ApiParameterOperand(1) etc.
-  void PrepareCallApiFunction(int stack_space, int argc);
+  // stored in ApiParameterOperand(0), ApiParameterOperand(1) etc. Saves
+  // context (esi).
+  void PrepareCallApiFunction(int argc, Register scratch);
 
   // Calls an API function. Allocates HandleScope, extracts
   // returned value from handle and propagates exceptions.
-  // Clobbers ebx, esi, edi and caller-save registers.
-  void CallApiFunctionAndReturn(ApiFunction* function, int argc);
+  // Clobbers ebx, edi and caller-save registers. Restores context.
+  // On return removes stack_space * kPointerSize (GCed).
+  MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function,
+                                           int stack_space);
 
   // Jump to a runtime routine.
   void JumpToExternalReference(const ExternalReference& ext);
 
+  MaybeObject* TryJumpToExternalReference(const ExternalReference& ext);
+
 
   // ---------------------------------------------------------------------------
   // Utilities
@@ -589,9 +627,10 @@
   void EnterExitFramePrologue();
   void EnterExitFrameEpilogue(int argc);
 
+  void LeaveExitFrameEpilogue();
+
   // Allocation support helpers.
   void LoadAllocationTopHelper(Register result,
-                               Register result_end,
                                Register scratch,
                                AllocationFlags flags);
   void UpdateAllocationTopHelper(Register result_end, Register scratch);
@@ -642,6 +681,17 @@
   return Operand(object, index, scale, offset - kHeapObjectTag);
 }
 
+
+static inline Operand ContextOperand(Register context, int index) {
+  return Operand(context, Context::SlotOffset(index));
+}
+
+
+static inline Operand GlobalObjectOperand() {
+  return ContextOperand(esi, Context::GLOBAL_INDEX);
+}
+
+
 // Generates an Operand for saving parameters after PrepareCallApiFunction.
 Operand ApiParameterOperand(int index);
 
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index f59928f..adcb521 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -417,7 +417,7 @@
 static const int kFastApiCallArguments = 3;
 
 
-// Reserves space for the extra arguments to FastHandleApiCall in the
+// Reserves space for the extra arguments to API function in the
 // caller's frame.
 //
 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
@@ -450,7 +450,7 @@
 }
 
 
-// Generates call to FastHandleApiCall builtin.
+// Generates call to API function.
 static bool GenerateFastApiCall(MacroAssembler* masm,
                                 const CallOptimization& optimization,
                                 int argc,
@@ -473,7 +473,7 @@
   __ mov(edi, Immediate(Handle<JSFunction>(function)));
   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
 
-  // Pass the additional arguments FastHandleApiCall expects.
+  // Pass the additional arguments.
   __ mov(Operand(esp, 2 * kPointerSize), edi);
   Object* call_data = optimization.api_call_info()->data();
   Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
@@ -486,31 +486,42 @@
            Immediate(Handle<Object>(call_data)));
   }
 
-  // Prepare arguments for ApiCallEntryStub.
+  // Prepare arguments.
   __ lea(eax, Operand(esp, 3 * kPointerSize));
-  __ lea(ebx, Operand(esp, (argc + 3) * kPointerSize));
-  __ Set(edx, Immediate(argc));
 
   Object* callback = optimization.api_call_info()->callback();
   Address api_function_address = v8::ToCData<Address>(callback);
   ApiFunction fun(api_function_address);
 
-  ApiCallEntryStub stub(api_call_info_handle, &fun);
+  const int kApiArgc = 1;  // API function gets reference to the v8::Arguments.
 
-  __ EnterInternalFrame();
+  // Allocate the v8::Arguments structure in the arguments' space since
+  // it's not controlled by GC.
+  const int kApiStackSpace = 4;
+
+  __ PrepareCallApiFunction(kApiArgc + kApiStackSpace, ebx);
+
+  __ mov(ApiParameterOperand(1), eax);  // v8::Arguments::implicit_args_.
+  __ add(Operand(eax), Immediate(argc * kPointerSize));
+  __ mov(ApiParameterOperand(2), eax);  // v8::Arguments::values_.
+  __ Set(ApiParameterOperand(3), Immediate(argc));  // v8::Arguments::length_.
+  // v8::Arguments::is_construct_call_.
+  __ Set(ApiParameterOperand(4), Immediate(0));
+
+  // v8::InvocationCallback's argument.
+  __ lea(eax, ApiParameterOperand(1));
+  __ mov(ApiParameterOperand(0), eax);
 
   // Emitting a stub call may try to allocate (if the code is not
   // already generated).  Do not allow the assembler to perform a
   // garbage collection but instead return the allocation failure
   // object.
-  MaybeObject* result = masm->TryCallStub(&stub);
+  MaybeObject* result =
+      masm->TryCallApiFunctionAndReturn(&fun, argc + kFastApiCallArguments + 1);
   if (result->IsFailure()) {
     *failure = Failure::cast(result);
     return false;
   }
-
-  __ LeaveInternalFrame();
-  __ ret((argc + 4) * kPointerSize);
   return true;
 }
 
@@ -1063,44 +1074,55 @@
 
   Handle<AccessorInfo> callback_handle(callback);
 
-  __ EnterInternalFrame();
-  // Push the stack address where the list of arguments ends.
-  __ lea(scratch2, Operand(esp, -2 * kPointerSize));
-  __ push(scratch2);
+  // Insert additional parameters into the stack frame above return address.
+  ASSERT(!scratch3.is(reg));
+  __ pop(scratch3);  // Get return address to place it below.
+
   __ push(receiver);  // receiver
+  __ mov(scratch2, Operand(esp));
+  ASSERT(!scratch2.is(reg));
   __ push(reg);  // holder
   // Push data from AccessorInfo.
   if (Heap::InNewSpace(callback_handle->data())) {
-    __ mov(scratch2, Immediate(callback_handle));
-    __ push(FieldOperand(scratch2, AccessorInfo::kDataOffset));
+    __ mov(scratch1, Immediate(callback_handle));
+    __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));
   } else {
     __ push(Immediate(Handle<Object>(callback_handle->data())));
   }
-  __ push(name_reg);  // name
+
   // Save a pointer to where we pushed the arguments pointer.
   // This will be passed as the const AccessorInfo& to the C++ callback.
-  STATIC_ASSERT(ApiGetterEntryStub::kStackSpace == 5);
-  __ lea(eax, Operand(esp, 4 * kPointerSize));
-  __ mov(ebx, esp);
+  __ push(scratch2);
+
+  __ push(name_reg);  // name
+  __ mov(ebx, esp);  // esp points to reference to name (handler).
+
+  __ push(scratch3);  // Restore return address.
 
   // Do call through the api.
   Address getter_address = v8::ToCData<Address>(callback->getter());
   ApiFunction fun(getter_address);
-  ApiGetterEntryStub stub(callback_handle, &fun);
+
+  // 3 elements array for v8::Agruments::values_, handler for name and pointer
+  // to the values (it considered as smi in GC).
+  const int kStackSpace = 5;
+  const int kApiArgc = 2;
+
+  __ PrepareCallApiFunction(kApiArgc, eax);
+  __ mov(ApiParameterOperand(0), ebx);  // name.
+  __ add(Operand(ebx), Immediate(kPointerSize));
+  __ mov(ApiParameterOperand(1), ebx);  // arguments pointer.
+
   // Emitting a stub call may try to allocate (if the code is not
   // already generated).  Do not allow the assembler to perform a
   // garbage collection but instead return the allocation failure
   // object.
-  Object* result = NULL;  // Initialization to please compiler.
-  { MaybeObject* try_call_result = masm()->TryCallStub(&stub);
-    if (!try_call_result->ToObject(&result)) {
-      *failure = Failure::cast(try_call_result);
-      return false;
-    }
+  MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
+  if (result->IsFailure()) {
+    *failure = Failure::cast(result);
+    return false;
   }
-  __ LeaveInternalFrame();
 
-  __ ret(0);
   return true;
 }
 
@@ -1119,9 +1141,8 @@
   __ j(zero, miss, not_taken);
 
   // Check that the maps haven't changed.
-  Register reg =
-      CheckPrototypes(object, receiver, holder,
-                      scratch1, scratch2, scratch3, name, miss);
+  CheckPrototypes(object, receiver, holder,
+                  scratch1, scratch2, scratch3, name, miss);
 
   // Return the constant value.
   __ mov(eax, Handle<Object>(value));
@@ -1241,8 +1262,8 @@
       __ push(receiver);
       __ push(holder_reg);
       __ mov(holder_reg, Immediate(Handle<AccessorInfo>(callback)));
-      __ push(holder_reg);
       __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
+      __ push(holder_reg);
       __ push(name_reg);
       __ push(scratch2);  // restore return address
 
@@ -2146,7 +2167,10 @@
 
       if (depth != kInvalidProtoDepth) {
         __ IncrementCounter(&Counters::call_const_fast_api, 1);
-        ReserveSpaceForFastApiCall(masm(), eax);
+
+        // Allocate space for v8::Arguments implicit values. Must be initialized
+        // before to call any runtime function.
+        __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
       }
 
       // Check that the maps haven't changed.
@@ -2226,6 +2250,12 @@
 
   if (depth != kInvalidProtoDepth) {
     Failure* failure;
+    // Move the return address on top of the stack.
+    __ mov(eax, Operand(esp, 3 * kPointerSize));
+    __ mov(Operand(esp, 0 * kPointerSize), eax);
+
+    // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
+    // duplicate of return address and will be overwritten.
     bool success = GenerateFastApiCall(masm(), optimization, argc, &failure);
     if (!success) {
       return failure;
@@ -2237,7 +2267,7 @@
   // Handle call cache miss.
   __ bind(&miss);
   if (depth != kInvalidProtoDepth) {
-    FreeSpaceForFastApiCall(masm(), eax);
+    __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
   }
   __ bind(&miss_in_smi_check);
   Object* obj;
@@ -2287,7 +2317,7 @@
                                   &miss,
                                   &failure);
   if (!success) {
-    return false;
+    return failure;
   }
 
   // Restore receiver.
@@ -2991,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
@@ -3068,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.
@@ -3095,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/ia32/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc
index a31f6e8..11e1aaf 100644
--- a/src/ia32/virtual-frame-ia32.cc
+++ b/src/ia32/virtual-frame-ia32.cc
@@ -33,6 +33,7 @@
 #include "register-allocator-inl.h"
 #include "scopes.h"
 #include "virtual-frame-inl.h"
+#include "stub-cache.h"
 
 namespace v8 {
 namespace internal {
@@ -1108,7 +1109,7 @@
   // The IC expects the name in ecx and the rest on the stack and
   // drops them all.
   InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = cgen()->ComputeCallInitialize(arg_count, in_loop);
+  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
   // Spill args, receiver, and function.  The call will drop args and
   // receiver.
   Result name = Pop();
@@ -1126,7 +1127,7 @@
   // The IC expects the name in ecx and the rest on the stack and
   // drops them all.
   InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = cgen()->ComputeKeyedCallInitialize(arg_count, in_loop);
+  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
   // Spill args, receiver, and function.  The call will drop args and
   // receiver.
   Result name = Pop();
diff --git a/src/list.h b/src/list.h
index 5a08212..24f3494 100644
--- a/src/list.h
+++ b/src/list.h
@@ -148,14 +148,6 @@
   DISALLOW_COPY_AND_ASSIGN(List);
 };
 
-class FrameElement;
-
-// Add() is inlined, ResizeAdd() called by Add() is inlined except for
-// Lists of FrameElements, and ResizeAddInternal() is inlined in ResizeAdd().
-template <>
-void List<FrameElement,
-          FreeStoreAllocationPolicy>::ResizeAdd(const FrameElement& element);
-
 } }  // namespace v8::internal
 
 #endif  // V8_LIST_H_
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/mark-compact.cc b/src/mark-compact.cc
index 484497f..40194e3 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -1099,13 +1099,6 @@
 }
 
 
-static int CountMarkedCallback(HeapObject* obj) {
-  MapWord map_word = obj->map_word();
-  map_word.ClearMark();
-  return obj->SizeFromMap(map_word.ToMap());
-}
-
-
 #ifdef DEBUG
 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) {
   live_bytes_ += obj->Size();
@@ -1152,7 +1145,7 @@
 
 
 void MarkCompactCollector::ClearNonLiveTransitions() {
-  HeapObjectIterator map_iterator(Heap::map_space(), &CountMarkedCallback);
+  HeapObjectIterator map_iterator(Heap::map_space(), &SizeOfMarkedObject);
   // Iterate over the map space, setting map transitions that go from
   // a marked map to an unmarked map to null transitions.  At the same time,
   // set all the prototype fields of maps back to their original value,
@@ -2673,6 +2666,13 @@
 }
 
 
+int MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) {
+  MapWord map_word = obj->map_word();
+  map_word.ClearMark();
+  return obj->SizeFromMap(map_word.ToMap());
+}
+
+
 void MarkCompactCollector::Initialize() {
   StaticPointersToNewGenUpdatingVisitor::Initialize();
   StaticMarkingVisitor::Initialize();
diff --git a/src/mark-compact.h b/src/mark-compact.h
index 7444c5b..1b7e600 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -119,6 +119,9 @@
   // Determine type of object and emit deletion log event.
   static void ReportDeleteIfNeeded(HeapObject* obj);
 
+  // Returns size of a possibly marked object.
+  static int SizeOfMarkedObject(HeapObject* obj);
+
   // Distinguishable invalid map encodings (for single word and multiple words)
   // that indicate free regions.
   static const uint32_t kSingleFreeEncoding = 0;
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 2b79016..69219ee 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -982,7 +982,6 @@
   VerifyPointer(name());
   VerifyPointer(data());
   VerifyPointer(flag());
-  VerifyPointer(load_stub_cache());
 }
 
 void AccessorInfo::AccessorInfoPrint() {
@@ -997,8 +996,6 @@
   data()->ShortPrint();
   PrintF("\n - flag: ");
   flag()->ShortPrint();
-  PrintF("\n - load_stub_cache: ");
-  load_stub_cache()->ShortPrint();
 }
 
 void AccessCheckInfo::AccessCheckInfoVerify() {
@@ -1048,7 +1045,6 @@
   CHECK(IsCallHandlerInfo());
   VerifyPointer(callback());
   VerifyPointer(data());
-  VerifyPointer(call_stub_cache());
 }
 
 void CallHandlerInfo::CallHandlerInfoPrint() {
@@ -1058,7 +1054,6 @@
   PrintF("\n - data: ");
   data()->ShortPrint();
   PrintF("\n - call_stub_cache: ");
-  call_stub_cache()->ShortPrint();
 }
 
 void TemplateInfo::TemplateInfoVerify() {
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 79d70e1..499cb91 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2542,7 +2542,6 @@
 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
-ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
 
 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
@@ -2557,7 +2556,6 @@
 
 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
-ACCESSORS(CallHandlerInfo, call_stub_cache, Object, kCallStubCacheOffset)
 
 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
diff --git a/src/objects.cc b/src/objects.cc
index c1cb922..f5d19e2 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -35,7 +35,7 @@
 #include "objects-inl.h"
 #include "objects-visiting.h"
 #include "macro-assembler.h"
-#include "scanner.h"
+#include "scanner-base.h"
 #include "scopeinfo.h"
 #include "string-stream.h"
 #include "utils.h"
@@ -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());
@@ -1208,7 +1205,8 @@
   // Normalize the object if the name is an actual string (not the
   // hidden symbols) and is not a real identifier.
   StringInputBuffer buffer(name);
-  if (!Scanner::IsIdentifier(&buffer) && name != Heap::hidden_symbol()) {
+  if (!ScannerConstants::IsIdentifier(&buffer)
+      && name != Heap::hidden_symbol()) {
     Object* obj;
     { MaybeObject* maybe_obj =
           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
@@ -5088,7 +5086,8 @@
 
 bool String::IsEqualTo(Vector<const char> str) {
   int slen = length();
-  Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
+  Access<ScannerConstants::Utf8Decoder>
+      decoder(ScannerConstants::utf8_decoder());
   decoder->Reset(str.start(), str.length());
   int i;
   for (i = 0; i < slen && decoder->has_more(); i++) {
diff --git a/src/objects.h b/src/objects.h
index 9d975ec..b52bac2 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -5327,7 +5327,6 @@
   DECL_ACCESSORS(data, Object)
   DECL_ACCESSORS(name, Object)
   DECL_ACCESSORS(flag, Smi)
-  DECL_ACCESSORS(load_stub_cache, Object)
 
   inline bool all_can_read();
   inline void set_all_can_read(bool value);
@@ -5353,8 +5352,7 @@
   static const int kDataOffset = kSetterOffset + kPointerSize;
   static const int kNameOffset = kDataOffset + kPointerSize;
   static const int kFlagOffset = kNameOffset + kPointerSize;
-  static const int kLoadStubCacheOffset = kFlagOffset + kPointerSize;
-  static const int kSize = kLoadStubCacheOffset + kPointerSize;
+  static const int kSize = kFlagOffset + kPointerSize;
 
  private:
   // Bit positions in flag.
@@ -5423,7 +5421,6 @@
  public:
   DECL_ACCESSORS(callback, Object)
   DECL_ACCESSORS(data, Object)
-  DECL_ACCESSORS(call_stub_cache, Object)
 
   static inline CallHandlerInfo* cast(Object* obj);
 
@@ -5434,8 +5431,7 @@
 
   static const int kCallbackOffset = HeapObject::kHeaderSize;
   static const int kDataOffset = kCallbackOffset + kPointerSize;
-  static const int kCallStubCacheOffset = kDataOffset + kPointerSize;
-  static const int kSize = kCallStubCacheOffset + kPointerSize;
+  static const int kSize = kDataOffset + kPointerSize;
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
diff --git a/src/parser.cc b/src/parser.cc
index a0f3b71..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];
 }
 
 
@@ -727,7 +607,7 @@
 
   // Initialize parser state.
   source->TryFlatten();
-  scanner_.Initialize(source, JAVASCRIPT);
+  scanner_.Initialize(source);
   ASSERT(target_stack_ == NULL);
   if (pre_data_ != NULL) pre_data_->Initialize();
 
@@ -790,8 +670,7 @@
 
   // Initialize parser state.
   source->TryFlatten();
-  scanner_.Initialize(source, info->start_position(), info->end_position(),
-                      JAVASCRIPT);
+  scanner_.Initialize(source, info->start_position(), info->end_position());
   ASSERT(target_stack_ == NULL);
   mode_ = PARSE_EAGERLY;
 
@@ -1692,11 +1571,13 @@
   // ExpressionStatement | LabelledStatement ::
   //   Expression ';'
   //   Identifier ':' Statement
-
+  bool starts_with_idenfifier = (peek() == Token::IDENTIFIER);
   Expression* expr = ParseExpression(true, CHECK_OK);
-  if (peek() == Token::COLON && expr &&
+  if (peek() == Token::COLON && starts_with_idenfifier && expr &&
       expr->AsVariableProxy() != NULL &&
       !expr->AsVariableProxy()->is_this()) {
+    // Expression is a single identifier, and not, e.g., a parenthesized
+    // identifier.
     VariableProxy* var = expr->AsVariableProxy();
     Handle<String> label = var->name();
     // TODO(1240780): We don't check for redeclaration of labels
@@ -2275,6 +2156,12 @@
     temp_scope_->AddProperty();
   }
 
+  // If we assign a function literal to a property we pretenure the
+  // literal so it can be added as a constant function property.
+  if (property != NULL && right->AsFunctionLiteral() != NULL) {
+    right->AsFunctionLiteral()->set_pretenure(true);
+  }
+
   if (fni_ != NULL) {
     // Check if the right hand side is a call to avoid inferring a
     // name if we're dealing with "a = function(){...}();"-like
@@ -3610,7 +3497,7 @@
 
 Handle<Object> JsonParser::ParseJson(Handle<String> source) {
   source->TryFlatten();
-  scanner_.Initialize(source, JSON);
+  scanner_.Initialize(source);
   Handle<Object> result = ParseJsonValue();
   if (result.is_null() || scanner_.Next() != Token::EOS) {
     if (scanner_.stack_overflow()) {
@@ -4594,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 {
@@ -4618,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;
   }
@@ -4635,51 +4523,55 @@
 }
 
 
-// Preparse, but only collect data that is immediately useful,
-// even if the preparser data is only used once.
-ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
-                                           unibrow::CharacterStream* stream,
-                                           v8::Extension* extension) {
-  Handle<Script> no_script;
-  bool allow_lazy = FLAG_lazy && (extension == NULL);
-  if (!allow_lazy) {
-    // Partial preparsing is only about lazily compiled functions.
-    // If we don't allow lazy compilation, the log data will be empty.
-    return NULL;
-  }
-  preparser::PreParser<Scanner, PartialParserRecorder> parser;
-  Scanner scanner;
-  scanner.Initialize(source, stream, JAVASCRIPT);
-  PartialParserRecorder recorder;
-  if (!parser.PreParseProgram(&scanner, &recorder, allow_lazy)) {
+// Create a Scanner for the preparser to use as input, and preparse the source.
+static ScriptDataImpl* DoPreParse(Handle<String> source,
+                                  unibrow::CharacterStream* stream,
+                                  bool allow_lazy,
+                                  ParserRecorder* recorder,
+                                  int literal_flags) {
+  V8JavaScriptScanner scanner;
+  scanner.Initialize(source, stream, literal_flags);
+  preparser::PreParser preparser;
+  if (!preparser.PreParseProgram(&scanner, recorder, allow_lazy)) {
     Top::StackOverflow();
     return NULL;
   }
 
   // Extract the accumulated data from the recorder as a single
   // contiguous vector that we are responsible for disposing.
-  Vector<unsigned> store = recorder.ExtractData();
+  Vector<unsigned> store = recorder->ExtractData();
   return new ScriptDataImpl(store);
 }
 
 
+// Preparse, but only collect data that is immediately useful,
+// even if the preparser data is only used once.
+ScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
+                                           unibrow::CharacterStream* stream,
+                                           v8::Extension* extension) {
+  bool allow_lazy = FLAG_lazy && (extension == NULL);
+  if (!allow_lazy) {
+    // Partial preparsing is only about lazily compiled functions.
+    // If we don't allow lazy compilation, the log data will be empty.
+    return NULL;
+  }
+  PartialParserRecorder recorder;
+
+  return DoPreParse(source, stream, allow_lazy, &recorder,
+                    JavaScriptScanner::kNoLiterals);
+}
+
+
 ScriptDataImpl* ParserApi::PreParse(Handle<String> source,
                                     unibrow::CharacterStream* stream,
                                     v8::Extension* extension) {
   Handle<Script> no_script;
-  preparser::PreParser<Scanner, CompleteParserRecorder> parser;
-  Scanner scanner;
-  scanner.Initialize(source, stream, JAVASCRIPT);
   bool allow_lazy = FLAG_lazy && (extension == NULL);
   CompleteParserRecorder recorder;
-  if (!parser.PreParseProgram(&scanner, &recorder, allow_lazy)) {
-    Top::StackOverflow();
-    return NULL;
-  }
-  // Extract the accumulated data from the recorder as a single
-  // contiguous vector that we are responsible for disposing.
-  Vector<unsigned> store = recorder.ExtractData();
-  return new ScriptDataImpl(store);
+  int kPreParseLiteralsFlags =
+      JavaScriptScanner::kLiteralString | JavaScriptScanner::kLiteralIdentifier;
+  return DoPreParse(source, stream, allow_lazy,
+                    &recorder, kPreParseLiteralsFlags);
 }
 
 
diff --git a/src/parser.h b/src/parser.h
index 667410b..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 = 4;
-
-  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,125 +161,6 @@
 };
 
 
-// Record only functions.
-class PartialParserRecorder {
- public:
-  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);
-  }
-
-  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);
-
-  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();
-
-  void LogSymbol(int start, Vector<const char> literal);
-
-  void LogSymbol(int start, const char* symbol, int length) {
-    LogSymbol(start, Vector<const char>(symbol, length));
-  }
-
-  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
@@ -682,7 +547,7 @@
   Expression* ParseV8Intrinsic(bool* ok);
 
   INLINE(Token::Value peek()) { return scanner_.peek(); }
-  INLINE(Token::Value Next()) { return scanner_.Next(); }
+  INLINE(Token::Value Next()) { return scanner_.NextCheckStack(); }
   INLINE(void Consume(Token::Value token));
   void Expect(Token::Value token, bool* ok);
   bool Check(Token::Value token);
@@ -760,7 +625,7 @@
   ZoneList<Handle<String> > symbol_cache_;
 
   Handle<Script> script_;
-  Scanner scanner_;
+  V8JavaScriptScanner scanner_;
 
   Scope* top_scope_;
   int with_nesting_level_;
@@ -852,7 +717,7 @@
   // Converts the currently parsed literal to a JavaScript String.
   Handle<String> GetString();
 
-  Scanner scanner_;
+  JsonScanner scanner_;
 };
 } }  // namespace v8::internal
 
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 caea16c..c50424e 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -865,8 +865,9 @@
 
   // For exectutable pages try and randomize the allocation address
   if (prot == PAGE_EXECUTE_READWRITE && msize >= Page::kPageSize) {
-      address = (V8::Random() << kPageSizeBits) | kAllocationRandomAddressMin;
-      address &= kAllocationRandomAddressMax;
+    address = (V8::RandomPrivate() << kPageSizeBits)
+      | kAllocationRandomAddressMin;
+    address &= kAllocationRandomAddressMax;
   }
 
   LPVOID mbase = VirtualAlloc(reinterpret_cast<void *>(address),
@@ -1902,7 +1903,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 44c55cf..b783d65 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -28,14 +28,12 @@
 #ifndef V8_PREPARSER_H
 #define V8_PREPARSER_H
 
-#include "unicode.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.
@@ -75,7 +73,6 @@
 typedef int Arguments;
 
 
-template <typename Scanner, typename PreParserLog>
 class PreParser {
  public:
   PreParser() : scope_(NULL), allow_lazy_(true) { }
@@ -85,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;
@@ -234,1181 +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 NULL;
-  }
-  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) {
-    Expect(i::Token::CATCH, CHECK_OK);
-    Expect(i::Token::LPAREN, CHECK_OK);
-    ParseIdentifier(CHECK_OK);
-    Expect(i::Token::RPAREN, CHECK_OK);
-    ParseBlock(CHECK_OK);
-    catch_or_finally_seen = true;
-  }
-  if (peek() == i::Token::FINALLY) {
-    Expect(i::Token::FINALLY, CHECK_OK);
-    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 = NULL;
-  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);
-  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, strlen(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-inl.h b/src/profile-generator-inl.h
index cdfa9e2..8b5c1e2 100644
--- a/src/profile-generator-inl.h
+++ b/src/profile-generator-inl.h
@@ -105,24 +105,6 @@
 }
 
 
-template<class Visitor>
-void HeapEntriesMap::UpdateEntries(Visitor* visitor) {
-  for (HashMap::Entry* p = entries_.Start();
-       p != NULL;
-       p = entries_.Next(p)) {
-    if (!IsAlias(p->value)) {
-      EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
-      entry_info->entry = visitor->GetEntry(
-          reinterpret_cast<HeapObject*>(p->key),
-          entry_info->children_count,
-          entry_info->retainers_count);
-      entry_info->children_count = 0;
-      entry_info->retainers_count = 0;
-    }
-  }
-}
-
-
 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
   switch (tag) {
     case GC:
@@ -139,6 +121,31 @@
   }
 }
 
+
+inline uint64_t HeapEntry::id() {
+  union {
+    Id stored_id;
+    uint64_t returned_id;
+  } id_adaptor = {id_};
+  return id_adaptor.returned_id;
+}
+
+
+template<class Visitor>
+void HeapEntriesMap::UpdateEntries(Visitor* visitor) {
+  for (HashMap::Entry* p = entries_.Start();
+       p != NULL;
+       p = entries_.Next(p)) {
+    EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
+    entry_info->entry = visitor->GetEntry(
+        reinterpret_cast<HeapObject*>(p->key),
+        entry_info->children_count,
+        entry_info->retainers_count);
+    entry_info->children_count = 0;
+    entry_info->retainers_count = 0;
+  }
+}
+
 } }  // namespace v8::internal
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 29f9ab4..640f13c 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -829,7 +829,10 @@
 
 void HeapGraphEdge::Init(
     int child_index, Type type, const char* name, HeapEntry* to) {
-  ASSERT(type == kContextVariable || type == kProperty || type == kInternal);
+  ASSERT(type == kContextVariable
+         || type == kProperty
+         || type == kInternal
+         || type == kShortcut);
   child_index_ = child_index;
   type_ = type;
   name_ = name;
@@ -837,14 +840,20 @@
 }
 
 
-void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) {
+void HeapGraphEdge::Init(int child_index, Type type, int index, HeapEntry* to) {
+  ASSERT(type == kElement || type == kHidden);
   child_index_ = child_index;
-  type_ = kElement;
+  type_ = type;
   index_ = index;
   to_ = to;
 }
 
 
+void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) {
+  Init(child_index, kElement, index, to);
+}
+
+
 HeapEntry* HeapGraphEdge::From() {
   return reinterpret_cast<HeapEntry*>(this - child_index_) - 1;
 }
@@ -860,12 +869,18 @@
   snapshot_ = snapshot;
   type_ = type;
   painted_ = kUnpainted;
-  calculated_data_index_ = kNoCalculatedData;
   name_ = name;
-  id_ = id;
   self_size_ = self_size;
+  retained_size_ = 0;
   children_count_ = children_count;
   retainers_count_ = retainers_count;
+  dominator_ = NULL;
+
+  union {
+    uint64_t set_id;
+    Id stored_id;
+  } id_adaptor = {id};
+  id_ = id_adaptor.stored_id;
 }
 
 
@@ -879,9 +894,12 @@
 }
 
 
-void HeapEntry::SetElementReference(
-    int child_index, int index, HeapEntry* entry, int retainer_index) {
-  children_arr()[child_index].Init(child_index, index, entry);
+void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type,
+                                    int child_index,
+                                    int index,
+                                    HeapEntry* entry,
+                                    int retainer_index) {
+  children_arr()[child_index].Init(child_index, type, index, entry);
   entry->retainers_arr()[retainer_index] = children_arr() + child_index;
 }
 
@@ -892,30 +910,16 @@
 }
 
 
-int HeapEntry::ReachableSize() {
-  if (calculated_data_index_ == kNoCalculatedData) {
-    calculated_data_index_ = snapshot_->AddCalculatedData();
+int HeapEntry::RetainedSize(bool exact) {
+  if (exact && (retained_size_ & kExactRetainedSizeTag) == 0) {
+    CalculateExactRetainedSize();
   }
-  return snapshot_->GetCalculatedData(
-      calculated_data_index_).ReachableSize(this);
-}
-
-
-int HeapEntry::RetainedSize() {
-  if (calculated_data_index_ == kNoCalculatedData) {
-    calculated_data_index_ = snapshot_->AddCalculatedData();
-  }
-  return snapshot_->GetCalculatedData(
-      calculated_data_index_).RetainedSize(this);
+  return retained_size_ & (~kExactRetainedSizeTag);
 }
 
 
 List<HeapGraphPath*>* HeapEntry::GetRetainingPaths() {
-  if (calculated_data_index_ == kNoCalculatedData) {
-    calculated_data_index_ = snapshot_->AddCalculatedData();
-  }
-  return snapshot_->GetCalculatedData(
-      calculated_data_index_).GetRetainingPaths(this);
+  return snapshot_->GetRetainingPaths(this);
 }
 
 
@@ -929,6 +933,7 @@
     HeapEntry* entry = list.RemoveLast();
     Vector<HeapGraphEdge> children = entry->children();
     for (int i = 0; i < children.length(); ++i) {
+      if (children[i].type() == HeapGraphEdge::kShortcut) continue;
       HeapEntry* child = children[i].to();
       if (!child->painted_reachable()) {
         list.Add(child);
@@ -952,8 +957,7 @@
 
 
 void HeapEntry::Print(int max_depth, int indent) {
-  OS::Print("%6d %6d %6d [%llu] ",
-            self_size(), ReachableSize(), RetainedSize(), id_);
+  OS::Print("%6d %6d [%llu] ", self_size(), RetainedSize(false), id());
   if (type() != kString) {
     OS::Print("%s %.40s\n", TypeAsString(), name_);
   } else {
@@ -985,6 +989,12 @@
       case HeapGraphEdge::kProperty:
         OS::Print("  %*c %s: ", indent, ' ', edge.name());
         break;
+      case HeapGraphEdge::kHidden:
+        OS::Print("  %*c $%d: ", indent, ' ', edge.index());
+        break;
+      case HeapGraphEdge::kShortcut:
+        OS::Print("  %*c ^%s: ", indent, ' ', edge.name());
+        break;
       default:
         OS::Print("!!! unknown edge type: %d ", edge.type());
     }
@@ -995,7 +1005,7 @@
 
 const char* HeapEntry::TypeAsString() {
   switch (type()) {
-    case kInternal: return "/internal/";
+    case kHidden: return "/hidden/";
     case kObject: return "/object/";
     case kClosure: return "/closure/";
     case kString: return "/string/";
@@ -1017,44 +1027,6 @@
 }
 
 
-static void DeleteHeapGraphPath(HeapGraphPath** path_ptr) {
-  delete *path_ptr;
-}
-
-void HeapEntryCalculatedData::Dispose() {
-  if (retaining_paths_ != NULL) retaining_paths_->Iterate(DeleteHeapGraphPath);
-  delete retaining_paths_;
-}
-
-
-int HeapEntryCalculatedData::ReachableSize(HeapEntry* entry) {
-  if (reachable_size_ == kUnknownSize) CalculateSizes(entry);
-  return reachable_size_;
-}
-
-
-int HeapEntryCalculatedData::RetainedSize(HeapEntry* entry) {
-  if (retained_size_ == kUnknownSize) CalculateSizes(entry);
-  return retained_size_;
-}
-
-
-class ReachableSizeCalculator {
- public:
-  ReachableSizeCalculator()
-      : reachable_size_(0) {
-  }
-
-  int reachable_size() const { return reachable_size_; }
-
-  void Apply(HeapEntry* entry) {
-    reachable_size_ += entry->self_size();
-  }
-
- private:
-  int reachable_size_;
-};
-
 class RetainedSizeCalculator {
  public:
   RetainedSizeCalculator()
@@ -1073,20 +1045,17 @@
   int retained_size_;
 };
 
-void HeapEntryCalculatedData::CalculateSizes(HeapEntry* entry) {
+void HeapEntry::CalculateExactRetainedSize() {
   // To calculate retained size, first we paint all reachable nodes in
-  // one color (and calculate reachable size as a byproduct), then we
-  // paint (or re-paint) all nodes reachable from other nodes with a
-  // different color. Then we consider only nodes painted with the
-  // first color for calculating the retained size.
-  entry->snapshot()->ClearPaint();
-  ReachableSizeCalculator rch_size_calc;
-  entry->ApplyAndPaintAllReachable(&rch_size_calc);
-  reachable_size_ = rch_size_calc.reachable_size();
+  // one color, then we paint (or re-paint) all nodes reachable from
+  // other nodes with a different color. Then we sum up self sizes of
+  // nodes painted with the first color.
+  snapshot()->ClearPaint();
+  PaintAllReachable();
 
   List<HeapEntry*> list(10);
-  HeapEntry* root = entry->snapshot()->root();
-  if (entry != root) {
+  HeapEntry* root = snapshot()->root();
+  if (this != root) {
     list.Add(root);
     root->paint_reachable_from_others();
   }
@@ -1094,8 +1063,9 @@
     HeapEntry* curr = list.RemoveLast();
     Vector<HeapGraphEdge> children = curr->children();
     for (int i = 0; i < children.length(); ++i) {
+      if (children[i].type() == HeapGraphEdge::kShortcut) continue;
       HeapEntry* child = children[i].to();
-      if (child != entry && child->not_painted_reachable_from_others()) {
+      if (child != this && child->not_painted_reachable_from_others()) {
         list.Add(child);
         child->paint_reachable_from_others();
       }
@@ -1103,8 +1073,10 @@
   }
 
   RetainedSizeCalculator ret_size_calc;
-  entry->snapshot()->IterateEntries(&ret_size_calc);
+  snapshot()->IterateEntries(&ret_size_calc);
   retained_size_ = ret_size_calc.reained_size();
+  ASSERT((retained_size_ & kExactRetainedSizeTag) == 0);
+  retained_size_ |= kExactRetainedSizeTag;
 }
 
 
@@ -1142,32 +1114,28 @@
 };
 
 
-List<HeapGraphPath*>* HeapEntryCalculatedData::GetRetainingPaths(
-    HeapEntry* entry) {
-  if (retaining_paths_ == NULL) retaining_paths_ = new List<HeapGraphPath*>(4);
-  if (retaining_paths_->length() == 0 && entry->retainers().length() != 0) {
-    CachedHeapGraphPath path;
-    FindRetainingPaths(entry, &path);
-  }
-  return retaining_paths_;
+List<HeapGraphPath*>* HeapEntry::CalculateRetainingPaths() {
+  List<HeapGraphPath*>* retaining_paths = new List<HeapGraphPath*>(4);
+  CachedHeapGraphPath path;
+  FindRetainingPaths(&path, retaining_paths);
+  return retaining_paths;
 }
 
 
-void HeapEntryCalculatedData::FindRetainingPaths(
-    HeapEntry* entry,
-    CachedHeapGraphPath* prev_path) {
-  Vector<HeapGraphEdge*> retainers = entry->retainers();
-  for (int i = 0; i < retainers.length(); ++i) {
-    HeapGraphEdge* ret_edge = retainers[i];
+void HeapEntry::FindRetainingPaths(CachedHeapGraphPath* prev_path,
+                                   List<HeapGraphPath*>* retaining_paths) {
+  Vector<HeapGraphEdge*> rets = retainers();
+  for (int i = 0; i < rets.length(); ++i) {
+    HeapGraphEdge* ret_edge = rets[i];
     if (prev_path->ContainsNode(ret_edge->From())) continue;
-    if (ret_edge->From() != entry->snapshot()->root()) {
+    if (ret_edge->From() != snapshot()->root()) {
       CachedHeapGraphPath path(*prev_path);
       path.Add(ret_edge);
-      FindRetainingPaths(ret_edge->From(), &path);
+      ret_edge->From()->FindRetainingPaths(&path, retaining_paths);
     } else {
       HeapGraphPath* ret_path = new HeapGraphPath(*prev_path->path());
       ret_path->Set(0, ret_edge);
-      retaining_paths_->Add(ret_path);
+      retaining_paths->Add(ret_path);
     }
   }
 }
@@ -1192,6 +1160,7 @@
         OS::Print("[#%s] ", edge->name());
         break;
       case HeapGraphEdge::kElement:
+      case HeapGraphEdge::kHidden:
         OS::Print("[%d] ", edge->index());
         break;
       case HeapGraphEdge::kInternal:
@@ -1200,6 +1169,9 @@
       case HeapGraphEdge::kProperty:
         OS::Print("[%s] ", edge->name());
         break;
+      case HeapGraphEdge::kShortcut:
+        OS::Print("[^%s] ", edge->name());
+        break;
       default:
         OS::Print("!!! unknown edge type: %d ", edge->type());
     }
@@ -1211,6 +1183,8 @@
 
 HeapObject *const HeapSnapshot::kInternalRootObject =
     reinterpret_cast<HeapObject*>(1);
+HeapObject *const HeapSnapshot::kGcRootsObject =
+    reinterpret_cast<HeapObject*>(2);
 
 
 // It is very important to keep objects that form a heap snapshot
@@ -1221,12 +1195,12 @@
 
 template <> struct SnapshotSizeConstants<4> {
   static const int kExpectedHeapGraphEdgeSize = 12;
-  static const int kExpectedHeapEntrySize = 32;
+  static const int kExpectedHeapEntrySize = 36;
 };
 
 template <> struct SnapshotSizeConstants<8> {
   static const int kExpectedHeapGraphEdgeSize = 24;
-  static const int kExpectedHeapEntrySize = 40;
+  static const int kExpectedHeapEntrySize = 48;
 };
 
 }  // namespace
@@ -1240,8 +1214,10 @@
       title_(title),
       uid_(uid),
       root_entry_(NULL),
+      gc_roots_entry_(NULL),
       raw_entries_(NULL),
-      entries_sorted_(false) {
+      entries_sorted_(false),
+      retaining_paths_(HeapEntry::Match) {
   STATIC_ASSERT(
       sizeof(HeapGraphEdge) ==
       SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize);  // NOLINT
@@ -1251,13 +1227,20 @@
 }
 
 
-static void DisposeCalculatedData(HeapEntryCalculatedData* cdata) {
-  cdata->Dispose();
+static void DeleteHeapGraphPath(HeapGraphPath** path_ptr) {
+  delete *path_ptr;
 }
 
 HeapSnapshot::~HeapSnapshot() {
   DeleteArray(raw_entries_);
-  calculated_data_.Iterate(DisposeCalculatedData);
+  for (HashMap::Entry* p = retaining_paths_.Start();
+       p != NULL;
+       p = retaining_paths_.Next(p)) {
+    List<HeapGraphPath*>* list =
+        reinterpret_cast<List<HeapGraphPath*>*>(p->value);
+    list->Iterate(DeleteHeapGraphPath);
+    delete list;
+  }
 }
 
 
@@ -1280,9 +1263,20 @@
   if (object == kInternalRootObject) {
     ASSERT(root_entry_ == NULL);
     ASSERT(retainers_count == 0);
-    root_entry_ = AddEntry(
-        HeapEntry::kInternal, "", 0, 0, children_count, retainers_count);
-    return root_entry_;
+    return (root_entry_ = AddEntry(HeapEntry::kObject,
+                                   "",
+                                   HeapObjectsMap::kInternalRootObjectId,
+                                   0,
+                                   children_count,
+                                   retainers_count));
+  } else if (object == kGcRootsObject) {
+    ASSERT(gc_roots_entry_ == NULL);
+    return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
+                                       "(GC roots)",
+                                       HeapObjectsMap::kGcRootsObjectId,
+                                       0,
+                                       children_count,
+                                       retainers_count));
   } else if (object->IsJSFunction()) {
     JSFunction* func = JSFunction::cast(object);
     SharedFunctionInfo* shared = func->shared();
@@ -1301,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()) {
@@ -1345,22 +1339,11 @@
                     children_count,
                     retainers_count);
   }
-  // No interest in this object.
-  return NULL;
-}
-
-
-bool HeapSnapshot::WillAddEntry(HeapObject* object) {
-  return object == kInternalRootObject
-      || object->IsJSFunction()
-      || object->IsJSRegExp()
-      || object->IsJSObject()
-      || object->IsString()
-      || object->IsCode()
-      || object->IsSharedFunctionInfo()
-      || object->IsScript()
-      || object->IsFixedArray()
-      || object->IsHeapNumber();
+  return AddEntry(object,
+                  HeapEntry::kHidden,
+                  "system",
+                  children_count,
+                  retainers_count);
 }
 
 
@@ -1373,12 +1356,6 @@
 }
 
 
-int HeapSnapshot::AddCalculatedData() {
-  calculated_data_.Add(HeapEntryCalculatedData());
-  return calculated_data_.length() - 1;
-}
-
-
 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
                                   HeapEntry::Type type,
                                   const char* name,
@@ -1387,7 +1364,7 @@
   return AddEntry(type,
                   name,
                   collection_->GetObjectId(object->address()),
-                  GetObjectSize(object),
+                  object->Size(),
                   children_count,
                   retainers_count);
 }
@@ -1405,6 +1382,149 @@
 }
 
 
+void HeapSnapshot::FillReversePostorderIndexes(Vector<HeapEntry*>* entries) {
+  ClearPaint();
+  int current_entry = 0;
+  List<HeapEntry*> nodes_to_visit;
+  nodes_to_visit.Add(root());
+  root()->paint_reachable();
+  while (!nodes_to_visit.is_empty()) {
+    HeapEntry* entry = nodes_to_visit.last();
+    Vector<HeapGraphEdge> children = entry->children();
+    bool has_new_edges = false;
+    for (int i = 0; i < children.length(); ++i) {
+      if (children[i].type() == HeapGraphEdge::kShortcut) continue;
+      HeapEntry* child = children[i].to();
+      if (!child->painted_reachable()) {
+        nodes_to_visit.Add(child);
+        child->paint_reachable();
+        has_new_edges = true;
+      }
+    }
+    if (!has_new_edges) {
+      entry->set_ordered_index(current_entry);
+      entries->at(current_entry++) = entry;
+      nodes_to_visit.RemoveLast();
+    }
+  }
+  entries->Truncate(current_entry);
+}
+
+
+static int Intersect(int i1, int i2, const Vector<HeapEntry*>& dominators) {
+  int finger1 = i1, finger2 = i2;
+  while (finger1 != finger2) {
+    while (finger1 < finger2) finger1 = dominators[finger1]->ordered_index();
+    while (finger2 < finger1) finger2 = dominators[finger2]->ordered_index();
+  }
+  return finger1;
+}
+
+// The algorithm is based on the article:
+// K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm"
+// Softw. Pract. Exper. 4 (2001), pp. 1–10.
+void HeapSnapshot::BuildDominatorTree(const Vector<HeapEntry*>& entries,
+                                      Vector<HeapEntry*>* dominators) {
+  if (entries.length() == 0) return;
+  const int root_index = entries.length() - 1;
+  for (int i = 0; i < root_index; ++i) dominators->at(i) = NULL;
+  dominators->at(root_index) = entries[root_index];
+  bool changed = true;
+  while (changed) {
+    changed = false;
+    for (int i = root_index - 1; i >= 0; --i) {
+      HeapEntry* new_idom = NULL;
+      Vector<HeapGraphEdge*> rets = entries[i]->retainers();
+      int j = 0;
+      for (; j < rets.length(); ++j) {
+        if (rets[j]->type() == HeapGraphEdge::kShortcut) continue;
+        HeapEntry* ret = rets[j]->From();
+        if (dominators->at(ret->ordered_index()) != NULL) {
+          new_idom = ret;
+          break;
+        }
+      }
+      for (++j; j < rets.length(); ++j) {
+        if (rets[j]->type() == HeapGraphEdge::kShortcut) continue;
+        HeapEntry* ret = rets[j]->From();
+        if (dominators->at(ret->ordered_index()) != NULL) {
+          new_idom = entries[Intersect(ret->ordered_index(),
+                                       new_idom->ordered_index(),
+                                       *dominators)];
+        }
+      }
+      if (new_idom != NULL && dominators->at(i) != new_idom) {
+        dominators->at(i) = new_idom;
+        changed = true;
+      }
+    }
+  }
+}
+
+
+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());
+  FillReversePostorderIndexes(&ordered_entries);
+  ScopedVector<HeapEntry*> dominators(ordered_entries.length());
+  BuildDominatorTree(ordered_entries, &dominators);
+  for (int i = 0; i < ordered_entries.length(); ++i) {
+    ASSERT(dominators[i] != NULL);
+    ordered_entries[i]->set_dominator(dominators[i]);
+  }
+  // For nodes unreachable from root, set dominator to itself.
+  SetDominatorsToSelf();
+}
+
+
+void HeapSnapshot::ApproximateRetainedSizes() {
+  SetEntriesDominators();
+  // As for the dominators tree we only know parent nodes, not
+  // children, to sum up total sizes we traverse the tree level by
+  // level upwards, starting from leaves.
+  for (int i = 0; i < entries_.length(); ++i) {
+    HeapEntry* entry = entries_[i];
+    entry->set_retained_size(entry->self_size());
+    entry->set_leaf();
+  }
+  while (true) {
+    bool onlyLeaves = true;
+    for (int i = 0; i < entries_.length(); ++i) {
+      HeapEntry *entry = entries_[i], *dominator = entry->dominator();
+      if (!entry->is_processed() && dominator != entry) {
+        dominator->set_non_leaf();
+        onlyLeaves = false;
+      }
+    }
+    if (onlyLeaves) break;
+
+    for (int i = 0; i < entries_.length(); ++i) {
+      HeapEntry *entry = entries_[i], *dominator = entry->dominator();
+      if (entry->is_leaf() && dominator != entry) {
+        dominator->add_retained_size(entry->retained_size());
+      }
+    }
+
+    // Mark all current leaves as processed, reset non-leaves back to leaves.
+    for (int i = 0; i < entries_.length(); ++i) {
+      HeapEntry* entry = entries_[i];
+      if (entry->is_leaf())
+        entry->set_processed();
+      else if (entry->is_non_leaf())
+        entry->set_leaf();
+    }
+  }
+}
+
+
 HeapEntry* HeapSnapshot::GetNextEntryToInit() {
   if (entries_.length() > 0) {
     HeapEntry* last_entry = entries_.last();
@@ -1419,41 +1539,21 @@
 }
 
 
-int HeapSnapshot::GetObjectSize(HeapObject* obj) {
-  return obj->IsJSObject() ?
-      CalculateNetworkSize(JSObject::cast(obj)) : obj->Size();
-}
-
-
-int HeapSnapshot::CalculateNetworkSize(JSObject* obj) {
-  int size = obj->Size();
-  // If 'properties' and 'elements' are non-empty (thus, non-shared),
-  // take their size into account.
-  if (obj->properties() != Heap::empty_fixed_array()) {
-    size += obj->properties()->Size();
-  }
-  if (obj->elements() != Heap::empty_fixed_array()) {
-    size += obj->elements()->Size();
-  }
-  // For functions, also account non-empty context and literals sizes.
-  if (obj->IsJSFunction()) {
-    JSFunction* f = JSFunction::cast(obj);
-    if (f->unchecked_context()->IsContext()) {
-      size += f->context()->Size();
-    }
-    if (f->literals()->length() != 0) {
-      size += f->literals()->Size();
-    }
-  }
-  return size;
-}
-
-
 HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) {
   return collection_->CompareSnapshots(this, snapshot);
 }
 
 
+List<HeapGraphPath*>* HeapSnapshot::GetRetainingPaths(HeapEntry* entry) {
+  HashMap::Entry* p =
+      retaining_paths_.Lookup(entry, HeapEntry::Hash(entry), true);
+  if (p->value == NULL) {
+    p->value = entry->CalculateRetainingPaths();
+  }
+  return reinterpret_cast<List<HeapGraphPath*>*>(p->value);
+}
+
+
 template<class T>
 static int SortByIds(const T* entry1_ptr,
                      const T* entry2_ptr) {
@@ -1475,9 +1575,14 @@
 }
 
 
+const uint64_t HeapObjectsMap::kInternalRootObjectId = 0;
+const uint64_t HeapObjectsMap::kGcRootsObjectId = 1;
+// Increase kFirstAvailableObjectId if new 'special' objects appear.
+const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 2;
+
 HeapObjectsMap::HeapObjectsMap()
     : initial_fill_mode_(true),
-      next_id_(1),
+      next_id_(kFirstAvailableObjectId),
       entries_map_(AddressesMatch),
       entries_(new List<EntryInfo>()) { }
 
@@ -1628,17 +1733,7 @@
 
 HeapEntriesMap::~HeapEntriesMap() {
   for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) {
-    if (!IsAlias(p->value)) delete reinterpret_cast<EntryInfo*>(p->value);
-  }
-}
-
-
-void HeapEntriesMap::Alias(HeapObject* from, HeapObject* to) {
-  HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), true);
-  HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false);
-  if (from_cache_entry->value == NULL) {
-    ASSERT(to_cache_entry != NULL);
-    from_cache_entry->value = MakeAlias(to_cache_entry->value);
+    delete reinterpret_cast<EntryInfo*>(p->value);
   }
 }
 
@@ -1646,8 +1741,7 @@
 HeapEntry* HeapEntriesMap::Map(HeapObject* object) {
   HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false);
   if (cache_entry != NULL) {
-    EntryInfo* entry_info =
-        reinterpret_cast<EntryInfo*>(Unalias(cache_entry->value));
+    EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
     return entry_info->entry;
   } else {
     return NULL;
@@ -1671,9 +1765,9 @@
   ASSERT(from_cache_entry != NULL);
   ASSERT(to_cache_entry != NULL);
   EntryInfo* from_entry_info =
-      reinterpret_cast<EntryInfo*>(Unalias(from_cache_entry->value));
+      reinterpret_cast<EntryInfo*>(from_cache_entry->value);
   EntryInfo* to_entry_info =
-      reinterpret_cast<EntryInfo*>(Unalias(to_cache_entry->value));
+      reinterpret_cast<EntryInfo*>(to_cache_entry->value);
   if (prev_children_count)
     *prev_children_count = from_entry_info->children_count;
   if (prev_retainers_count)
@@ -1685,6 +1779,36 @@
 }
 
 
+HeapObjectsSet::HeapObjectsSet()
+    : entries_(HeapEntriesMap::HeapObjectsMatch) {
+}
+
+
+void HeapObjectsSet::Clear() {
+  entries_.Clear();
+}
+
+
+bool HeapObjectsSet::Contains(Object* obj) {
+  if (!obj->IsHeapObject()) return false;
+  HeapObject* object = HeapObject::cast(obj);
+  HashMap::Entry* cache_entry =
+      entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
+  return cache_entry != NULL;
+}
+
+
+void HeapObjectsSet::Insert(Object* obj) {
+  if (!obj->IsHeapObject()) return;
+  HeapObject* object = HeapObject::cast(obj);
+  HashMap::Entry* cache_entry =
+      entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
+  if (cache_entry->value == NULL) {
+    cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder;
+  }
+}
+
+
 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot)
     : snapshot_(snapshot),
       collection_(snapshot->collection()),
@@ -1699,7 +1823,8 @@
     entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder);
     return HeapEntriesMap::kHeapEntryPlaceholder;
   }
-  void SetElementReference(HeapObject* parent_obj,
+  void SetIndexedReference(HeapGraphEdge::Type,
+                           HeapObject* parent_obj,
                            HeapEntry*,
                            int,
                            Object* child_obj,
@@ -1714,10 +1839,18 @@
                          HeapEntry*) {
     entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
   }
-  void SetRootReference(Object* child_obj, HeapEntry*) {
+  void SetRootShortcutReference(Object* child_obj, HeapEntry*) {
     entries_->CountReference(
         HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj));
   }
+  void SetRootGcRootsReference() {
+    entries_->CountReference(
+        HeapSnapshot::kInternalRootObject, HeapSnapshot::kGcRootsObject);
+  }
+  void SetStrongRootReference(Object* child_obj, HeapEntry*) {
+    entries_->CountReference(
+        HeapSnapshot::kGcRootsObject, HeapObject::cast(child_obj));
+  }
  private:
   HeapEntriesMap* entries_;
 };
@@ -1733,16 +1866,19 @@
     UNREACHABLE();
     return NULL;
   }
-  void SetElementReference(HeapObject* parent_obj,
+  void SetIndexedReference(HeapGraphEdge::Type type,
+                           HeapObject* parent_obj,
                            HeapEntry* parent_entry,
                            int index,
                            Object* child_obj,
                            HeapEntry* child_entry) {
     int child_index, retainer_index;
-    entries_->CountReference(parent_obj, HeapObject::cast(child_obj),
-                             &child_index, &retainer_index);
-    parent_entry->SetElementReference(
-        child_index, index, child_entry, retainer_index);
+    entries_->CountReference(parent_obj,
+                             HeapObject::cast(child_obj),
+                             &child_index,
+                             &retainer_index);
+    parent_entry->SetIndexedReference(
+        type, child_index, index, child_entry, retainer_index);
   }
   void SetNamedReference(HeapGraphEdge::Type type,
                          HeapObject* parent_obj,
@@ -1759,13 +1895,43 @@
                               child_entry,
                               retainer_index);
   }
-  void SetRootReference(Object* child_obj, HeapEntry* child_entry) {
+  void SetRootGcRootsReference() {
     int child_index, retainer_index;
-    entries_->CountReference(
-        HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj),
-        &child_index, &retainer_index);
-    snapshot_->root()->SetElementReference(
-        child_index, child_index + 1, child_entry, retainer_index);
+    entries_->CountReference(HeapSnapshot::kInternalRootObject,
+                             HeapSnapshot::kGcRootsObject,
+                             &child_index,
+                             &retainer_index);
+    snapshot_->root()->SetIndexedReference(HeapGraphEdge::kElement,
+                                           child_index,
+                                           child_index + 1,
+                                           snapshot_->gc_roots(),
+                                           retainer_index);
+  }
+  void SetRootShortcutReference(Object* child_obj,
+                                HeapEntry* child_entry) {
+    int child_index, retainer_index;
+    entries_->CountReference(HeapSnapshot::kInternalRootObject,
+                             HeapObject::cast(child_obj),
+                             &child_index,
+                             &retainer_index);
+    snapshot_->root()->SetNamedReference(HeapGraphEdge::kShortcut,
+                                         child_index,
+                                         collection_->GetName(child_index + 1),
+                                         child_entry,
+                                         retainer_index);
+  }
+  void SetStrongRootReference(Object* child_obj,
+                              HeapEntry* child_entry) {
+    int child_index, retainer_index;
+    entries_->CountReference(HeapSnapshot::kGcRootsObject,
+                             HeapObject::cast(child_obj),
+                             &child_index,
+                             &retainer_index);
+    snapshot_->gc_roots()->SetIndexedReference(HeapGraphEdge::kElement,
+                                               child_index,
+                                               child_index + 1,
+                                               child_entry,
+                                               retainer_index);
   }
  private:
   HeapSnapshot* snapshot_;
@@ -1788,6 +1954,19 @@
   HeapSnapshot* snapshot_;
 };
 
+class RootsReferencesExtractor : public ObjectVisitor {
+ public:
+  explicit RootsReferencesExtractor(HeapSnapshotGenerator* generator)
+      : generator_(generator) {
+  }
+  void VisitPointers(Object** start, Object** end) {
+    for (Object** p = start; p < end; p++) generator_->SetGcRootsReference(*p);
+  }
+ private:
+  HeapSnapshotGenerator* generator_;
+};
+
+
 void HeapSnapshotGenerator::GenerateSnapshot() {
   AssertNoAllocation no_alloc;
 
@@ -1795,12 +1974,14 @@
   SnapshotCounter counter(&entries_);
   filler_ = &counter;
   filler_->AddEntry(HeapSnapshot::kInternalRootObject);
-  HeapIterator iterator1;
-  for (HeapObject* obj = iterator1.next();
-       obj != NULL;
-       obj = iterator1.next()) {
+  filler_->AddEntry(HeapSnapshot::kGcRootsObject);
+  HeapIterator iterator(HeapIterator::kPreciseFiltering);
+  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
     ExtractReferences(obj);
   }
+  SetRootGcRootsReference();
+  RootsReferencesExtractor extractor(this);
+  Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG);
 
   // Allocate and fill entries in the snapshot, allocate references.
   snapshot_->AllocateEntries(entries_.entries_count(),
@@ -1812,12 +1993,14 @@
   // Pass 2. Fill references.
   SnapshotFiller filler(snapshot_, &entries_);
   filler_ = &filler;
-  HeapIterator iterator2;
-  for (HeapObject* obj = iterator2.next();
-       obj != NULL;
-       obj = iterator2.next()) {
+  iterator.reset();
+  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
     ExtractReferences(obj);
   }
+  SetRootGcRootsReference();
+  Heap::IterateRoots(&extractor, VISIT_ONLY_STRONG);
+
+  snapshot_->ApproximateRetainedSizes();
 }
 
 
@@ -1825,25 +2008,8 @@
   if (!obj->IsHeapObject()) return NULL;
   HeapObject* object = HeapObject::cast(obj);
   HeapEntry* entry = entries_.Map(object);
-
   // A new entry.
-  if (entry == NULL) {
-    if (obj->IsJSGlobalPropertyCell()) {
-      Object* cell_target = JSGlobalPropertyCell::cast(obj)->value();
-      entry = GetEntry(cell_target);
-      // If GPC references an object that we have interest in (see
-      // HeapSnapshot::AddEntry, WillAddEntry), add the object.  We
-      // don't store HeapEntries for GPCs. Instead, we make our hash
-      // map to point to object's HeapEntry by GPCs address.
-      if (entry != NULL) {
-        entries_.Alias(object, HeapObject::cast(cell_target));
-      }
-      return entry;
-    }
-
-    if (snapshot_->WillAddEntry(object)) entry = filler_->AddEntry(object);
-  }
-
+  if (entry == NULL) entry = filler_->AddEntry(object);
   return entry;
 }
 
@@ -1852,43 +2018,44 @@
  public:
   IndexedReferencesExtractor(HeapSnapshotGenerator* generator,
                              HeapObject* parent_obj,
-                             HeapEntry* parent_entry)
+                             HeapEntry* parent_entry,
+                             HeapObjectsSet* known_references = NULL)
       : generator_(generator),
         parent_obj_(parent_obj),
         parent_(parent_entry),
+        known_references_(known_references),
         next_index_(1) {
   }
-
-  void VisitPointer(Object** o) {
-    generator_->SetElementReference(parent_obj_, parent_, next_index_++, *o);
-  }
-
   void VisitPointers(Object** start, Object** end) {
-    for (Object** p = start; p < end; p++) VisitPointer(p);
+    for (Object** p = start; p < end; p++) {
+      if (!known_references_ || !known_references_->Contains(*p)) {
+        generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p);
+      }
+    }
   }
-
  private:
   HeapSnapshotGenerator* generator_;
   HeapObject* parent_obj_;
   HeapEntry* parent_;
+  HeapObjectsSet* known_references_;
   int next_index_;
 };
 
 
 void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
-  // We need to reference JS global objects from snapshot's root.
-  // We use JSGlobalProxy because this is what embedder (e.g. browser)
-  // uses for the global object.
-  if (obj->IsJSGlobalProxy()) {
-    JSGlobalProxy* proxy = JSGlobalProxy::cast(obj);
-    SetRootReference(proxy->map()->prototype());
-    return;
-  }
-
   HeapEntry* entry = GetEntry(obj);
   if (entry == NULL) return;  // No interest in this object.
 
-  if (obj->IsJSObject()) {
+  known_references_.Clear();
+  if (obj->IsJSGlobalProxy()) {
+    // We need to reference JS global objects from snapshot's root.
+    // We use JSGlobalProxy because this is what embedder (e.g. browser)
+    // uses for the global object.
+    JSGlobalProxy* proxy = JSGlobalProxy::cast(obj);
+    SetRootShortcutReference(proxy->map()->prototype());
+    IndexedReferencesExtractor refs_extractor(this, obj, entry);
+    obj->Iterate(&refs_extractor);
+  } else if (obj->IsJSObject()) {
     JSObject* js_obj = JSObject::cast(obj);
     ExtractClosureReferences(js_obj, entry);
     ExtractPropertyReferences(js_obj, entry);
@@ -1903,16 +2070,16 @@
             obj, entry, Heap::prototype_symbol(), js_fun->prototype());
       }
     }
+    IndexedReferencesExtractor refs_extractor(
+        this, obj, entry, &known_references_);
+    obj->Iterate(&refs_extractor);
   } else if (obj->IsString()) {
     if (obj->IsConsString()) {
       ConsString* cs = ConsString::cast(obj);
-      SetInternalReference(obj, entry, "1", cs->first());
-      SetInternalReference(obj, entry, "2", cs->second());
+      SetInternalReference(obj, entry, 1, cs->first());
+      SetInternalReference(obj, entry, 2, cs->second());
     }
-  } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
-    IndexedReferencesExtractor refs_extractor(this, obj, entry);
-    obj->Iterate(&refs_extractor);
-  } else if (obj->IsFixedArray()) {
+  } else {
     IndexedReferencesExtractor refs_extractor(this, obj, entry);
     obj->Iterate(&refs_extractor);
   }
@@ -1967,8 +2134,17 @@
     for (int i = 0; i < length; ++i) {
       Object* k = dictionary->KeyAt(i);
       if (dictionary->IsKey(k)) {
+        Object* target = dictionary->ValueAt(i);
         SetPropertyReference(
-            js_obj, entry, String::cast(k), dictionary->ValueAt(i));
+            js_obj, entry, String::cast(k), target);
+        // We assume that global objects can only have slow properties.
+        if (target->IsJSGlobalPropertyCell()) {
+          SetPropertyShortcutReference(js_obj,
+                                       entry,
+                                       String::cast(k),
+                                       JSGlobalPropertyCell::cast(
+                                           target)->value());
+        }
       }
     }
   }
@@ -2024,6 +2200,7 @@
                                collection_->GetName(reference_name),
                                child_obj,
                                child_entry);
+    known_references_.Insert(child_obj);
   }
 }
 
@@ -2034,8 +2211,13 @@
                                                 Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
-    filler_->SetElementReference(
-        parent_obj, parent_entry, index, child_obj, child_entry);
+    filler_->SetIndexedReference(HeapGraphEdge::kElement,
+                                 parent_obj,
+                                 parent_entry,
+                                 index,
+                                 child_obj,
+                                 child_entry);
+    known_references_.Insert(child_obj);
   }
 }
 
@@ -2052,6 +2234,7 @@
                                reference_name,
                                child_obj,
                                child_entry);
+    known_references_.Insert(child_obj);
   }
 }
 
@@ -2068,6 +2251,23 @@
                                collection_->GetName(index),
                                child_obj,
                                child_entry);
+    known_references_.Insert(child_obj);
+  }
+}
+
+
+void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj,
+                                               HeapEntry* parent_entry,
+                                               int index,
+                                               Object* child_obj) {
+  HeapEntry* child_entry = GetEntry(child_obj);
+  if (child_entry != NULL) {
+    filler_->SetIndexedReference(HeapGraphEdge::kHidden,
+                                 parent_obj,
+                                 parent_entry,
+                                 index,
+                                 child_obj,
+                                 child_entry);
   }
 }
 
@@ -2086,14 +2286,45 @@
                                collection_->GetName(reference_name),
                                child_obj,
                                child_entry);
+    known_references_.Insert(child_obj);
   }
 }
 
 
-void HeapSnapshotGenerator::SetRootReference(Object* child_obj) {
+void HeapSnapshotGenerator::SetPropertyShortcutReference(
+    HeapObject* parent_obj,
+    HeapEntry* parent_entry,
+    String* reference_name,
+    Object* child_obj) {
+  HeapEntry* child_entry = GetEntry(child_obj);
+  if (child_entry != NULL) {
+    filler_->SetNamedReference(HeapGraphEdge::kShortcut,
+                               parent_obj,
+                               parent_entry,
+                               collection_->GetName(reference_name),
+                               child_obj,
+                               child_entry);
+  }
+}
+
+
+void HeapSnapshotGenerator::SetRootGcRootsReference() {
+  filler_->SetRootGcRootsReference();
+}
+
+
+void HeapSnapshotGenerator::SetRootShortcutReference(Object* child_obj) {
   HeapEntry* child_entry = GetEntry(child_obj);
   ASSERT(child_entry != NULL);
-  filler_->SetRootReference(child_obj, child_entry);
+  filler_->SetRootShortcutReference(child_obj, child_entry);
+}
+
+
+void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) {
+  HeapEntry* child_entry = GetEntry(child_obj);
+  if (child_entry != NULL) {
+    filler_->SetStrongRootReference(child_obj, child_entry);
+  }
 }
 
 
@@ -2101,11 +2332,11 @@
   raw_additions_root_ =
       NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0));
   additions_root()->Init(
-      snapshot2_, HeapEntry::kInternal, "", 0, 0, additions_count, 0);
+      snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0);
   raw_deletions_root_ =
       NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0));
   deletions_root()->Init(
-      snapshot1_, HeapEntry::kInternal, "", 0, 0, deletions_count, 0);
+      snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0);
 }
 
 
@@ -2324,7 +2555,8 @@
   writer_->AddCharacter(',');
   writer_->AddNumber(edge->type());
   writer_->AddCharacter(',');
-  if (edge->type() == HeapGraphEdge::kElement) {
+  if (edge->type() == HeapGraphEdge::kElement
+      || edge->type() == HeapGraphEdge::kHidden) {
     writer_->AddNumber(edge->index());
   } else {
     writer_->AddNumber(GetStringId(edge->name()));
@@ -2344,6 +2576,10 @@
   writer_->AddNumber(entry->id());
   writer_->AddCharacter(',');
   writer_->AddNumber(entry->self_size());
+  writer_->AddCharacter(',');
+  writer_->AddNumber(entry->RetainedSize(false));
+  writer_->AddCharacter(',');
+  writer_->AddNumber(GetNodeId(entry->dominator()));
   Vector<HeapGraphEdge> children = entry->children();
   writer_->AddCharacter(',');
   writer_->AddNumber(children.length());
@@ -2355,23 +2591,25 @@
 
 
 void HeapSnapshotJSONSerializer::SerializeNodes() {
-  // The first (zero) item of nodes array is a JSON-ified object
-  // describing node serialization layout.
-  // We use a set of macros to improve readability.
+  // The first (zero) item of nodes array is an object describing node
+  // serialization layout.  We use a set of macros to improve
+  // readability.
 #define JSON_A(s) "["s"]"
 #define JSON_O(s) "{"s"}"
-#define JSON_S(s) "\\\""s"\\\""
-  writer_->AddString("\"" JSON_O(
+#define JSON_S(s) "\""s"\""
+  writer_->AddString(JSON_O(
     JSON_S("fields") ":" JSON_A(
         JSON_S("type")
         "," JSON_S("name")
         "," JSON_S("id")
         "," JSON_S("self_size")
+        "," JSON_S("retained_size")
+        "," JSON_S("dominator")
         "," JSON_S("children_count")
         "," JSON_S("children"))
     "," JSON_S("types") ":" JSON_A(
         JSON_A(
-            JSON_S("internal")
+            JSON_S("hidden")
             "," JSON_S("array")
             "," JSON_S("string")
             "," JSON_S("object")
@@ -2383,6 +2621,8 @@
         "," JSON_S("number")
         "," JSON_S("number")
         "," JSON_S("number")
+        "," JSON_S("number")
+        "," JSON_S("number")
         "," JSON_O(
             JSON_S("fields") ":" JSON_A(
                 JSON_S("type")
@@ -2393,14 +2633,17 @@
                     JSON_S("context")
                     "," JSON_S("element")
                     "," JSON_S("property")
-                    "," JSON_S("internal"))
+                    "," JSON_S("internal")
+                    "," JSON_S("hidden")
+                    "," JSON_S("shortcut"))
                 "," JSON_S("string_or_number")
-                "," JSON_S("node"))))) "\"");
+                "," JSON_S("node"))))));
 #undef JSON_S
 #undef JSON_O
 #undef JSON_A
 
-  const int node_fields_count = 5;  // type,name,id,self_size,children_count.
+  const int node_fields_count = 7;
+  // type,name,id,self_size,retained_size,dominator,children_count.
   const int edge_fields_count = 3;  // type,name|index,to_node.
   List<HashMap::Entry*> sorted_nodes;
   SortHashMap(&nodes_, &sorted_nodes);
@@ -2526,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 b691a05..55c57fd 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -439,22 +439,26 @@
     kContextVariable = v8::HeapGraphEdge::kContextVariable,
     kElement = v8::HeapGraphEdge::kElement,
     kProperty = v8::HeapGraphEdge::kProperty,
-    kInternal = v8::HeapGraphEdge::kInternal
+    kInternal = v8::HeapGraphEdge::kInternal,
+    kHidden = v8::HeapGraphEdge::kHidden,
+    kShortcut = v8::HeapGraphEdge::kShortcut
   };
 
   HeapGraphEdge() { }
   void Init(int child_index, Type type, const char* name, HeapEntry* to);
+  void Init(int child_index, Type type, int index, HeapEntry* to);
   void Init(int child_index, int index, HeapEntry* to);
 
   Type type() { return static_cast<Type>(type_); }
   int index() {
-    ASSERT(type_ == kElement);
+    ASSERT(type_ == kElement || type_ == kHidden);
     return index_;
   }
   const char* name() {
     ASSERT(type_ == kContextVariable
            || type_ == kProperty
-           || type_ == kInternal);
+           || type_ == kInternal
+           || type_ == kShortcut);
     return name_;
   }
   HeapEntry* to() { return to_; }
@@ -462,8 +466,8 @@
   HeapEntry* From();
 
  private:
-  int child_index_ : 30;
-  unsigned type_ : 2;
+  int child_index_ : 29;
+  unsigned type_ : 3;
   union {
     int index_;
     const char* name_;
@@ -500,7 +504,7 @@
 class HeapEntry BASE_EMBEDDED {
  public:
   enum Type {
-    kInternal = v8::HeapGraphNode::kInternal,
+    kHidden = v8::HeapGraphNode::kHidden,
     kArray = v8::HeapGraphNode::kArray,
     kString = v8::HeapGraphNode::kString,
     kObject = v8::HeapGraphNode::kObject,
@@ -522,14 +526,21 @@
   HeapSnapshot* snapshot() { return snapshot_; }
   Type type() { return static_cast<Type>(type_); }
   const char* name() { return name_; }
-  uint64_t id() { return id_; }
+  uint64_t id();
   int self_size() { return self_size_; }
+  int retained_size() { return retained_size_; }
+  void add_retained_size(int size) { retained_size_ += size; }
+  void set_retained_size(int value) { retained_size_ = value; }
+  int ordered_index() { return ordered_index_; }
+  void set_ordered_index(int value) { ordered_index_ = value; }
 
   Vector<HeapGraphEdge> children() {
     return Vector<HeapGraphEdge>(children_arr(), children_count_); }
   Vector<HeapGraphEdge*> retainers() {
     return Vector<HeapGraphEdge*>(retainers_arr(), retainers_count_); }
   List<HeapGraphPath*>* GetRetainingPaths();
+  HeapEntry* dominator() { return dominator_; }
+  void set_dominator(HeapEntry* entry) { dominator_ = entry; }
 
   void clear_paint() { painted_ = kUnpainted; }
   bool painted_reachable() { return painted_ == kPainted; }
@@ -547,8 +558,18 @@
   void ApplyAndPaintAllReachable(Visitor* visitor);
   void PaintAllReachable();
 
-  void SetElementReference(
-      int child_index, int index, HeapEntry* entry, int retainer_index);
+  bool is_leaf() { return painted_ == kLeaf; }
+  void set_leaf() { painted_ = kLeaf; }
+  bool is_non_leaf() { return painted_ == kNonLeaf; }
+  void set_non_leaf() { painted_ = kNonLeaf; }
+  bool is_processed() { return painted_ == kProcessed; }
+  void set_processed() { painted_ = kProcessed; }
+
+  void SetIndexedReference(HeapGraphEdge::Type type,
+                           int child_index,
+                           int index,
+                           HeapEntry* entry,
+                           int retainer_index);
   void SetNamedReference(HeapGraphEdge::Type type,
                          int child_index,
                          const char* name,
@@ -557,14 +578,19 @@
   void SetUnidirElementReference(int child_index, int index, HeapEntry* entry);
 
   int EntrySize() { return EntriesSize(1, children_count_, retainers_count_); }
-  int ReachableSize();
-  int RetainedSize();
+  int RetainedSize(bool exact);
+  List<HeapGraphPath*>* CalculateRetainingPaths();
 
   void Print(int max_depth, int indent);
 
   static int EntriesSize(int entries_count,
                          int children_count,
                          int retainers_count);
+  static uint32_t Hash(HeapEntry* entry) {
+    return ComputeIntegerHash(
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(entry)));
+  }
+  static bool Match(void* entry1, void* entry2) { return entry1 == entry2; }
 
  private:
   HeapGraphEdge* children_arr() {
@@ -573,56 +599,43 @@
   HeapGraphEdge** retainers_arr() {
     return reinterpret_cast<HeapGraphEdge**>(children_arr() + children_count_);
   }
+  void CalculateExactRetainedSize();
+  void FindRetainingPaths(CachedHeapGraphPath* prev_path,
+                          List<HeapGraphPath*>* retaining_paths);
   const char* TypeAsString();
 
   unsigned painted_: 2;
   unsigned type_: 3;
-  // The calculated data is stored in HeapSnapshot in HeapEntryCalculatedData
-  // entries. See AddCalculatedData and GetCalculatedData.
-  int calculated_data_index_: 27;
-  int self_size_;
-  int children_count_;
+  int children_count_: 27;
   int retainers_count_;
+  int self_size_;
+  union {
+    int ordered_index_;  // Used during dominator tree building.
+    int retained_size_;  // At that moment, there is no retained size yet.
+  };
+  HeapEntry* dominator_;
   HeapSnapshot* snapshot_;
+  struct Id {
+    uint32_t id1_;
+    uint32_t id2_;
+  } id_;  // This is to avoid extra padding of 64-bit value.
   const char* name_;
-  uint64_t id_;
 
+  // Paints used for exact retained sizes calculation.
   static const unsigned kUnpainted = 0;
   static const unsigned kPainted = 1;
   static const unsigned kPaintedReachableFromOthers = 2;
-  static const int kNoCalculatedData = -1;
+  // Paints used for approximate retained sizes calculation.
+  static const unsigned kLeaf = 0;
+  static const unsigned kNonLeaf = 1;
+  static const unsigned kProcessed = 2;
+
+  static const int kExactRetainedSizeTag = 1;
 
   DISALLOW_COPY_AND_ASSIGN(HeapEntry);
 };
 
 
-class HeapEntryCalculatedData {
- public:
-  HeapEntryCalculatedData()
-      : retaining_paths_(NULL),
-        reachable_size_(kUnknownSize),
-        retained_size_(kUnknownSize) {
-  }
-  void Dispose();
-
-  List<HeapGraphPath*>* GetRetainingPaths(HeapEntry* entry);
-  int ReachableSize(HeapEntry* entry);
-  int RetainedSize(HeapEntry* entry);
-
- private:
-  void CalculateSizes(HeapEntry* entry);
-  void FindRetainingPaths(HeapEntry* entry, CachedHeapGraphPath* prev_path);
-
-  List<HeapGraphPath*>* retaining_paths_;
-  int reachable_size_;
-  int retained_size_;
-
-  static const int kUnknownSize = -1;
-
-  // Allow generated copy constructor and assignment operator.
-};
-
-
 class HeapGraphPath {
  public:
   HeapGraphPath()
@@ -668,32 +681,32 @@
   const char* title() { return title_; }
   unsigned uid() { return uid_; }
   HeapEntry* root() { return root_entry_; }
+  HeapEntry* gc_roots() { return gc_roots_entry_; }
 
   void AllocateEntries(
       int entries_count, int children_count, int retainers_count);
   HeapEntry* AddEntry(
       HeapObject* object, int children_count, int retainers_count);
-  bool WillAddEntry(HeapObject* object);
   HeapEntry* AddEntry(HeapEntry::Type type,
                       const char* name,
                       uint64_t id,
                       int size,
                       int children_count,
                       int retainers_count);
-  int AddCalculatedData();
-  HeapEntryCalculatedData& GetCalculatedData(int index) {
-    return calculated_data_[index];
-  }
+  void ApproximateRetainedSizes();
   void ClearPaint();
   HeapSnapshotsDiff* CompareWith(HeapSnapshot* snapshot);
+  List<HeapGraphPath*>* GetRetainingPaths(HeapEntry* entry);
   List<HeapEntry*>* GetSortedEntriesList();
   template<class Visitor>
   void IterateEntries(Visitor* visitor) { entries_.Iterate(visitor); }
+  void SetDominatorsToSelf();
 
   void Print(int max_depth);
   void PrintEntriesSize();
 
-  static HeapObject *const kInternalRootObject;
+  static HeapObject* const kInternalRootObject;
+  static HeapObject* const kGcRootsObject;
 
  private:
   HeapEntry* AddEntry(HeapObject* object,
@@ -702,18 +715,21 @@
                       int children_count,
                       int retainers_count);
   HeapEntry* GetNextEntryToInit();
-  static int GetObjectSize(HeapObject* obj);
-  static int CalculateNetworkSize(JSObject* obj);
+  void BuildDominatorTree(const Vector<HeapEntry*>& entries,
+                          Vector<HeapEntry*>* dominators);
+  void FillReversePostorderIndexes(Vector<HeapEntry*>* entries);
+  void SetEntriesDominators();
 
   HeapSnapshotsCollection* collection_;
   Type type_;
   const char* title_;
   unsigned uid_;
   HeapEntry* root_entry_;
+  HeapEntry* gc_roots_entry_;
   char* raw_entries_;
   List<HeapEntry*> entries_;
   bool entries_sorted_;
-  List<HeapEntryCalculatedData> calculated_data_;
+  HashMap retaining_paths_;
 #ifdef DEBUG
   int raw_entries_size_;
 #endif
@@ -733,6 +749,10 @@
   uint64_t FindObject(Address addr);
   void MoveObject(Address from, Address to);
 
+  static const uint64_t kInternalRootObjectId;
+  static const uint64_t kGcRootsObjectId;
+  static const uint64_t kFirstAvailableObjectId;
+
  private:
   struct EntryInfo {
     explicit EntryInfo(uint64_t id) : id(id), accessed(true) { }
@@ -868,9 +888,6 @@
   HeapEntriesMap();
   ~HeapEntriesMap();
 
-  // Aliasing is used for skipping intermediate proxy objects, like
-  // JSGlobalPropertyCell.
-  void Alias(HeapObject* from, HeapObject* to);
   HeapEntry* Map(HeapObject* object);
   void Pair(HeapObject* object, HeapEntry* entry);
   void CountReference(HeapObject* from, HeapObject* to,
@@ -894,41 +911,45 @@
     int retainers_count;
   };
 
-  uint32_t Hash(HeapObject* object) {
+  static uint32_t Hash(HeapObject* object) {
     return ComputeIntegerHash(
         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object)));
   }
   static bool HeapObjectsMatch(void* key1, void* key2) { return key1 == key2; }
 
-  bool IsAlias(void* ptr) {
-    return reinterpret_cast<intptr_t>(ptr) & kAliasTag;
-  }
-  void* MakeAlias(void* ptr) {
-    return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(ptr) | kAliasTag);
-  }
-  void* Unalias(void* ptr) {
-    return reinterpret_cast<void*>(
-        reinterpret_cast<intptr_t>(ptr) & (~kAliasTag));
-  }
-
   HashMap entries_;
   int entries_count_;
   int total_children_count_;
   int total_retainers_count_;
 
-  static const intptr_t kAliasTag = 1;
+  friend class HeapObjectsSet;
 
   DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap);
 };
 
 
+class HeapObjectsSet {
+ public:
+  HeapObjectsSet();
+  void Clear();
+  bool Contains(Object* object);
+  void Insert(Object* obj);
+
+ private:
+  HashMap entries_;
+
+  DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet);
+};
+
+
 class HeapSnapshotGenerator {
  public:
   class SnapshotFillerInterface {
    public:
     virtual ~SnapshotFillerInterface() { }
     virtual HeapEntry* AddEntry(HeapObject* obj) = 0;
-    virtual void SetElementReference(HeapObject* parent_obj,
+    virtual void SetIndexedReference(HeapGraphEdge::Type type,
+                                     HeapObject* parent_obj,
                                      HeapEntry* parent_entry,
                                      int index,
                                      Object* child_obj,
@@ -939,8 +960,11 @@
                                    const char* reference_name,
                                    Object* child_obj,
                                    HeapEntry* child_entry) = 0;
-    virtual void SetRootReference(Object* child_obj,
-                                  HeapEntry* child_entry) = 0;
+    virtual void SetRootGcRootsReference() = 0;
+    virtual void SetRootShortcutReference(Object* child_obj,
+                                          HeapEntry* child_entry) = 0;
+    virtual void SetStrongRootReference(Object* child_obj,
+                                        HeapEntry* child_entry) = 0;
   };
 
   explicit HeapSnapshotGenerator(HeapSnapshot* snapshot);
@@ -969,19 +993,33 @@
                             HeapEntry* parent,
                             int index,
                             Object* child);
+  void SetHiddenReference(HeapObject* parent_obj,
+                          HeapEntry* parent,
+                          int index,
+                          Object* child);
   void SetPropertyReference(HeapObject* parent_obj,
                             HeapEntry* parent,
                             String* reference_name,
                             Object* child);
-  void SetRootReference(Object* child);
+  void SetPropertyShortcutReference(HeapObject* parent_obj,
+                                    HeapEntry* parent,
+                                    String* reference_name,
+                                    Object* child);
+  void SetRootShortcutReference(Object* child);
+  void SetRootGcRootsReference();
+  void SetGcRootsReference(Object* child);
 
   HeapSnapshot* snapshot_;
   HeapSnapshotsCollection* collection_;
   // Mapping from HeapObject* pointers to HeapEntry* pointers.
   HeapEntriesMap entries_;
   SnapshotFillerInterface* filler_;
+  // Used during references extraction to mark heap objects that
+  // are references via non-hidden properties.
+  HeapObjectsSet known_references_;
 
   friend class IndexedReferencesExtractor;
+  friend class RootsReferencesExtractor;
 
   DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator);
 };
@@ -1035,6 +1073,9 @@
   DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
 };
 
+
+String* GetConstructorNameForHeapProfile(JSObject* object);
+
 } }  // namespace v8::internal
 
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/src/regexp.js b/src/regexp.js
index 9e708fd..d01d04f 100644
--- a/src/regexp.js
+++ b/src/regexp.js
@@ -193,20 +193,16 @@
   var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
 
   if (matchIndices === null) {
-    if (global) {
-      this.lastIndex = 0;
-    }
+    if (global) this.lastIndex = 0;
     return null;
   }
 
   // Successful match.
   lastMatchInfoOverride = null;
-  var result = BuildResultFromMatchInfo(matchIndices, s);
-
   if (global) {
     this.lastIndex = lastMatchInfo[CAPTURE1];
   }
-  return result;
+  return BuildResultFromMatchInfo(matchIndices, s);
 }
 
 
@@ -244,43 +240,44 @@
   // algorithm, step 5) even if the value is discarded for non-global RegExps.
   var i = TO_INTEGER(lastIndex);
   
-  var global = this.global;
-  if (global) {
+  if (this.global) {
     if (i < 0 || i > s.length) {
       this.lastIndex = 0;
       return false;
     }
-  } else {
-    i = 0;
-  }
-
-  // Remove irrelevant preceeding '.*' in a test regexp. The expression
-  // checks whether this.source starts with '.*' and that the third
-  // char is not a '?'
-  if (%_StringCharCodeAt(this.source, 0) == 46 &&  // '.'
-      %_StringCharCodeAt(this.source, 1) == 42 &&  // '*'
-      %_StringCharCodeAt(this.source, 2) != 63) {  // '?'
-    if (!%_ObjectEquals(regexp_key, this)) {
-      regexp_key = this;
-      regexp_val = new $RegExp(this.source.substring(2, this.source.length),
-                               (global ? 'g' : '')
-                               + (this.ignoreCase ? 'i' : '')
-                               + (this.multiline ? 'm' : ''));
+    %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
+    // matchIndices is either null or the lastMatchInfo array.
+    var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
+    if (matchIndices === null) {
+      this.lastIndex = 0;
+      return false;
     }
-    if (!regexp_val.test(s)) return false;
+    lastMatchInfoOverride = null;
+    this.lastIndex = lastMatchInfo[CAPTURE1];
+    return true;    
+  } else {
+    // Non-global regexp.
+    // Remove irrelevant preceeding '.*' in a non-global test regexp. 
+    // The expression checks whether this.source starts with '.*' and 
+    // that the third char is not a '?'.
+    if (%_StringCharCodeAt(this.source, 0) == 46 &&  // '.'
+        %_StringCharCodeAt(this.source, 1) == 42 &&  // '*'
+        %_StringCharCodeAt(this.source, 2) != 63) {  // '?'
+      if (!%_ObjectEquals(regexp_key, this)) {
+        regexp_key = this;
+        regexp_val = new $RegExp(this.source.substring(2, this.source.length),
+                                 (this.ignoreCase ? 'i' : '')
+                                 + (this.multiline ? 'm' : ''));
+      }
+      if (!regexp_val.test(s)) return false;
+    }    
+    %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
+    // matchIndices is either null or the lastMatchInfo array.
+    var matchIndices = %_RegExpExec(this, s, 0, lastMatchInfo);
+    if (matchIndices === null) return false;
+    lastMatchInfoOverride = null;
+    return true;
   }
-
-  %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
-  // matchIndices is either null or the lastMatchInfo array.
-  var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
-
-  if (matchIndices === null) {
-    if (global) this.lastIndex = 0;
-    return false;
-  }
-  lastMatchInfoOverride = null;
-  if (global) this.lastIndex = lastMatchInfo[CAPTURE1];
-  return true;
 }
 
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 5534db5..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()) {
@@ -6340,15 +6341,20 @@
 
 static MaybeObject* Runtime_NewClosure(Arguments args) {
   HandleScope scope;
-  ASSERT(args.length() == 2);
+  ASSERT(args.length() == 3);
   CONVERT_ARG_CHECKED(Context, context, 0);
   CONVERT_ARG_CHECKED(SharedFunctionInfo, shared, 1);
+  CONVERT_BOOLEAN_CHECKED(pretenure, args[2]);
 
-  PretenureFlag pretenure = (context->global_context() == *context)
-      ? TENURED       // Allocate global closures in old space.
-      : NOT_TENURED;  // Allocate local closures in new space.
+  // Allocate global closures in old space and allocate local closures
+  // in new space. Additionally pretenure closures that are assigned
+  // directly to properties.
+  pretenure = pretenure || (context->global_context() == *context);
+  PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
   Handle<JSFunction> result =
-      Factory::NewFunctionFromSharedFunctionInfo(shared, context, pretenure);
+      Factory::NewFunctionFromSharedFunctionInfo(shared,
+                                                 context,
+                                                 pretenure_flag);
   return *result;
 }
 
@@ -6386,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()));
@@ -6454,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 756099b..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 */ \
@@ -262,7 +262,7 @@
   F(CreateCatchExtensionObject, 2, 1) \
   \
   /* Statements */ \
-  F(NewClosure, 2, 1) \
+  F(NewClosure, 3, 1) \
   F(NewObject, 1, 1) \
   F(NewObjectFromBound, 2, 1) \
   F(FinalizeInstanceSize, 1, 1) \
@@ -418,7 +418,8 @@
   F(MathSqrt, 1, 1)                                                          \
   F(IsRegExpEquivalent, 2, 1)                                                \
   F(HasCachedArrayIndex, 1, 1)                                               \
-  F(GetCachedArrayIndex, 1, 1)
+  F(GetCachedArrayIndex, 1, 1)                                               \
+  F(FastAsciiArrayJoin, 2, 1)
 
 
 // ----------------------------------------------------------------------------
diff --git a/src/scanner-base.cc b/src/scanner-base.cc
index 6e9d40e..8242f81 100644
--- a/src/scanner-base.cc
+++ b/src/scanner-base.cc
@@ -27,12 +27,770 @@
 
 // Features shared by parsing and pre-parsing scanners.
 
+#include "../include/v8stdint.h"
 #include "scanner-base.h"
+#include "char-predicates-inl.h"
 
 namespace v8 {
 namespace internal {
 
 // ----------------------------------------------------------------------------
+// UTF16Buffer
+
+UTF16Buffer::UTF16Buffer()
+    : pos_(0), end_(kNoEndPosition) { }
+
+// ----------------------------------------------------------------------------
+// LiteralCollector
+
+LiteralCollector::LiteralCollector()
+    : buffer_(kInitialCapacity), recording_(false) { }
+
+
+LiteralCollector::~LiteralCollector() {}
+
+
+void LiteralCollector::AddCharSlow(uc32 c) {
+  ASSERT(static_cast<unsigned>(c) > unibrow::Utf8::kMaxOneByteChar);
+  int length = unibrow::Utf8::Length(c);
+  Vector<char> block = buffer_.AddBlock(length, '\0');
+#ifdef DEBUG
+  int written_length = unibrow::Utf8::Encode(block.start(), c);
+  CHECK_EQ(length, written_length);
+#else
+  unibrow::Utf8::Encode(block.start(), c);
+#endif
+}
+
+// ----------------------------------------------------------------------------
+// Character predicates
+
+unibrow::Predicate<IdentifierStart, 128> ScannerConstants::kIsIdentifierStart;
+unibrow::Predicate<IdentifierPart, 128> ScannerConstants::kIsIdentifierPart;
+unibrow::Predicate<unibrow::WhiteSpace, 128> ScannerConstants::kIsWhiteSpace;
+unibrow::Predicate<unibrow::LineTerminator, 128>
+  ScannerConstants::kIsLineTerminator;
+
+StaticResource<ScannerConstants::Utf8Decoder> ScannerConstants::utf8_decoder_;
+
+// Compound predicates.
+
+bool ScannerConstants::IsIdentifier(unibrow::CharacterStream* buffer) {
+  // Checks whether the buffer contains an identifier (no escape).
+  if (!buffer->has_more()) return false;
+  if (!kIsIdentifierStart.get(buffer->GetNext())) {
+    return false;
+  }
+  while (buffer->has_more()) {
+    if (!kIsIdentifierPart.get(buffer->GetNext())) {
+      return false;
+    }
+  }
+  return true;
+}
+
+// ----------------------------------------------------------------------------
+// Scanner
+
+Scanner::Scanner() : source_(NULL), stack_overflow_(false) {}
+
+
+uc32 Scanner::ScanHexEscape(uc32 c, int length) {
+  ASSERT(length <= 4);  // prevent overflow
+
+  uc32 digits[4];
+  uc32 x = 0;
+  for (int i = 0; i < length; i++) {
+    digits[i] = c0_;
+    int d = HexValue(c0_);
+    if (d < 0) {
+      // According to ECMA-262, 3rd, 7.8.4, page 18, these hex escapes
+      // should be illegal, but other JS VMs just return the
+      // non-escaped version of the original character.
+
+      // Push back digits read, except the last one (in c0_).
+      for (int j = i-1; j >= 0; j--) {
+        PushBack(digits[j]);
+      }
+      // Notice: No handling of error - treat it as "\u"->"u".
+      return c;
+    }
+    x = x * 16 + d;
+    Advance();
+  }
+
+  return x;
+}
+
+
+// Octal escapes of the forms '\0xx' and '\xxx' are not a part of
+// ECMA-262. Other JS VMs support them.
+uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
+  uc32 x = c - '0';
+  for (int i = 0; i < length; i++) {
+    int d = c0_ - '0';
+    if (d < 0 || d > 7) break;
+    int nx = x * 8 + d;
+    if (nx >= 256) break;
+    x = nx;
+    Advance();
+  }
+  return x;
+}
+
+
+// ----------------------------------------------------------------------------
+// JavaScriptScanner
+
+JavaScriptScanner::JavaScriptScanner()
+    : has_line_terminator_before_next_(false) {}
+
+
+Token::Value JavaScriptScanner::Next() {
+  current_ = next_;
+  has_line_terminator_before_next_ = false;
+  Scan();
+  return current_.token;
+}
+
+
+static inline bool IsByteOrderMark(uc32 c) {
+  // The Unicode value U+FFFE is guaranteed never to be assigned as a
+  // Unicode character; this implies that in a Unicode context the
+  // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF
+  // character expressed in little-endian byte order (since it could
+  // not be a U+FFFE character expressed in big-endian byte
+  // order). Nevertheless, we check for it to be compatible with
+  // Spidermonkey.
+  return c == 0xFEFF || c == 0xFFFE;
+}
+
+
+bool JavaScriptScanner::SkipWhiteSpace() {
+  int start_position = source_pos();
+
+  while (true) {
+    // We treat byte-order marks (BOMs) as whitespace for better
+    // compatibility with Spidermonkey and other JavaScript engines.
+    while (ScannerConstants::kIsWhiteSpace.get(c0_) || IsByteOrderMark(c0_)) {
+      // IsWhiteSpace() includes line terminators!
+      if (ScannerConstants::kIsLineTerminator.get(c0_)) {
+        // Ignore line terminators, but remember them. This is necessary
+        // for automatic semicolon insertion.
+        has_line_terminator_before_next_ = true;
+      }
+      Advance();
+    }
+
+    // If there is an HTML comment end '-->' at the beginning of a
+    // line (with only whitespace in front of it), we treat the rest
+    // of the line as a comment. This is in line with the way
+    // SpiderMonkey handles it.
+    if (c0_ == '-' && has_line_terminator_before_next_) {
+      Advance();
+      if (c0_ == '-') {
+        Advance();
+        if (c0_ == '>') {
+          // Treat the rest of the line as a comment.
+          SkipSingleLineComment();
+          // Continue skipping white space after the comment.
+          continue;
+        }
+        PushBack('-');  // undo Advance()
+      }
+      PushBack('-');  // undo Advance()
+    }
+    // Return whether or not we skipped any characters.
+    return source_pos() != start_position;
+  }
+}
+
+
+Token::Value JavaScriptScanner::SkipSingleLineComment() {
+  Advance();
+
+  // The line terminator at the end of the line is not considered
+  // to be part of the single-line comment; it is recognized
+  // separately by the lexical grammar and becomes part of the
+  // stream of input elements for the syntactic grammar (see
+  // ECMA-262, section 7.4, page 12).
+  while (c0_ >= 0 && !ScannerConstants::kIsLineTerminator.get(c0_)) {
+    Advance();
+  }
+
+  return Token::WHITESPACE;
+}
+
+
+Token::Value JavaScriptScanner::SkipMultiLineComment() {
+  ASSERT(c0_ == '*');
+  Advance();
+
+  while (c0_ >= 0) {
+    char ch = c0_;
+    Advance();
+    // If we have reached the end of the multi-line comment, we
+    // consume the '/' and insert a whitespace. This way all
+    // multi-line comments are treated as whitespace - even the ones
+    // containing line terminators. This contradicts ECMA-262, section
+    // 7.4, page 12, that says that multi-line comments containing
+    // line terminators should be treated as a line terminator, but it
+    // matches the behaviour of SpiderMonkey and KJS.
+    if (ch == '*' && c0_ == '/') {
+      c0_ = ' ';
+      return Token::WHITESPACE;
+    }
+  }
+
+  // Unterminated multi-line comment.
+  return Token::ILLEGAL;
+}
+
+
+Token::Value JavaScriptScanner::ScanHtmlComment() {
+  // Check for <!-- comments.
+  ASSERT(c0_ == '!');
+  Advance();
+  if (c0_ == '-') {
+    Advance();
+    if (c0_ == '-') return SkipSingleLineComment();
+    PushBack('-');  // undo Advance()
+  }
+  PushBack('!');  // undo Advance()
+  ASSERT(c0_ == '!');
+  return Token::LT;
+}
+
+
+void JavaScriptScanner::Scan() {
+  next_.literal_chars = Vector<const char>();
+  Token::Value token;
+  do {
+    // Remember the position of the next token
+    next_.location.beg_pos = source_pos();
+
+    switch (c0_) {
+      case ' ':
+      case '\t':
+        Advance();
+        token = Token::WHITESPACE;
+        break;
+
+      case '\n':
+        Advance();
+        has_line_terminator_before_next_ = true;
+        token = Token::WHITESPACE;
+        break;
+
+      case '"': case '\'':
+        token = ScanString();
+        break;
+
+      case '<':
+        // < <= << <<= <!--
+        Advance();
+        if (c0_ == '=') {
+          token = Select(Token::LTE);
+        } else if (c0_ == '<') {
+          token = Select('=', Token::ASSIGN_SHL, Token::SHL);
+        } else if (c0_ == '!') {
+          token = ScanHtmlComment();
+        } else {
+          token = Token::LT;
+        }
+        break;
+
+      case '>':
+        // > >= >> >>= >>> >>>=
+        Advance();
+        if (c0_ == '=') {
+          token = Select(Token::GTE);
+        } else if (c0_ == '>') {
+          // >> >>= >>> >>>=
+          Advance();
+          if (c0_ == '=') {
+            token = Select(Token::ASSIGN_SAR);
+          } else if (c0_ == '>') {
+            token = Select('=', Token::ASSIGN_SHR, Token::SHR);
+          } else {
+            token = Token::SAR;
+          }
+        } else {
+          token = Token::GT;
+        }
+        break;
+
+      case '=':
+        // = == ===
+        Advance();
+        if (c0_ == '=') {
+          token = Select('=', Token::EQ_STRICT, Token::EQ);
+        } else {
+          token = Token::ASSIGN;
+        }
+        break;
+
+      case '!':
+        // ! != !==
+        Advance();
+        if (c0_ == '=') {
+          token = Select('=', Token::NE_STRICT, Token::NE);
+        } else {
+          token = Token::NOT;
+        }
+        break;
+
+      case '+':
+        // + ++ +=
+        Advance();
+        if (c0_ == '+') {
+          token = Select(Token::INC);
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_ADD);
+        } else {
+          token = Token::ADD;
+        }
+        break;
+
+      case '-':
+        // - -- --> -=
+        Advance();
+        if (c0_ == '-') {
+          Advance();
+          if (c0_ == '>' && has_line_terminator_before_next_) {
+            // For compatibility with SpiderMonkey, we skip lines that
+            // start with an HTML comment end '-->'.
+            token = SkipSingleLineComment();
+          } else {
+            token = Token::DEC;
+          }
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_SUB);
+        } else {
+          token = Token::SUB;
+        }
+        break;
+
+      case '*':
+        // * *=
+        token = Select('=', Token::ASSIGN_MUL, Token::MUL);
+        break;
+
+      case '%':
+        // % %=
+        token = Select('=', Token::ASSIGN_MOD, Token::MOD);
+        break;
+
+      case '/':
+        // /  // /* /=
+        Advance();
+        if (c0_ == '/') {
+          token = SkipSingleLineComment();
+        } else if (c0_ == '*') {
+          token = SkipMultiLineComment();
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_DIV);
+        } else {
+          token = Token::DIV;
+        }
+        break;
+
+      case '&':
+        // & && &=
+        Advance();
+        if (c0_ == '&') {
+          token = Select(Token::AND);
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_BIT_AND);
+        } else {
+          token = Token::BIT_AND;
+        }
+        break;
+
+      case '|':
+        // | || |=
+        Advance();
+        if (c0_ == '|') {
+          token = Select(Token::OR);
+        } else if (c0_ == '=') {
+          token = Select(Token::ASSIGN_BIT_OR);
+        } else {
+          token = Token::BIT_OR;
+        }
+        break;
+
+      case '^':
+        // ^ ^=
+        token = Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
+        break;
+
+      case '.':
+        // . Number
+        Advance();
+        if (IsDecimalDigit(c0_)) {
+          token = ScanNumber(true);
+        } else {
+          token = Token::PERIOD;
+        }
+        break;
+
+      case ':':
+        token = Select(Token::COLON);
+        break;
+
+      case ';':
+        token = Select(Token::SEMICOLON);
+        break;
+
+      case ',':
+        token = Select(Token::COMMA);
+        break;
+
+      case '(':
+        token = Select(Token::LPAREN);
+        break;
+
+      case ')':
+        token = Select(Token::RPAREN);
+        break;
+
+      case '[':
+        token = Select(Token::LBRACK);
+        break;
+
+      case ']':
+        token = Select(Token::RBRACK);
+        break;
+
+      case '{':
+        token = Select(Token::LBRACE);
+        break;
+
+      case '}':
+        token = Select(Token::RBRACE);
+        break;
+
+      case '?':
+        token = Select(Token::CONDITIONAL);
+        break;
+
+      case '~':
+        token = Select(Token::BIT_NOT);
+        break;
+
+      default:
+        if (ScannerConstants::kIsIdentifierStart.get(c0_)) {
+          token = ScanIdentifierOrKeyword();
+        } else if (IsDecimalDigit(c0_)) {
+          token = ScanNumber(false);
+        } else if (SkipWhiteSpace()) {
+          token = Token::WHITESPACE;
+        } else if (c0_ < 0) {
+          token = Token::EOS;
+        } else {
+          token = Select(Token::ILLEGAL);
+        }
+        break;
+    }
+
+    // Continue scanning for tokens as long as we're just skipping
+    // whitespace.
+  } while (token == Token::WHITESPACE);
+
+  next_.location.end_pos = source_pos();
+  next_.token = token;
+}
+
+
+void JavaScriptScanner::SeekForward(int pos) {
+  source_->SeekForward(pos - 1);
+  Advance();
+  // This function is only called to seek to the location
+  // of the end of a function (at the "}" token). It doesn't matter
+  // whether there was a line terminator in the part we skip.
+  has_line_terminator_before_next_ = false;
+  Scan();
+}
+
+
+void JavaScriptScanner::ScanEscape() {
+  uc32 c = c0_;
+  Advance();
+
+  // Skip escaped newlines.
+  if (ScannerConstants::kIsLineTerminator.get(c)) {
+    // Allow CR+LF newlines in multiline string literals.
+    if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
+    // Allow LF+CR newlines in multiline string literals.
+    if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance();
+    return;
+  }
+
+  switch (c) {
+    case '\'':  // fall through
+    case '"' :  // fall through
+    case '\\': break;
+    case 'b' : c = '\b'; break;
+    case 'f' : c = '\f'; break;
+    case 'n' : c = '\n'; break;
+    case 'r' : c = '\r'; break;
+    case 't' : c = '\t'; break;
+    case 'u' : c = ScanHexEscape(c, 4); break;
+    case 'v' : c = '\v'; break;
+    case 'x' : c = ScanHexEscape(c, 2); break;
+    case '0' :  // fall through
+    case '1' :  // fall through
+    case '2' :  // fall through
+    case '3' :  // fall through
+    case '4' :  // fall through
+    case '5' :  // fall through
+    case '6' :  // fall through
+    case '7' : c = ScanOctalEscape(c, 2); break;
+  }
+
+  // According to ECMA-262, 3rd, 7.8.4 (p 18ff) these
+  // should be illegal, but they are commonly handled
+  // as non-escaped characters by JS VMs.
+  AddLiteralChar(c);
+}
+
+
+Token::Value JavaScriptScanner::ScanString() {
+  uc32 quote = c0_;
+  Advance();  // consume quote
+
+  LiteralScope literal(this, kLiteralString);
+  while (c0_ != quote && c0_ >= 0
+         && !ScannerConstants::kIsLineTerminator.get(c0_)) {
+    uc32 c = c0_;
+    Advance();
+    if (c == '\\') {
+      if (c0_ < 0) return Token::ILLEGAL;
+      ScanEscape();
+    } else {
+      AddLiteralChar(c);
+    }
+  }
+  if (c0_ != quote) return Token::ILLEGAL;
+  literal.Complete();
+
+  Advance();  // consume quote
+  return Token::STRING;
+}
+
+
+void JavaScriptScanner::ScanDecimalDigits() {
+  while (IsDecimalDigit(c0_))
+    AddLiteralCharAdvance();
+}
+
+
+Token::Value JavaScriptScanner::ScanNumber(bool seen_period) {
+  ASSERT(IsDecimalDigit(c0_));  // the first digit of the number or the fraction
+
+  enum { DECIMAL, HEX, OCTAL } kind = DECIMAL;
+
+  LiteralScope literal(this, kLiteralNumber);
+  if (seen_period) {
+    // we have already seen a decimal point of the float
+    AddLiteralChar('.');
+    ScanDecimalDigits();  // we know we have at least one digit
+
+  } else {
+    // if the first character is '0' we must check for octals and hex
+    if (c0_ == '0') {
+      AddLiteralCharAdvance();
+
+      // either 0, 0exxx, 0Exxx, 0.xxx, an octal number, or a hex number
+      if (c0_ == 'x' || c0_ == 'X') {
+        // hex number
+        kind = HEX;
+        AddLiteralCharAdvance();
+        if (!IsHexDigit(c0_)) {
+          // we must have at least one hex digit after 'x'/'X'
+          return Token::ILLEGAL;
+        }
+        while (IsHexDigit(c0_)) {
+          AddLiteralCharAdvance();
+        }
+      } else if ('0' <= c0_ && c0_ <= '7') {
+        // (possible) octal number
+        kind = OCTAL;
+        while (true) {
+          if (c0_ == '8' || c0_ == '9') {
+            kind = DECIMAL;
+            break;
+          }
+          if (c0_  < '0' || '7'  < c0_) break;
+          AddLiteralCharAdvance();
+        }
+      }
+    }
+
+    // Parse decimal digits and allow trailing fractional part.
+    if (kind == DECIMAL) {
+      ScanDecimalDigits();  // optional
+      if (c0_ == '.') {
+        AddLiteralCharAdvance();
+        ScanDecimalDigits();  // optional
+      }
+    }
+  }
+
+  // scan exponent, if any
+  if (c0_ == 'e' || c0_ == 'E') {
+    ASSERT(kind != HEX);  // 'e'/'E' must be scanned as part of the hex number
+    if (kind == OCTAL) return Token::ILLEGAL;  // no exponent for octals allowed
+    // scan exponent
+    AddLiteralCharAdvance();
+    if (c0_ == '+' || c0_ == '-')
+      AddLiteralCharAdvance();
+    if (!IsDecimalDigit(c0_)) {
+      // we must have at least one decimal digit after 'e'/'E'
+      return Token::ILLEGAL;
+    }
+    ScanDecimalDigits();
+  }
+
+  // The source character immediately following a numeric literal must
+  // not be an identifier start or a decimal digit; see ECMA-262
+  // section 7.8.3, page 17 (note that we read only one decimal digit
+  // if the value is 0).
+  if (IsDecimalDigit(c0_) || ScannerConstants::kIsIdentifierStart.get(c0_))
+    return Token::ILLEGAL;
+
+  literal.Complete();
+
+  return Token::NUMBER;
+}
+
+
+uc32 JavaScriptScanner::ScanIdentifierUnicodeEscape() {
+  Advance();
+  if (c0_ != 'u') return unibrow::Utf8::kBadChar;
+  Advance();
+  uc32 c = ScanHexEscape('u', 4);
+  // We do not allow a unicode escape sequence to start another
+  // unicode escape sequence.
+  if (c == '\\') return unibrow::Utf8::kBadChar;
+  return c;
+}
+
+
+Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() {
+  ASSERT(ScannerConstants::kIsIdentifierStart.get(c0_));
+  LiteralScope literal(this, kLiteralIdentifier);
+  KeywordMatcher keyword_match;
+  // Scan identifier start character.
+  if (c0_ == '\\') {
+    uc32 c = ScanIdentifierUnicodeEscape();
+    // Only allow legal identifier start characters.
+    if (!ScannerConstants::kIsIdentifierStart.get(c)) return Token::ILLEGAL;
+    AddLiteralChar(c);
+    return ScanIdentifierSuffix(&literal);
+  }
+
+  uc32 first_char = c0_;
+  Advance();
+  AddLiteralChar(first_char);
+  if (!keyword_match.AddChar(first_char)) {
+    return ScanIdentifierSuffix(&literal);
+  }
+
+  // Scan the rest of the identifier characters.
+  while (ScannerConstants::kIsIdentifierPart.get(c0_)) {
+    if (c0_ != '\\') {
+      uc32 next_char = c0_;
+      Advance();
+      AddLiteralChar(next_char);
+      if (keyword_match.AddChar(next_char)) continue;
+    }
+    // Fallthrough if no loner able to complete keyword.
+    return ScanIdentifierSuffix(&literal);
+  }
+  literal.Complete();
+
+  return keyword_match.token();
+}
+
+
+Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) {
+  // Scan the rest of the identifier characters.
+  while (ScannerConstants::kIsIdentifierPart.get(c0_)) {
+    if (c0_ == '\\') {
+      uc32 c = ScanIdentifierUnicodeEscape();
+      // Only allow legal identifier part characters.
+      if (!ScannerConstants::kIsIdentifierPart.get(c)) return Token::ILLEGAL;
+      AddLiteralChar(c);
+    } else {
+      AddLiteralChar(c0_);
+      Advance();
+    }
+  }
+  literal->Complete();
+
+  return Token::IDENTIFIER;
+}
+
+
+bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) {
+  // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
+  bool in_character_class = false;
+
+  // Previous token is either '/' or '/=', in the second case, the
+  // pattern starts at =.
+  next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
+  next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0);
+
+  // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
+  // the scanner should pass uninterpreted bodies to the RegExp
+  // constructor.
+  LiteralScope literal(this, kLiteralRegExp);
+  if (seen_equal)
+    AddLiteralChar('=');
+
+  while (c0_ != '/' || in_character_class) {
+    if (ScannerConstants::kIsLineTerminator.get(c0_) || c0_ < 0) return false;
+    if (c0_ == '\\') {  // escaped character
+      AddLiteralCharAdvance();
+      if (ScannerConstants::kIsLineTerminator.get(c0_) || c0_ < 0) return false;
+      AddLiteralCharAdvance();
+    } else {  // unescaped character
+      if (c0_ == '[') in_character_class = true;
+      if (c0_ == ']') in_character_class = false;
+      AddLiteralCharAdvance();
+    }
+  }
+  Advance();  // consume '/'
+
+  literal.Complete();
+
+  return true;
+}
+
+
+bool JavaScriptScanner::ScanRegExpFlags() {
+  // Scan regular expression flags.
+  LiteralScope literal(this, kLiteralRegExpFlags);
+  while (ScannerConstants::kIsIdentifierPart.get(c0_)) {
+    if (c0_ == '\\') {
+      uc32 c = ScanIdentifierUnicodeEscape();
+      if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) {
+        // We allow any escaped character, unlike the restriction on
+        // IdentifierPart when it is used to build an IdentifierName.
+        AddLiteralChar(c);
+        continue;
+      }
+    }
+    AddLiteralCharAdvance();
+  }
+  literal.Complete();
+
+  next_.location.end_pos = source_pos() - 1;
+  return true;
+}
+
+// ----------------------------------------------------------------------------
 // Keyword Matcher
 
 KeywordMatcher::FirstState KeywordMatcher::first_states_[] = {
@@ -127,9 +885,7 @@
       break;
     case IN:
       token_ = Token::IDENTIFIER;
-      if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) {
-        return;
-      }
+      if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) return;
       break;
     case N:
       if (MatchKeywordStart(input, "native", 1, Token::NATIVE)) return;
diff --git a/src/scanner-base.h b/src/scanner-base.h
index 500870b..3714ae2 100644
--- a/src/scanner-base.h
+++ b/src/scanner-base.h
@@ -30,12 +30,402 @@
 #ifndef V8_SCANNER_BASE_H_
 #define V8_SCANNER_BASE_H_
 
+#include "globals.h"
+#include "checks.h"
+#include "allocation.h"
 #include "token.h"
-#include "unicode.h"
+#include "unicode-inl.h"
+#include "char-predicates.h"
+#include "utils.h"
+#include "list-inl.h"
 
 namespace v8 {
 namespace internal {
 
+// Returns the value (0 .. 15) of a hexadecimal character c.
+// If c is not a legal hexadecimal character, returns a value < 0.
+inline int HexValue(uc32 c) {
+  c -= '0';
+  if (static_cast<unsigned>(c) <= 9) return c;
+  c = (c | 0x20) - ('a' - '0');  // detect 0x11..0x16 and 0x31..0x36.
+  if (static_cast<unsigned>(c) <= 5) return c + 10;
+  return -1;
+}
+
+// ----------------------------------------------------------------------------
+// UTF16Buffer - scanner input source with pushback.
+
+class UTF16Buffer {
+ public:
+  UTF16Buffer();
+  virtual ~UTF16Buffer() {}
+
+  virtual void PushBack(uc32 ch) = 0;
+  // Returns a value < 0 when the buffer end is reached.
+  virtual uc32 Advance() = 0;
+  virtual void SeekForward(int pos) = 0;
+
+  int pos() const { return pos_; }
+
+  static const int kNoEndPosition = 1;
+
+ protected:
+  // Initial value of end_ before the input stream is initialized.
+
+  int pos_;  // Current position in the buffer.
+  int end_;  // Position where scanning should stop (EOF).
+};
+
+
+class ScannerConstants : AllStatic {
+ public:
+  typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder;
+
+  static StaticResource<Utf8Decoder>* utf8_decoder() {
+    return &utf8_decoder_;
+  }
+
+  static unibrow::Predicate<IdentifierStart, 128> kIsIdentifierStart;
+  static unibrow::Predicate<IdentifierPart, 128> kIsIdentifierPart;
+  static unibrow::Predicate<unibrow::LineTerminator, 128> kIsLineTerminator;
+  static unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;
+
+  static bool IsIdentifier(unibrow::CharacterStream* buffer);
+
+ private:
+  static StaticResource<Utf8Decoder> utf8_decoder_;
+};
+
+// ----------------------------------------------------------------------------
+// LiteralCollector -  Collector of chars of literals.
+
+class LiteralCollector {
+ public:
+  LiteralCollector();
+  ~LiteralCollector();
+
+  inline void AddChar(uc32 c) {
+    if (recording_) {
+      if (static_cast<unsigned>(c) <= unibrow::Utf8::kMaxOneByteChar) {
+        buffer_.Add(static_cast<char>(c));
+      } else {
+        AddCharSlow(c);
+      }
+    }
+  }
+
+  void StartLiteral() {
+    buffer_.StartSequence();
+    recording_ = true;
+  }
+
+  Vector<const char> EndLiteral() {
+    if (recording_) {
+      recording_ = false;
+      buffer_.Add(kEndMarker);
+      Vector<char> sequence = buffer_.EndSequence();
+      return Vector<const char>(sequence.start(), sequence.length());
+    }
+    return Vector<const char>();
+  }
+
+  void DropLiteral() {
+    if (recording_) {
+      recording_ = false;
+      buffer_.DropSequence();
+    }
+  }
+
+  void Reset() {
+    buffer_.Reset();
+  }
+
+  // The end marker added after a parsed literal.
+  // Using zero allows the usage of strlen and similar functions on
+  // identifiers and numbers (but not strings, since they may contain zero
+  // bytes).
+  static const char kEndMarker = '\x00';
+ private:
+  static const int kInitialCapacity = 256;
+  SequenceCollector<char, 4> buffer_;
+  bool recording_;
+  void AddCharSlow(uc32 c);
+};
+
+// ----------------------------------------------------------------------------
+// Scanner base-class.
+
+// Generic functionality used by both JSON and JavaScript scanners.
+class Scanner {
+ public:
+  typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder;
+
+  class LiteralScope {
+   public:
+    explicit LiteralScope(Scanner* self);
+    ~LiteralScope();
+    void Complete();
+
+   private:
+    Scanner* scanner_;
+    bool complete_;
+  };
+
+  Scanner();
+
+  // Returns the current token again.
+  Token::Value current_token() { return current_.token; }
+
+  // One token look-ahead (past the token returned by Next()).
+  Token::Value peek() const { return next_.token; }
+
+  struct Location {
+    Location(int b, int e) : beg_pos(b), end_pos(e) { }
+    Location() : beg_pos(0), end_pos(0) { }
+    int beg_pos;
+    int end_pos;
+  };
+
+  // Returns the location information for the current token
+  // (the token returned by Next()).
+  Location location() const { return current_.location; }
+  Location peek_location() const { return next_.location; }
+
+  // Returns the literal string, if any, for the current token (the
+  // token returned by Next()). The string is 0-terminated and in
+  // UTF-8 format; they may contain 0-characters. Literal strings are
+  // collected for identifiers, strings, and numbers.
+  // These functions only give the correct result if the literal
+  // was scanned between calls to StartLiteral() and TerminateLiteral().
+  const char* literal_string() const {
+    return current_.literal_chars.start();
+  }
+
+  int literal_length() const {
+    // Excluding terminal '\x00' added by TerminateLiteral().
+    return current_.literal_chars.length() - 1;
+  }
+
+  Vector<const char> literal() const {
+    return Vector<const char>(literal_string(), literal_length());
+  }
+
+  // Returns the literal string for the next token (the token that
+  // would be returned if Next() were called).
+  const char* next_literal_string() const {
+    return next_.literal_chars.start();
+  }
+
+
+  // Returns the length of the next token (that would be returned if
+  // Next() were called).
+  int next_literal_length() const {
+    // Excluding terminal '\x00' added by TerminateLiteral().
+    return next_.literal_chars.length() - 1;
+  }
+
+  Vector<const char> next_literal() const {
+    return Vector<const char>(next_literal_string(), next_literal_length());
+  }
+
+  bool stack_overflow() { return stack_overflow_; }
+
+  static const int kCharacterLookaheadBufferSize = 1;
+
+ protected:
+  // The current and look-ahead token.
+  struct TokenDesc {
+    Token::Value token;
+    Location location;
+    Vector<const char> literal_chars;
+  };
+
+  // Call this after setting source_ to the input.
+  void Init() {
+    // Set c0_ (one character ahead)
+    ASSERT(kCharacterLookaheadBufferSize == 1);
+    Advance();
+    // Initialize current_ to not refer to a literal.
+    current_.literal_chars = Vector<const char>();
+    // Reset literal buffer.
+    literal_buffer_.Reset();
+  }
+
+  // Literal buffer support
+  inline void StartLiteral() {
+    literal_buffer_.StartLiteral();
+  }
+
+  inline void AddLiteralChar(uc32 c) {
+    literal_buffer_.AddChar(c);
+  }
+
+  // Complete scanning of a literal.
+  inline void TerminateLiteral() {
+    next_.literal_chars = literal_buffer_.EndLiteral();
+  }
+
+  // Stops scanning of a literal and drop the collected characters,
+  // e.g., due to an encountered error.
+  inline void DropLiteral() {
+    literal_buffer_.DropLiteral();
+  }
+
+  inline void AddLiteralCharAdvance() {
+    AddLiteralChar(c0_);
+    Advance();
+  }
+
+  // Low-level scanning support.
+  void Advance() { c0_ = source_->Advance(); }
+  void PushBack(uc32 ch) {
+    source_->PushBack(ch);
+    c0_ = ch;
+  }
+
+  inline Token::Value Select(Token::Value tok) {
+    Advance();
+    return tok;
+  }
+
+  inline Token::Value Select(uc32 next, Token::Value then, Token::Value else_) {
+    Advance();
+    if (c0_ == next) {
+      Advance();
+      return then;
+    } else {
+      return else_;
+    }
+  }
+
+  uc32 ScanHexEscape(uc32 c, int length);
+  uc32 ScanOctalEscape(uc32 c, int length);
+
+  // Return the current source position.
+  int source_pos() {
+    return source_->pos() - kCharacterLookaheadBufferSize;
+  }
+
+  TokenDesc current_;  // desc for current token (as returned by Next())
+  TokenDesc next_;     // desc for next token (one token look-ahead)
+
+  // Input stream. Must be initialized to an UTF16Buffer.
+  UTF16Buffer* source_;
+
+  // Buffer to hold literal values (identifiers, strings, numbers)
+  // using '\x00'-terminated UTF-8 encoding. Handles allocation internally.
+  LiteralCollector literal_buffer_;
+
+  bool stack_overflow_;
+
+  // One Unicode character look-ahead; c0_ < 0 at the end of the input.
+  uc32 c0_;
+};
+
+// ----------------------------------------------------------------------------
+// JavaScriptScanner - base logic for JavaScript scanning.
+
+class JavaScriptScanner : public Scanner {
+ public:
+
+  // Bit vector representing set of types of literals.
+  enum LiteralType {
+    kNoLiterals = 0,
+    kLiteralNumber = 1,
+    kLiteralIdentifier = 2,
+    kLiteralString = 4,
+    kLiteralRegExp = 8,
+    kLiteralRegExpFlags = 16,
+    kAllLiterals = 31
+  };
+
+  // A LiteralScope that disables recording of some types of JavaScript
+  // literals. If the scanner is configured to not record the specific
+  // type of literal, the scope will not call StartLiteral.
+  class LiteralScope {
+   public:
+    LiteralScope(JavaScriptScanner* self, LiteralType type)
+        : scanner_(self), complete_(false) {
+      if (scanner_->RecordsLiteral(type)) {
+        scanner_->StartLiteral();
+      }
+    }
+     ~LiteralScope() {
+       if (!complete_) scanner_->DropLiteral();
+     }
+    void Complete() {
+      scanner_->TerminateLiteral();
+      complete_ = true;
+    }
+
+   private:
+    JavaScriptScanner* scanner_;
+    bool complete_;
+  };
+
+  JavaScriptScanner();
+
+  // Returns the next token.
+  Token::Value Next();
+
+  // Returns true if there was a line terminator before the peek'ed token.
+  bool has_line_terminator_before_next() const {
+    return has_line_terminator_before_next_;
+  }
+
+  // Scans the input as a regular expression pattern, previous
+  // character(s) must be /(=). Returns true if a pattern is scanned.
+  bool ScanRegExpPattern(bool seen_equal);
+  // Returns true if regexp flags are scanned (always since flags can
+  // be empty).
+  bool ScanRegExpFlags();
+
+  // Tells whether the buffer contains an identifier (no escapes).
+  // Used for checking if a property name is an identifier.
+  static bool IsIdentifier(unibrow::CharacterStream* buffer);
+
+  // Seek forward to the given position.  This operation does not
+  // work in general, for instance when there are pushed back
+  // characters, but works for seeking forward until simple delimiter
+  // tokens, which is what it is used for.
+  void SeekForward(int pos);
+
+  // Whether this scanner records the given literal type or not.
+  bool RecordsLiteral(LiteralType type) {
+    return (literal_flags_ & type) != 0;
+  }
+
+ protected:
+  bool SkipWhiteSpace();
+  Token::Value SkipSingleLineComment();
+  Token::Value SkipMultiLineComment();
+
+  // Scans a single JavaScript token.
+  void Scan();
+
+  void ScanDecimalDigits();
+  Token::Value ScanNumber(bool seen_period);
+  Token::Value ScanIdentifierOrKeyword();
+  Token::Value ScanIdentifierSuffix(LiteralScope* literal);
+
+  void ScanEscape();
+  Token::Value ScanString();
+
+  // Scans a possible HTML comment -- begins with '<!'.
+  Token::Value ScanHtmlComment();
+
+  // Decodes a unicode escape-sequence which is part of an identifier.
+  // If the escape sequence cannot be decoded the result is kBadChar.
+  uc32 ScanIdentifierUnicodeEscape();
+
+  int literal_flags_;
+  bool has_line_terminator_before_next_;
+};
+
+
+// ----------------------------------------------------------------------------
+// Keyword matching state machine.
+
 class KeywordMatcher {
 //  Incrementally recognize keywords.
 //
@@ -45,7 +435,8 @@
 //      return switch this throw true try typeof var void while with
 //
 //  *: Actually "future reserved keywords". These are the only ones we
-//     recognized, the remaining are allowed as identifiers.
+//     recognize, the remaining are allowed as identifiers.
+//     In ES5 strict mode, we should disallow all reserved keywords.
  public:
   KeywordMatcher()
       : state_(INITIAL),
@@ -56,10 +447,11 @@
 
   Token::Value token() { return token_; }
 
-  inline void AddChar(unibrow::uchar input) {
+  inline bool AddChar(unibrow::uchar input) {
     if (state_ != UNMATCHABLE) {
       Step(input);
     }
+    return state_ != UNMATCHABLE;
   }
 
   void Fail() {
@@ -110,23 +502,23 @@
                                 const char* keyword,
                                 int position,
                                 Token::Value token_if_match) {
-    if (input == static_cast<unibrow::uchar>(keyword[position])) {
-      state_ = KEYWORD_PREFIX;
-      this->keyword_ = keyword;
-      this->counter_ = position + 1;
-      this->keyword_token_ = token_if_match;
-      return true;
+    if (input != static_cast<unibrow::uchar>(keyword[position])) {
+      return false;
     }
-    return false;
+    state_ = KEYWORD_PREFIX;
+    this->keyword_ = keyword;
+    this->counter_ = position + 1;
+    this->keyword_token_ = token_if_match;
+    return true;
   }
 
   // If input equals match character, transition to new state and return true.
   inline bool MatchState(unibrow::uchar input, char match, State new_state) {
-    if (input == static_cast<unibrow::uchar>(match)) {
-      state_ = new_state;
-      return true;
+    if (input != static_cast<unibrow::uchar>(match)) {
+      return false;
     }
-    return false;
+    state_ = new_state;
+    return true;
   }
 
   inline bool MatchKeyword(unibrow::uchar input,
@@ -156,10 +548,6 @@
 };
 
 
-
-
-
-
 } }  // namespace v8::internal
 
 #endif  // V8_SCANNER_BASE_H_
diff --git a/src/scanner.cc b/src/scanner.cc
index a24952a..63b2fd8 100755
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -30,53 +30,14 @@
 #include "ast.h"
 #include "handles.h"
 #include "scanner.h"
+#include "unicode-inl.h"
 
 namespace v8 {
 namespace internal {
 
 // ----------------------------------------------------------------------------
-// Character predicates
-
-
-unibrow::Predicate<IdentifierStart, 128> Scanner::kIsIdentifierStart;
-unibrow::Predicate<IdentifierPart, 128> Scanner::kIsIdentifierPart;
-unibrow::Predicate<unibrow::LineTerminator, 128> Scanner::kIsLineTerminator;
-unibrow::Predicate<unibrow::WhiteSpace, 128> Scanner::kIsWhiteSpace;
-
-
-StaticResource<Scanner::Utf8Decoder> Scanner::utf8_decoder_;
-
-
-// ----------------------------------------------------------------------------
-// UTF8Buffer
-
-UTF8Buffer::UTF8Buffer() : buffer_(kInitialCapacity) { }
-
-
-UTF8Buffer::~UTF8Buffer() {}
-
-
-void UTF8Buffer::AddCharSlow(uc32 c) {
-  ASSERT(static_cast<unsigned>(c) > unibrow::Utf8::kMaxOneByteChar);
-  int length = unibrow::Utf8::Length(c);
-  Vector<char> block = buffer_.AddBlock(length, '\0');
-#ifdef DEBUG
-  int written_length = unibrow::Utf8::Encode(block.start(), c);
-  CHECK_EQ(length, written_length);
-#else
-  unibrow::Utf8::Encode(block.start(), c);
-#endif
-}
-
-
-// ----------------------------------------------------------------------------
 // UTF16Buffer
 
-
-UTF16Buffer::UTF16Buffer()
-    : pos_(0), end_(Scanner::kNoEndPosition) { }
-
-
 // CharacterStreamUTF16Buffer
 CharacterStreamUTF16Buffer::CharacterStreamUTF16Buffer()
     : pushback_buffer_(0), last_(0), stream_(NULL) { }
@@ -90,7 +51,7 @@
   if (start_position > 0) {
     SeekForward(start_position);
   }
-  end_ = end_position != Scanner::kNoEndPosition ? end_position : kMaxInt;
+  end_ = end_position != kNoEndPosition ? end_position : kMaxInt;
 }
 
 
@@ -102,7 +63,7 @@
 
 
 uc32 CharacterStreamUTF16Buffer::Advance() {
-  ASSERT(end_ != Scanner::kNoEndPosition);
+  ASSERT(end_ != kNoEndPosition);
   ASSERT(end_ >= 0);
   // NOTE: It is of importance to Persian / Farsi resources that we do
   // *not* strip format control characters in the scanner; see
@@ -135,55 +96,6 @@
 }
 
 
-// ExternalStringUTF16Buffer
-template <typename StringType, typename CharType>
-ExternalStringUTF16Buffer<StringType, CharType>::ExternalStringUTF16Buffer()
-    : raw_data_(NULL) { }
-
-
-template <typename StringType, typename CharType>
-void ExternalStringUTF16Buffer<StringType, CharType>::Initialize(
-     Handle<StringType> data,
-     int start_position,
-     int end_position) {
-  ASSERT(!data.is_null());
-  raw_data_ = data->resource()->data();
-
-  ASSERT(end_position <= data->length());
-  if (start_position > 0) {
-    SeekForward(start_position);
-  }
-  end_ =
-      end_position != Scanner::kNoEndPosition ? end_position : data->length();
-}
-
-
-template <typename StringType, typename CharType>
-uc32 ExternalStringUTF16Buffer<StringType, CharType>::Advance() {
-  if (pos_ < end_) {
-    return raw_data_[pos_++];
-  } else {
-    // note: currently the following increment is necessary to avoid a
-    // test-parser problem!
-    pos_++;
-    return static_cast<uc32>(-1);
-  }
-}
-
-
-template <typename StringType, typename CharType>
-void ExternalStringUTF16Buffer<StringType, CharType>::PushBack(uc32 ch) {
-  pos_--;
-  ASSERT(pos_ >= Scanner::kCharacterLookaheadBufferSize);
-  ASSERT(raw_data_[pos_ - Scanner::kCharacterLookaheadBufferSize] == ch);
-}
-
-
-template <typename StringType, typename CharType>
-void ExternalStringUTF16Buffer<StringType, CharType>::SeekForward(int pos) {
-  pos_ = pos;
-}
-
 // ----------------------------------------------------------------------------
 // Scanner::LiteralScope
 
@@ -204,41 +116,74 @@
 }
 
 // ----------------------------------------------------------------------------
-// Scanner
+// V8JavaScriptScanner
 
-Scanner::Scanner()
-    : has_line_terminator_before_next_(false),
-      is_parsing_json_(false),
-      source_(NULL),
-      stack_overflow_(false) {}
-
-
-void Scanner::Initialize(Handle<String> source,
-                         ParserLanguage language) {
-  Init(source, NULL, 0, source->length(), language);
+void V8JavaScriptScanner::Initialize(Handle<String> source,
+                                     int literal_flags) {
+  source_ = stream_initializer_.Init(source, NULL, 0, source->length());
+  // Need to capture identifiers in order to recognize "get" and "set"
+  // in object literals.
+  literal_flags_ = literal_flags | 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();
 }
 
 
-void Scanner::Initialize(Handle<String> source,
-                         unibrow::CharacterStream* stream,
-                         ParserLanguage language) {
-  Init(source, stream, 0, kNoEndPosition, language);
+void V8JavaScriptScanner::Initialize(Handle<String> source,
+                                     unibrow::CharacterStream* stream,
+                                     int literal_flags) {
+  source_ = stream_initializer_.Init(source, stream,
+                                     0, UTF16Buffer::kNoEndPosition);
+  literal_flags_ = literal_flags | 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();
 }
 
 
-void Scanner::Initialize(Handle<String> source,
-                         int start_position,
-                         int end_position,
-                         ParserLanguage language) {
-  Init(source, NULL, start_position, end_position, language);
+void V8JavaScriptScanner::Initialize(Handle<String> source,
+                                     int start_position,
+                                     int end_position,
+                                     int literal_flags) {
+  source_ = stream_initializer_.Init(source, NULL,
+                                     start_position, end_position);
+  literal_flags_ = literal_flags | 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();
 }
 
 
-void Scanner::Init(Handle<String> source,
-                   unibrow::CharacterStream* stream,
-                   int start_position,
-                   int end_position,
-                   ParserLanguage language) {
+Token::Value V8JavaScriptScanner::NextCheckStack() {
+  // BUG 1215673: Find a thread safe way to set a stack limit in
+  // pre-parse mode. Otherwise, we cannot safely pre-parse from other
+  // threads.
+  StackLimitCheck check;
+  if (check.HasOverflowed()) {
+    stack_overflow_ = true;
+    current_ = next_;
+    next_.token = Token::ILLEGAL;
+    return current_.token;
+  } else {
+    return Next();
+  }
+}
+
+
+UTF16Buffer* StreamInitializer::Init(Handle<String> source,
+                                     unibrow::CharacterStream* stream,
+                                     int start_position,
+                                     int end_position) {
   // Either initialize the scanner from a character stream or from a
   // string.
   ASSERT(source.is_null() || stream == NULL);
@@ -249,13 +194,13 @@
         Handle<ExternalTwoByteString>::cast(source),
         start_position,
         end_position);
-    source_ = &two_byte_string_buffer_;
+    return &two_byte_string_buffer_;
   } else if (!source.is_null() && StringShape(*source).IsExternalAscii()) {
     ascii_string_buffer_.Initialize(
         Handle<ExternalAsciiString>::cast(source),
         start_position,
         end_position);
-    source_ = &ascii_string_buffer_;
+    return &ascii_string_buffer_;
   } else {
     if (!source.is_null()) {
       safe_string_input_buffer_.Reset(source.location());
@@ -265,28 +210,27 @@
                                    stream,
                                    start_position,
                                    end_position);
-    source_ = &char_stream_buffer_;
+    return &char_stream_buffer_;
   }
+}
 
-  is_parsing_json_ = (language == JSON);
+// ----------------------------------------------------------------------------
+// JsonScanner
 
-  // Set c0_ (one character ahead)
-  ASSERT(kCharacterLookaheadBufferSize == 1);
-  Advance();
-  // Initialize current_ to not refer to a literal.
-  current_.literal_chars = Vector<const char>();
-  // Reset literal buffer.
-  literal_buffer_.Reset();
+JsonScanner::JsonScanner() {}
 
-  // Skip initial whitespace allowing HTML comment ends just like
-  // after a newline and scan first token.
-  has_line_terminator_before_next_ = true;
-  SkipWhiteSpace();
-  Scan();
+
+void JsonScanner::Initialize(Handle<String> source) {
+  source_ = stream_initializer_.Init(source, NULL, 0, source->length());
+  Init();
+  // Skip initial whitespace.
+  SkipJsonWhiteSpace();
+  // Preload first token as look-ahead.
+  ScanJson();
 }
 
 
-Token::Value Scanner::Next() {
+Token::Value JsonScanner::Next() {
   // BUG 1215673: Find a thread safe way to set a stack limit in
   // pre-parse mode. Otherwise, we cannot safely pre-parse from other
   // threads.
@@ -297,52 +241,13 @@
     stack_overflow_ = true;
     next_.token = Token::ILLEGAL;
   } else {
-    has_line_terminator_before_next_ = false;
-    Scan();
+    ScanJson();
   }
   return current_.token;
 }
 
 
-void Scanner::StartLiteral() {
-  literal_buffer_.StartLiteral();
-}
-
-
-void Scanner::AddChar(uc32 c) {
-  literal_buffer_.AddChar(c);
-}
-
-
-void Scanner::TerminateLiteral() {
-  next_.literal_chars = literal_buffer_.EndLiteral();
-}
-
-
-void Scanner::DropLiteral() {
-  literal_buffer_.DropLiteral();
-}
-
-
-void Scanner::AddCharAdvance() {
-  AddChar(c0_);
-  Advance();
-}
-
-
-static inline bool IsByteOrderMark(uc32 c) {
-  // The Unicode value U+FFFE is guaranteed never to be assigned as a
-  // Unicode character; this implies that in a Unicode context the
-  // 0xFF, 0xFE byte pattern can only be interpreted as the U+FEFF
-  // character expressed in little-endian byte order (since it could
-  // not be a U+FFFE character expressed in big-endian byte
-  // order). Nevertheless, we check for it to be compatible with
-  // Spidermonkey.
-  return c == 0xFEFF || c == 0xFFFE;
-}
-
-
-bool Scanner::SkipJsonWhiteSpace() {
+bool JsonScanner::SkipJsonWhiteSpace() {
   int start_position = source_pos();
   // JSON WhiteSpace is tab, carrige-return, newline and space.
   while (c0_ == ' ' || c0_ == '\n' || c0_ == '\r' || c0_ == '\t') {
@@ -352,107 +257,9 @@
 }
 
 
-bool Scanner::SkipJavaScriptWhiteSpace() {
-  int start_position = source_pos();
-
-  while (true) {
-    // We treat byte-order marks (BOMs) as whitespace for better
-    // compatibility with Spidermonkey and other JavaScript engines.
-    while (kIsWhiteSpace.get(c0_) || IsByteOrderMark(c0_)) {
-      // IsWhiteSpace() includes line terminators!
-      if (kIsLineTerminator.get(c0_)) {
-        // Ignore line terminators, but remember them. This is necessary
-        // for automatic semicolon insertion.
-        has_line_terminator_before_next_ = true;
-      }
-      Advance();
-    }
-
-    // If there is an HTML comment end '-->' at the beginning of a
-    // line (with only whitespace in front of it), we treat the rest
-    // of the line as a comment. This is in line with the way
-    // SpiderMonkey handles it.
-    if (c0_ == '-' && has_line_terminator_before_next_) {
-      Advance();
-      if (c0_ == '-') {
-        Advance();
-        if (c0_ == '>') {
-          // Treat the rest of the line as a comment.
-          SkipSingleLineComment();
-          // Continue skipping white space after the comment.
-          continue;
-        }
-        PushBack('-');  // undo Advance()
-      }
-      PushBack('-');  // undo Advance()
-    }
-    // Return whether or not we skipped any characters.
-    return source_pos() != start_position;
-  }
-}
-
-
-Token::Value Scanner::SkipSingleLineComment() {
-  Advance();
-
-  // The line terminator at the end of the line is not considered
-  // to be part of the single-line comment; it is recognized
-  // separately by the lexical grammar and becomes part of the
-  // stream of input elements for the syntactic grammar (see
-  // ECMA-262, section 7.4, page 12).
-  while (c0_ >= 0 && !kIsLineTerminator.get(c0_)) {
-    Advance();
-  }
-
-  return Token::WHITESPACE;
-}
-
-
-Token::Value Scanner::SkipMultiLineComment() {
-  ASSERT(c0_ == '*');
-  Advance();
-
-  while (c0_ >= 0) {
-    char ch = c0_;
-    Advance();
-    // If we have reached the end of the multi-line comment, we
-    // consume the '/' and insert a whitespace. This way all
-    // multi-line comments are treated as whitespace - even the ones
-    // containing line terminators. This contradicts ECMA-262, section
-    // 7.4, page 12, that says that multi-line comments containing
-    // line terminators should be treated as a line terminator, but it
-    // matches the behaviour of SpiderMonkey and KJS.
-    if (ch == '*' && c0_ == '/') {
-      c0_ = ' ';
-      return Token::WHITESPACE;
-    }
-  }
-
-  // Unterminated multi-line comment.
-  return Token::ILLEGAL;
-}
-
-
-Token::Value Scanner::ScanHtmlComment() {
-  // Check for <!-- comments.
-  ASSERT(c0_ == '!');
-  Advance();
-  if (c0_ == '-') {
-    Advance();
-    if (c0_ == '-') return SkipSingleLineComment();
-    PushBack('-');  // undo Advance()
-  }
-  PushBack('!');  // undo Advance()
-  ASSERT(c0_ == '!');
-  return Token::LT;
-}
-
-
-
-void Scanner::ScanJson() {
+void JsonScanner::ScanJson() {
   next_.literal_chars = Vector<const char>();
   Token::Value token;
-  has_line_terminator_before_next_ = false;
   do {
     // Remember the position of the next token
     next_.location.beg_pos = source_pos();
@@ -529,7 +336,7 @@
 }
 
 
-Token::Value Scanner::ScanJsonString() {
+Token::Value JsonScanner::ScanJsonString() {
   ASSERT_EQ('"', c0_);
   Advance();
   LiteralScope literal(this);
@@ -537,29 +344,29 @@
     // Check for control character (0x00-0x1f) or unterminated string (<0).
     if (c0_ < 0x20) return Token::ILLEGAL;
     if (c0_ != '\\') {
-      AddCharAdvance();
+      AddLiteralCharAdvance();
     } else {
       Advance();
       switch (c0_) {
         case '"':
         case '\\':
         case '/':
-          AddChar(c0_);
+          AddLiteralChar(c0_);
           break;
         case 'b':
-          AddChar('\x08');
+          AddLiteralChar('\x08');
           break;
         case 'f':
-          AddChar('\x0c');
+          AddLiteralChar('\x0c');
           break;
         case 'n':
-          AddChar('\x0a');
+          AddLiteralChar('\x0a');
           break;
         case 'r':
-          AddChar('\x0d');
+          AddLiteralChar('\x0d');
           break;
         case 't':
-          AddChar('\x09');
+          AddLiteralChar('\x09');
           break;
         case 'u': {
           uc32 value = 0;
@@ -571,7 +378,7 @@
             }
             value = value * 16 + digit;
           }
-          AddChar(value);
+          AddLiteralChar(value);
           break;
         }
         default:
@@ -589,33 +396,33 @@
 }
 
 
-Token::Value Scanner::ScanJsonNumber() {
+Token::Value JsonScanner::ScanJsonNumber() {
   LiteralScope literal(this);
-  if (c0_ == '-') AddCharAdvance();
+  if (c0_ == '-') AddLiteralCharAdvance();
   if (c0_ == '0') {
-    AddCharAdvance();
+    AddLiteralCharAdvance();
     // Prefix zero is only allowed if it's the only digit before
     // a decimal point or exponent.
     if ('0' <= c0_ && c0_ <= '9') return Token::ILLEGAL;
   } else {
     if (c0_ < '1' || c0_ > '9') return Token::ILLEGAL;
     do {
-      AddCharAdvance();
+      AddLiteralCharAdvance();
     } while (c0_ >= '0' && c0_ <= '9');
   }
   if (c0_ == '.') {
-    AddCharAdvance();
+    AddLiteralCharAdvance();
     if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL;
     do {
-      AddCharAdvance();
+      AddLiteralCharAdvance();
     } while (c0_ >= '0' && c0_ <= '9');
   }
   if (AsciiAlphaToLower(c0_) == 'e') {
-    AddCharAdvance();
-    if (c0_ == '-' || c0_ == '+') AddCharAdvance();
+    AddLiteralCharAdvance();
+    if (c0_ == '-' || c0_ == '+') AddLiteralCharAdvance();
     if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL;
     do {
-      AddCharAdvance();
+      AddLiteralCharAdvance();
     } while (c0_ >= '0' && c0_ <= '9');
   }
   literal.Complete();
@@ -623,601 +430,19 @@
 }
 
 
-Token::Value Scanner::ScanJsonIdentifier(const char* text,
-                                         Token::Value token) {
+Token::Value JsonScanner::ScanJsonIdentifier(const char* text,
+                                             Token::Value token) {
   LiteralScope literal(this);
   while (*text != '\0') {
     if (c0_ != *text) return Token::ILLEGAL;
     Advance();
     text++;
   }
-  if (kIsIdentifierPart.get(c0_)) return Token::ILLEGAL;
+  if (ScannerConstants::kIsIdentifierPart.get(c0_)) return Token::ILLEGAL;
   literal.Complete();
   return token;
 }
 
 
-void Scanner::ScanJavaScript() {
-  next_.literal_chars = Vector<const char>();
-  Token::Value token;
-  do {
-    // Remember the position of the next token
-    next_.location.beg_pos = source_pos();
-
-    switch (c0_) {
-      case ' ':
-      case '\t':
-        Advance();
-        token = Token::WHITESPACE;
-        break;
-
-      case '\n':
-        Advance();
-        has_line_terminator_before_next_ = true;
-        token = Token::WHITESPACE;
-        break;
-
-      case '"': case '\'':
-        token = ScanString();
-        break;
-
-      case '<':
-        // < <= << <<= <!--
-        Advance();
-        if (c0_ == '=') {
-          token = Select(Token::LTE);
-        } else if (c0_ == '<') {
-          token = Select('=', Token::ASSIGN_SHL, Token::SHL);
-        } else if (c0_ == '!') {
-          token = ScanHtmlComment();
-        } else {
-          token = Token::LT;
-        }
-        break;
-
-      case '>':
-        // > >= >> >>= >>> >>>=
-        Advance();
-        if (c0_ == '=') {
-          token = Select(Token::GTE);
-        } else if (c0_ == '>') {
-          // >> >>= >>> >>>=
-          Advance();
-          if (c0_ == '=') {
-            token = Select(Token::ASSIGN_SAR);
-          } else if (c0_ == '>') {
-            token = Select('=', Token::ASSIGN_SHR, Token::SHR);
-          } else {
-            token = Token::SAR;
-          }
-        } else {
-          token = Token::GT;
-        }
-        break;
-
-      case '=':
-        // = == ===
-        Advance();
-        if (c0_ == '=') {
-          token = Select('=', Token::EQ_STRICT, Token::EQ);
-        } else {
-          token = Token::ASSIGN;
-        }
-        break;
-
-      case '!':
-        // ! != !==
-        Advance();
-        if (c0_ == '=') {
-          token = Select('=', Token::NE_STRICT, Token::NE);
-        } else {
-          token = Token::NOT;
-        }
-        break;
-
-      case '+':
-        // + ++ +=
-        Advance();
-        if (c0_ == '+') {
-          token = Select(Token::INC);
-        } else if (c0_ == '=') {
-          token = Select(Token::ASSIGN_ADD);
-        } else {
-          token = Token::ADD;
-        }
-        break;
-
-      case '-':
-        // - -- --> -=
-        Advance();
-        if (c0_ == '-') {
-          Advance();
-          if (c0_ == '>' && has_line_terminator_before_next_) {
-            // For compatibility with SpiderMonkey, we skip lines that
-            // start with an HTML comment end '-->'.
-            token = SkipSingleLineComment();
-          } else {
-            token = Token::DEC;
-          }
-        } else if (c0_ == '=') {
-          token = Select(Token::ASSIGN_SUB);
-        } else {
-          token = Token::SUB;
-        }
-        break;
-
-      case '*':
-        // * *=
-        token = Select('=', Token::ASSIGN_MUL, Token::MUL);
-        break;
-
-      case '%':
-        // % %=
-        token = Select('=', Token::ASSIGN_MOD, Token::MOD);
-        break;
-
-      case '/':
-        // /  // /* /=
-        Advance();
-        if (c0_ == '/') {
-          token = SkipSingleLineComment();
-        } else if (c0_ == '*') {
-          token = SkipMultiLineComment();
-        } else if (c0_ == '=') {
-          token = Select(Token::ASSIGN_DIV);
-        } else {
-          token = Token::DIV;
-        }
-        break;
-
-      case '&':
-        // & && &=
-        Advance();
-        if (c0_ == '&') {
-          token = Select(Token::AND);
-        } else if (c0_ == '=') {
-          token = Select(Token::ASSIGN_BIT_AND);
-        } else {
-          token = Token::BIT_AND;
-        }
-        break;
-
-      case '|':
-        // | || |=
-        Advance();
-        if (c0_ == '|') {
-          token = Select(Token::OR);
-        } else if (c0_ == '=') {
-          token = Select(Token::ASSIGN_BIT_OR);
-        } else {
-          token = Token::BIT_OR;
-        }
-        break;
-
-      case '^':
-        // ^ ^=
-        token = Select('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
-        break;
-
-      case '.':
-        // . Number
-        Advance();
-        if (IsDecimalDigit(c0_)) {
-          token = ScanNumber(true);
-        } else {
-          token = Token::PERIOD;
-        }
-        break;
-
-      case ':':
-        token = Select(Token::COLON);
-        break;
-
-      case ';':
-        token = Select(Token::SEMICOLON);
-        break;
-
-      case ',':
-        token = Select(Token::COMMA);
-        break;
-
-      case '(':
-        token = Select(Token::LPAREN);
-        break;
-
-      case ')':
-        token = Select(Token::RPAREN);
-        break;
-
-      case '[':
-        token = Select(Token::LBRACK);
-        break;
-
-      case ']':
-        token = Select(Token::RBRACK);
-        break;
-
-      case '{':
-        token = Select(Token::LBRACE);
-        break;
-
-      case '}':
-        token = Select(Token::RBRACE);
-        break;
-
-      case '?':
-        token = Select(Token::CONDITIONAL);
-        break;
-
-      case '~':
-        token = Select(Token::BIT_NOT);
-        break;
-
-      default:
-        if (kIsIdentifierStart.get(c0_)) {
-          token = ScanIdentifier();
-        } else if (IsDecimalDigit(c0_)) {
-          token = ScanNumber(false);
-        } else if (SkipWhiteSpace()) {
-          token = Token::WHITESPACE;
-        } else if (c0_ < 0) {
-          token = Token::EOS;
-        } else {
-          token = Select(Token::ILLEGAL);
-        }
-        break;
-    }
-
-    // Continue scanning for tokens as long as we're just skipping
-    // whitespace.
-  } while (token == Token::WHITESPACE);
-
-  next_.location.end_pos = source_pos();
-  next_.token = token;
-}
-
-
-void Scanner::SeekForward(int pos) {
-  source_->SeekForward(pos - 1);
-  Advance();
-  // This function is only called to seek to the location
-  // of the end of a function (at the "}" token). It doesn't matter
-  // whether there was a line terminator in the part we skip.
-  has_line_terminator_before_next_ = false;
-  Scan();
-}
-
-
-uc32 Scanner::ScanHexEscape(uc32 c, int length) {
-  ASSERT(length <= 4);  // prevent overflow
-
-  uc32 digits[4];
-  uc32 x = 0;
-  for (int i = 0; i < length; i++) {
-    digits[i] = c0_;
-    int d = HexValue(c0_);
-    if (d < 0) {
-      // According to ECMA-262, 3rd, 7.8.4, page 18, these hex escapes
-      // should be illegal, but other JS VMs just return the
-      // non-escaped version of the original character.
-
-      // Push back digits read, except the last one (in c0_).
-      for (int j = i-1; j >= 0; j--) {
-        PushBack(digits[j]);
-      }
-      // Notice: No handling of error - treat it as "\u"->"u".
-      return c;
-    }
-    x = x * 16 + d;
-    Advance();
-  }
-
-  return x;
-}
-
-
-// Octal escapes of the forms '\0xx' and '\xxx' are not a part of
-// ECMA-262. Other JS VMs support them.
-uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
-  uc32 x = c - '0';
-  for (int i = 0; i < length; i++) {
-    int d = c0_ - '0';
-    if (d < 0 || d > 7) break;
-    int nx = x * 8 + d;
-    if (nx >= 256) break;
-    x = nx;
-    Advance();
-  }
-  return x;
-}
-
-
-void Scanner::ScanEscape() {
-  uc32 c = c0_;
-  Advance();
-
-  // Skip escaped newlines.
-  if (kIsLineTerminator.get(c)) {
-    // Allow CR+LF newlines in multiline string literals.
-    if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance();
-    // Allow LF+CR newlines in multiline string literals.
-    if (IsLineFeed(c) && IsCarriageReturn(c0_)) Advance();
-    return;
-  }
-
-  switch (c) {
-    case '\'':  // fall through
-    case '"' :  // fall through
-    case '\\': break;
-    case 'b' : c = '\b'; break;
-    case 'f' : c = '\f'; break;
-    case 'n' : c = '\n'; break;
-    case 'r' : c = '\r'; break;
-    case 't' : c = '\t'; break;
-    case 'u' : c = ScanHexEscape(c, 4); break;
-    case 'v' : c = '\v'; break;
-    case 'x' : c = ScanHexEscape(c, 2); break;
-    case '0' :  // fall through
-    case '1' :  // fall through
-    case '2' :  // fall through
-    case '3' :  // fall through
-    case '4' :  // fall through
-    case '5' :  // fall through
-    case '6' :  // fall through
-    case '7' : c = ScanOctalEscape(c, 2); break;
-  }
-
-  // According to ECMA-262, 3rd, 7.8.4 (p 18ff) these
-  // should be illegal, but they are commonly handled
-  // as non-escaped characters by JS VMs.
-  AddChar(c);
-}
-
-
-Token::Value Scanner::ScanString() {
-  uc32 quote = c0_;
-  Advance();  // consume quote
-
-  LiteralScope literal(this);
-  while (c0_ != quote && c0_ >= 0 && !kIsLineTerminator.get(c0_)) {
-    uc32 c = c0_;
-    Advance();
-    if (c == '\\') {
-      if (c0_ < 0) return Token::ILLEGAL;
-      ScanEscape();
-    } else {
-      AddChar(c);
-    }
-  }
-  if (c0_ != quote) return Token::ILLEGAL;
-  literal.Complete();
-
-  Advance();  // consume quote
-  return Token::STRING;
-}
-
-
-Token::Value Scanner::Select(Token::Value tok) {
-  Advance();
-  return tok;
-}
-
-
-Token::Value Scanner::Select(uc32 next, Token::Value then, Token::Value else_) {
-  Advance();
-  if (c0_ == next) {
-    Advance();
-    return then;
-  } else {
-    return else_;
-  }
-}
-
-
-// Returns true if any decimal digits were scanned, returns false otherwise.
-void Scanner::ScanDecimalDigits() {
-  while (IsDecimalDigit(c0_))
-    AddCharAdvance();
-}
-
-
-Token::Value Scanner::ScanNumber(bool seen_period) {
-  ASSERT(IsDecimalDigit(c0_));  // the first digit of the number or the fraction
-
-  enum { DECIMAL, HEX, OCTAL } kind = DECIMAL;
-
-  LiteralScope literal(this);
-  if (seen_period) {
-    // we have already seen a decimal point of the float
-    AddChar('.');
-    ScanDecimalDigits();  // we know we have at least one digit
-
-  } else {
-    // if the first character is '0' we must check for octals and hex
-    if (c0_ == '0') {
-      AddCharAdvance();
-
-      // either 0, 0exxx, 0Exxx, 0.xxx, an octal number, or a hex number
-      if (c0_ == 'x' || c0_ == 'X') {
-        // hex number
-        kind = HEX;
-        AddCharAdvance();
-        if (!IsHexDigit(c0_)) {
-          // we must have at least one hex digit after 'x'/'X'
-          return Token::ILLEGAL;
-        }
-        while (IsHexDigit(c0_)) {
-          AddCharAdvance();
-        }
-      } else if ('0' <= c0_ && c0_ <= '7') {
-        // (possible) octal number
-        kind = OCTAL;
-        while (true) {
-          if (c0_ == '8' || c0_ == '9') {
-            kind = DECIMAL;
-            break;
-          }
-          if (c0_  < '0' || '7'  < c0_) break;
-          AddCharAdvance();
-        }
-      }
-    }
-
-    // Parse decimal digits and allow trailing fractional part.
-    if (kind == DECIMAL) {
-      ScanDecimalDigits();  // optional
-      if (c0_ == '.') {
-        AddCharAdvance();
-        ScanDecimalDigits();  // optional
-      }
-    }
-  }
-
-  // scan exponent, if any
-  if (c0_ == 'e' || c0_ == 'E') {
-    ASSERT(kind != HEX);  // 'e'/'E' must be scanned as part of the hex number
-    if (kind == OCTAL) return Token::ILLEGAL;  // no exponent for octals allowed
-    // scan exponent
-    AddCharAdvance();
-    if (c0_ == '+' || c0_ == '-')
-      AddCharAdvance();
-    if (!IsDecimalDigit(c0_)) {
-      // we must have at least one decimal digit after 'e'/'E'
-      return Token::ILLEGAL;
-    }
-    ScanDecimalDigits();
-  }
-
-  // The source character immediately following a numeric literal must
-  // not be an identifier start or a decimal digit; see ECMA-262
-  // section 7.8.3, page 17 (note that we read only one decimal digit
-  // if the value is 0).
-  if (IsDecimalDigit(c0_) || kIsIdentifierStart.get(c0_))
-    return Token::ILLEGAL;
-
-  literal.Complete();
-
-  return Token::NUMBER;
-}
-
-
-uc32 Scanner::ScanIdentifierUnicodeEscape() {
-  Advance();
-  if (c0_ != 'u') return unibrow::Utf8::kBadChar;
-  Advance();
-  uc32 c = ScanHexEscape('u', 4);
-  // We do not allow a unicode escape sequence to start another
-  // unicode escape sequence.
-  if (c == '\\') return unibrow::Utf8::kBadChar;
-  return c;
-}
-
-
-Token::Value Scanner::ScanIdentifier() {
-  ASSERT(kIsIdentifierStart.get(c0_));
-
-  LiteralScope literal(this);
-  KeywordMatcher keyword_match;
-
-  // Scan identifier start character.
-  if (c0_ == '\\') {
-    uc32 c = ScanIdentifierUnicodeEscape();
-    // Only allow legal identifier start characters.
-    if (!kIsIdentifierStart.get(c)) return Token::ILLEGAL;
-    AddChar(c);
-    keyword_match.Fail();
-  } else {
-    AddChar(c0_);
-    keyword_match.AddChar(c0_);
-    Advance();
-  }
-
-  // Scan the rest of the identifier characters.
-  while (kIsIdentifierPart.get(c0_)) {
-    if (c0_ == '\\') {
-      uc32 c = ScanIdentifierUnicodeEscape();
-      // Only allow legal identifier part characters.
-      if (!kIsIdentifierPart.get(c)) return Token::ILLEGAL;
-      AddChar(c);
-      keyword_match.Fail();
-    } else {
-      AddChar(c0_);
-      keyword_match.AddChar(c0_);
-      Advance();
-    }
-  }
-  literal.Complete();
-
-  return keyword_match.token();
-}
-
-
-
-bool Scanner::IsIdentifier(unibrow::CharacterStream* buffer) {
-  // Checks whether the buffer contains an identifier (no escape).
-  if (!buffer->has_more()) return false;
-  if (!kIsIdentifierStart.get(buffer->GetNext())) return false;
-  while (buffer->has_more()) {
-    if (!kIsIdentifierPart.get(buffer->GetNext())) return false;
-  }
-  return true;
-}
-
-
-bool Scanner::ScanRegExpPattern(bool seen_equal) {
-  // Scan: ('/' | '/=') RegularExpressionBody '/' RegularExpressionFlags
-  bool in_character_class = false;
-
-  // Previous token is either '/' or '/=', in the second case, the
-  // pattern starts at =.
-  next_.location.beg_pos = source_pos() - (seen_equal ? 2 : 1);
-  next_.location.end_pos = source_pos() - (seen_equal ? 1 : 0);
-
-  // Scan regular expression body: According to ECMA-262, 3rd, 7.8.5,
-  // the scanner should pass uninterpreted bodies to the RegExp
-  // constructor.
-  LiteralScope literal(this);
-  if (seen_equal)
-    AddChar('=');
-
-  while (c0_ != '/' || in_character_class) {
-    if (kIsLineTerminator.get(c0_) || c0_ < 0) return false;
-    if (c0_ == '\\') {  // escaped character
-      AddCharAdvance();
-      if (kIsLineTerminator.get(c0_) || c0_ < 0) return false;
-      AddCharAdvance();
-    } else {  // unescaped character
-      if (c0_ == '[') in_character_class = true;
-      if (c0_ == ']') in_character_class = false;
-      AddCharAdvance();
-    }
-  }
-  Advance();  // consume '/'
-
-  literal.Complete();
-
-  return true;
-}
-
-bool Scanner::ScanRegExpFlags() {
-  // Scan regular expression flags.
-  LiteralScope literal(this);
-  while (kIsIdentifierPart.get(c0_)) {
-    if (c0_ == '\\') {
-      uc32 c = ScanIdentifierUnicodeEscape();
-      if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) {
-        // We allow any escaped character, unlike the restriction on
-        // IdentifierPart when it is used to build an IdentifierName.
-        AddChar(c);
-        continue;
-      }
-    }
-    AddCharAdvance();
-  }
-  literal.Complete();
-
-  next_.location.end_pos = source_pos() - 1;
-  return true;
-}
 
 } }  // namespace v8::internal
diff --git a/src/scanner.h b/src/scanner.h
index 1f49fd0..acb9b47 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -35,74 +35,6 @@
 namespace v8 {
 namespace internal {
 
-
-class UTF8Buffer {
- public:
-  UTF8Buffer();
-  ~UTF8Buffer();
-
-  inline void AddChar(uc32 c) {
-    if (static_cast<unsigned>(c) <= unibrow::Utf8::kMaxOneByteChar) {
-      buffer_.Add(static_cast<char>(c));
-    } else {
-      AddCharSlow(c);
-    }
-  }
-
-  void StartLiteral() {
-    buffer_.StartSequence();
-  }
-
-  Vector<const char> EndLiteral() {
-    buffer_.Add(kEndMarker);
-    Vector<char> sequence = buffer_.EndSequence();
-    return Vector<const char>(sequence.start(), sequence.length());
-  }
-
-  void DropLiteral() {
-    buffer_.DropSequence();
-  }
-
-  void Reset() {
-    buffer_.Reset();
-  }
-
-  // The end marker added after a parsed literal.
-  // Using zero allows the usage of strlen and similar functions on
-  // identifiers and numbers (but not strings, since they may contain zero
-  // bytes).
-  // TODO(lrn): Use '\xff' as end marker, since it cannot occur inside
-  // an utf-8 string. This requires changes in all places that uses
-  // str-functions on the literals, but allows a single pointer to represent
-  // the literal, even if it contains embedded zeros.
-  static const char kEndMarker = '\x00';
- private:
-  static const int kInitialCapacity = 256;
-  SequenceCollector<char, 4> buffer_;
-
-  void AddCharSlow(uc32 c);
-};
-
-
-// Interface through which the scanner reads characters from the input source.
-class UTF16Buffer {
- public:
-  UTF16Buffer();
-  virtual ~UTF16Buffer() {}
-
-  virtual void PushBack(uc32 ch) = 0;
-  // Returns a value < 0 when the buffer end is reached.
-  virtual uc32 Advance() = 0;
-  virtual void SeekForward(int pos) = 0;
-
-  int pos() const { return pos_; }
-
- protected:
-  int pos_;  // Current position in the buffer.
-  int end_;  // Position where scanning should stop (EOF).
-};
-
-
 // UTF16 buffer to read characters from a character stream.
 class CharacterStreamUTF16Buffer: public UTF16Buffer {
  public:
@@ -143,182 +75,65 @@
 };
 
 
-enum ParserLanguage { JAVASCRIPT, JSON };
-
-
-class Scanner {
+// Initializes a UTF16Buffer as input stream, using one of a number
+// of strategies depending on the available character sources.
+class StreamInitializer {
  public:
-  typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder;
+  UTF16Buffer* Init(Handle<String> source,
+                    unibrow::CharacterStream* stream,
+                    int start_position,
+                    int end_position);
+ private:
+  // Different UTF16 buffers used to pull characters from. Based on input one of
+  // these will be initialized as the actual data source.
+  CharacterStreamUTF16Buffer char_stream_buffer_;
+  ExternalStringUTF16Buffer<ExternalTwoByteString, uint16_t>
+      two_byte_string_buffer_;
+  ExternalStringUTF16Buffer<ExternalAsciiString, char> ascii_string_buffer_;
 
-  class LiteralScope {
-   public:
-    explicit LiteralScope(Scanner* self);
-    ~LiteralScope();
-    void Complete();
+  // Used to convert the source string into a character stream when a stream
+  // is not passed to the scanner.
+  SafeStringInputBuffer safe_string_input_buffer_;
+};
 
-   private:
-    Scanner* scanner_;
-    bool complete_;
-  };
+// ----------------------------------------------------------------------------
+// V8JavaScriptScanner
+// JavaScript scanner getting its input from either a V8 String or a unicode
+// CharacterStream.
 
-  Scanner();
+class V8JavaScriptScanner : public JavaScriptScanner {
+ public:
+  V8JavaScriptScanner() {}
+
+  Token::Value NextCheckStack();
 
   // Initialize the Scanner to scan source.
-  void Initialize(Handle<String> source,
-                  ParserLanguage language);
+  void Initialize(Handle<String> source, int literal_flags = kAllLiterals);
   void Initialize(Handle<String> source,
                   unibrow::CharacterStream* stream,
-                  ParserLanguage language);
+                  int literal_flags = kAllLiterals);
   void Initialize(Handle<String> source,
                   int start_position, int end_position,
-                  ParserLanguage language);
+                  int literal_flags = kAllLiterals);
+
+ protected:
+  StreamInitializer stream_initializer_;
+};
+
+
+class JsonScanner : public Scanner {
+ public:
+  JsonScanner();
+
+  // Initialize the Scanner to scan source.
+  void Initialize(Handle<String> source);
 
   // Returns the next token.
   Token::Value Next();
 
-  // Returns the current token again.
-  Token::Value current_token() { return current_.token; }
-
-  // One token look-ahead (past the token returned by Next()).
-  Token::Value peek() const { return next_.token; }
-
-  // Returns true if there was a line terminator before the peek'ed token.
-  bool has_line_terminator_before_next() const {
-    return has_line_terminator_before_next_;
-  }
-
-  struct Location {
-    Location(int b, int e) : beg_pos(b), end_pos(e) { }
-    Location() : beg_pos(0), end_pos(0) { }
-    int beg_pos;
-    int end_pos;
-  };
-
-  // Returns the location information for the current token
-  // (the token returned by Next()).
-  Location location() const { return current_.location; }
-  Location peek_location() const { return next_.location; }
-
-  // Returns the literal string, if any, for the current token (the
-  // token returned by Next()). The string is 0-terminated and in
-  // UTF-8 format; they may contain 0-characters. Literal strings are
-  // collected for identifiers, strings, and numbers.
-  // These functions only give the correct result if the literal
-  // was scanned between calls to StartLiteral() and TerminateLiteral().
-  const char* literal_string() const {
-    return current_.literal_chars.start();
-  }
-
-  int literal_length() const {
-    // Excluding terminal '\x00' added by TerminateLiteral().
-    return current_.literal_chars.length() - 1;
-  }
-
-  Vector<const char> literal() const {
-    return Vector<const char>(literal_string(), literal_length());
-  }
-
-  // Returns the literal string for the next token (the token that
-  // would be returned if Next() were called).
-  const char* next_literal_string() const {
-    return next_.literal_chars.start();
-  }
-
-
-  // Returns the length of the next token (that would be returned if
-  // Next() were called).
-  int next_literal_length() const {
-    // Excluding terminal '\x00' added by TerminateLiteral().
-    return next_.literal_chars.length() - 1;
-  }
-
-  Vector<const char> next_literal() const {
-    return Vector<const char>(next_literal_string(), next_literal_length());
-  }
-
-  // Scans the input as a regular expression pattern, previous
-  // character(s) must be /(=). Returns true if a pattern is scanned.
-  bool ScanRegExpPattern(bool seen_equal);
-  // Returns true if regexp flags are scanned (always since flags can
-  // be empty).
-  bool ScanRegExpFlags();
-
-  // Seek forward to the given position.  This operation does not
-  // work in general, for instance when there are pushed back
-  // characters, but works for seeking forward until simple delimiter
-  // tokens, which is what it is used for.
-  void SeekForward(int pos);
-
-  bool stack_overflow() { return stack_overflow_; }
-
-  static StaticResource<Utf8Decoder>* utf8_decoder() { return &utf8_decoder_; }
-
-  // Tells whether the buffer contains an identifier (no escapes).
-  // Used for checking if a property name is an identifier.
-  static bool IsIdentifier(unibrow::CharacterStream* buffer);
-
-  static unibrow::Predicate<IdentifierStart, 128> kIsIdentifierStart;
-  static unibrow::Predicate<IdentifierPart, 128> kIsIdentifierPart;
-  static unibrow::Predicate<unibrow::LineTerminator, 128> kIsLineTerminator;
-  static unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;
-
-  static const int kCharacterLookaheadBufferSize = 1;
-  static const int kNoEndPosition = 1;
-
- private:
-  // The current and look-ahead token.
-  struct TokenDesc {
-    Token::Value token;
-    Location location;
-    Vector<const char> literal_chars;
-  };
-
-  void Init(Handle<String> source,
-            unibrow::CharacterStream* stream,
-            int start_position, int end_position,
-            ParserLanguage language);
-
-  // Literal buffer support
-  inline void StartLiteral();
-  inline void AddChar(uc32 ch);
-  inline void AddCharAdvance();
-  inline void TerminateLiteral();
-  // Stops scanning of a literal, e.g., due to an encountered error.
-  inline void DropLiteral();
-
-  // Low-level scanning support.
-  void Advance() { c0_ = source_->Advance(); }
-  void PushBack(uc32 ch) {
-    source_->PushBack(ch);
-    c0_ = ch;
-  }
-
-  bool SkipWhiteSpace() {
-    if (is_parsing_json_) {
-      return SkipJsonWhiteSpace();
-    } else {
-      return SkipJavaScriptWhiteSpace();
-    }
-  }
-
-  bool SkipJavaScriptWhiteSpace();
+ protected:
+  // Skip past JSON whitespace (only space, tab, newline and carrige-return).
   bool SkipJsonWhiteSpace();
-  Token::Value SkipSingleLineComment();
-  Token::Value SkipMultiLineComment();
-
-  inline Token::Value Select(Token::Value tok);
-  inline Token::Value Select(uc32 next, Token::Value then, Token::Value else_);
-
-  inline void Scan() {
-    if (is_parsing_json_) {
-      ScanJson();
-    } else {
-      ScanJavaScript();
-    }
-  }
-
-  // Scans a single JavaScript token.
-  void ScanJavaScript();
 
   // Scan a single JSON token. The JSON lexical grammar is specified in the
   // ECMAScript 5 standard, section 15.12.1.1.
@@ -347,56 +162,59 @@
   // JSONNullLiteral).
   Token::Value ScanJsonIdentifier(const char* text, Token::Value token);
 
-  void ScanDecimalDigits();
-  Token::Value ScanNumber(bool seen_period);
-  Token::Value ScanIdentifier();
-  uc32 ScanHexEscape(uc32 c, int length);
-  uc32 ScanOctalEscape(uc32 c, int length);
-  void ScanEscape();
-  Token::Value ScanString();
-
-  // Scans a possible HTML comment -- begins with '<!'.
-  Token::Value ScanHtmlComment();
-
-  // Return the current source position.
-  int source_pos() {
-    return source_->pos() - kCharacterLookaheadBufferSize;
-  }
-
-  // Decodes a unicode escape-sequence which is part of an identifier.
-  // If the escape sequence cannot be decoded the result is kBadRune.
-  uc32 ScanIdentifierUnicodeEscape();
-
-  TokenDesc current_;  // desc for current token (as returned by Next())
-  TokenDesc next_;     // desc for next token (one token look-ahead)
-  bool has_line_terminator_before_next_;
-  bool is_parsing_json_;
-
-  // Different UTF16 buffers used to pull characters from. Based on input one of
-  // these will be initialized as the actual data source.
-  CharacterStreamUTF16Buffer char_stream_buffer_;
-  ExternalStringUTF16Buffer<ExternalTwoByteString, uint16_t>
-      two_byte_string_buffer_;
-  ExternalStringUTF16Buffer<ExternalAsciiString, char> ascii_string_buffer_;
-
-  // Source. Will point to one of the buffers declared above.
-  UTF16Buffer* source_;
-
-  // Used to convert the source string into a character stream when a stream
-  // is not passed to the scanner.
-  SafeStringInputBuffer safe_string_input_buffer_;
-
-  // Buffer to hold literal values (identifiers, strings, numbers)
-  // using '\x00'-terminated UTF-8 encoding. Handles allocation internally.
-  UTF8Buffer literal_buffer_;
-
-  bool stack_overflow_;
-  static StaticResource<Utf8Decoder> utf8_decoder_;
-
-  // One Unicode character look-ahead; c0_ < 0 at the end of the input.
-  uc32 c0_;
+  StreamInitializer stream_initializer_;
 };
 
+
+// ExternalStringUTF16Buffer
+template <typename StringType, typename CharType>
+ExternalStringUTF16Buffer<StringType, CharType>::ExternalStringUTF16Buffer()
+    : raw_data_(NULL) { }
+
+
+template <typename StringType, typename CharType>
+void ExternalStringUTF16Buffer<StringType, CharType>::Initialize(
+     Handle<StringType> data,
+     int start_position,
+     int end_position) {
+  ASSERT(!data.is_null());
+  raw_data_ = data->resource()->data();
+
+  ASSERT(end_position <= data->length());
+  if (start_position > 0) {
+    SeekForward(start_position);
+  }
+  end_ =
+      end_position != kNoEndPosition ? end_position : data->length();
+}
+
+
+template <typename StringType, typename CharType>
+uc32 ExternalStringUTF16Buffer<StringType, CharType>::Advance() {
+  if (pos_ < end_) {
+    return raw_data_[pos_++];
+  } else {
+    // note: currently the following increment is necessary to avoid a
+    // test-parser problem!
+    pos_++;
+    return static_cast<uc32>(-1);
+  }
+}
+
+
+template <typename StringType, typename CharType>
+void ExternalStringUTF16Buffer<StringType, CharType>::PushBack(uc32 ch) {
+  pos_--;
+  ASSERT(pos_ >= Scanner::kCharacterLookaheadBufferSize);
+  ASSERT(raw_data_[pos_ - Scanner::kCharacterLookaheadBufferSize] == ch);
+}
+
+
+template <typename StringType, typename CharType>
+void ExternalStringUTF16Buffer<StringType, CharType>::SeekForward(int pos) {
+  pos_ = pos;
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_SCANNER_H_
diff --git a/src/serialize.cc b/src/serialize.cc
index 763c12f..15fed44 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -290,10 +290,6 @@
     Add(Top::get_address_from_id((Top::AddressId)i), TOP_ADDRESS, i, chars);
   }
 
-  // Extensions
-  Add(FUNCTION_ADDR(GCExtension::GC), EXTENSION, 1,
-      "GCExtension::GC");
-
   // Accessors
 #define ACCESSOR_DESCRIPTOR_DECLARATION(name) \
   Add((Address)&Accessors::name, \
diff --git a/src/spaces.cc b/src/spaces.cc
index 2f3e41a..239c9cd 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -1898,6 +1898,18 @@
 }
 
 
+void OldSpaceFreeList::MarkNodes() {
+  for (int i = 0; i < kFreeListsLength; i++) {
+    Address cur_addr = free_[i].head_node_;
+    while (cur_addr != NULL) {
+      FreeListNode* cur_node = FreeListNode::FromAddress(cur_addr);
+      cur_addr = cur_node->next();
+      cur_node->SetMark();
+    }
+  }
+}
+
+
 #ifdef DEBUG
 bool OldSpaceFreeList::Contains(FreeListNode* node) {
   for (int i = 0; i < kFreeListsLength; i++) {
@@ -1957,6 +1969,16 @@
 }
 
 
+void FixedSizeFreeList::MarkNodes() {
+  Address cur_addr = head_;
+  while (cur_addr != NULL && cur_addr != tail_) {
+    FreeListNode* cur_node = FreeListNode::FromAddress(cur_addr);
+    cur_addr = cur_node->next();
+    cur_node->SetMark();
+  }
+}
+
+
 // -----------------------------------------------------------------------------
 // OldSpace implementation
 
@@ -2711,13 +2733,15 @@
     : Space(id, NOT_EXECUTABLE),  // Managed on a per-allocation basis
       first_chunk_(NULL),
       size_(0),
-      page_count_(0) {}
+      page_count_(0),
+      objects_size_(0) {}
 
 
 bool LargeObjectSpace::Setup() {
   first_chunk_ = NULL;
   size_ = 0;
   page_count_ = 0;
+  objects_size_ = 0;
   return true;
 }
 
@@ -2740,6 +2764,7 @@
 
   size_ = 0;
   page_count_ = 0;
+  objects_size_ = 0;
 }
 
 
@@ -2786,6 +2811,7 @@
   }
 
   size_ += static_cast<int>(chunk_size);
+  objects_size_ += requested_size;
   page_count_++;
   chunk->set_next(first_chunk_);
   chunk->set_size(chunk_size);
@@ -2948,6 +2974,7 @@
       // Free the chunk.
       MarkCompactCollector::ReportDeleteIfNeeded(object);
       size_ -= static_cast<int>(chunk_size);
+      objects_size_ -= object->Size();
       page_count_--;
       ObjectSpace space = kObjectSpaceLoSpace;
       if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace;
@@ -3052,7 +3079,8 @@
     CollectHistogramInfo(obj);
   }
 
-  PrintF("  number of objects %d\n", num_objects);
+  PrintF("  number of objects %d, "
+         "size of objects %" V8_PTR_PREFIX "d\n", num_objects, objects_size_);
   if (num_objects > 0) ReportHistogram(false);
 }
 
diff --git a/src/spaces.h b/src/spaces.h
index 0c10d2c..60068c3 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -371,8 +371,13 @@
   // Identity used in error reporting.
   AllocationSpace identity() { return id_; }
 
+  // Returns allocated size.
   virtual intptr_t Size() = 0;
 
+  // Returns size of objects. Can differ from the allocated size
+  // (e.g. see LargeObjectSpace).
+  virtual intptr_t SizeOfObjects() { return Size(); }
+
 #ifdef ENABLE_HEAP_PROTECTION
   // Protect/unprotect the space by marking it read-only/writable.
   virtual void Protect() = 0;
@@ -591,7 +596,7 @@
   static intptr_t Size() { return size_; }
 
   // Returns the maximum available executable bytes of heaps.
-  static int AvailableExecutable() {
+  static intptr_t AvailableExecutable() {
     if (capacity_executable_ < size_executable_) return 0;
     return capacity_executable_ - size_executable_;
   }
@@ -1715,6 +1720,8 @@
   // 'wasted_bytes'.  The size should be a non-zero multiple of the word size.
   MUST_USE_RESULT MaybeObject* Allocate(int size_in_bytes, int* wasted_bytes);
 
+  void MarkNodes();
+
  private:
   // The size range of blocks, in bytes. (Smaller allocations are allowed, but
   // will always result in waste.)
@@ -1813,6 +1820,8 @@
   // A failure is returned if no block is available.
   MUST_USE_RESULT MaybeObject* Allocate();
 
+  void MarkNodes();
+
  private:
   // Available bytes on the free list.
   intptr_t available_;
@@ -1884,6 +1893,8 @@
 
   virtual void PutRestOfCurrentPageOnFreeList(Page* current_page);
 
+  void MarkFreeListNodes() { free_list_.MarkNodes(); }
+
 #ifdef DEBUG
   // Reports statistics for the space
   void ReportStatistics();
@@ -1951,6 +1962,9 @@
   virtual void DeallocateBlock(Address start,
                                int size_in_bytes,
                                bool add_to_freelist);
+
+  void MarkFreeListNodes() { free_list_.MarkNodes(); }
+
 #ifdef DEBUG
   // Reports statistic info of the space
   void ReportStatistics();
@@ -2191,6 +2205,10 @@
     return size_;
   }
 
+  virtual intptr_t SizeOfObjects() {
+    return objects_size_;
+  }
+
   int PageCount() {
     return page_count_;
   }
@@ -2242,7 +2260,7 @@
   LargeObjectChunk* first_chunk_;
   intptr_t size_;  // allocated bytes
   int page_count_;  // number of chunks
-
+  intptr_t objects_size_;  // size of objects
 
   // Shared implementation of AllocateRaw, AllocateRawCode and
   // AllocateRawFixedArray.
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/strtod.cc b/src/strtod.cc
index 0523d88..cedbff9 100644
--- a/src/strtod.cc
+++ b/src/strtod.cc
@@ -422,9 +422,9 @@
     int significant_exponent;
     TrimToMaxSignificantDigits(trimmed, exponent,
                                significant_buffer, &significant_exponent);
-    trimmed =
-        Vector<const char>(significant_buffer, kMaxSignificantDecimalDigits);
-    exponent = significant_exponent;
+    return Strtod(Vector<const char>(significant_buffer,
+                                     kMaxSignificantDecimalDigits),
+                  significant_exponent);
   }
   if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY;
   if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0;
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index e794f09..5cc009f 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -820,6 +820,34 @@
 }
 
 
+Handle<Code> StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) {
+  if (in_loop == IN_LOOP) {
+    // Force the creation of the corresponding stub outside loops,
+    // because it may be used when clearing the ICs later - it is
+    // possible for a series of IC transitions to lose the in-loop
+    // information, and the IC clearing code can't generate a stub
+    // that it needs so we need to ensure it is generated already.
+    ComputeCallInitialize(argc, NOT_IN_LOOP);
+  }
+  CALL_HEAP_FUNCTION(ComputeCallInitialize(argc, in_loop, Code::CALL_IC), Code);
+}
+
+
+Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc,
+                                                   InLoopFlag in_loop) {
+  if (in_loop == IN_LOOP) {
+    // Force the creation of the corresponding stub outside loops,
+    // because it may be used when clearing the ICs later - it is
+    // possible for a series of IC transitions to lose the in-loop
+    // information, and the IC clearing code can't generate a stub
+    // that it needs so we need to ensure it is generated already.
+    ComputeKeyedCallInitialize(argc, NOT_IN_LOOP);
+  }
+  CALL_HEAP_FUNCTION(
+      ComputeCallInitialize(argc, in_loop, Code::KEYED_CALL_IC), Code);
+}
+
+
 MaybeObject* StubCache::ComputeCallPreMonomorphic(int argc,
                                                   InLoopFlag in_loop,
                                                   Code::Kind kind) {
@@ -932,14 +960,11 @@
 MaybeObject* LoadCallbackProperty(Arguments args) {
   ASSERT(args[0]->IsJSObject());
   ASSERT(args[1]->IsJSObject());
-  AccessorInfo* callback = AccessorInfo::cast(args[2]);
+  AccessorInfo* callback = AccessorInfo::cast(args[3]);
   Address getter_address = v8::ToCData<Address>(callback->getter());
   v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
   ASSERT(fun != NULL);
-  CustomArguments custom_args(callback->data(),
-                              JSObject::cast(args[0]),
-                              JSObject::cast(args[1]));
-  v8::AccessorInfo info(custom_args.end());
+  v8::AccessorInfo info(&args[0]);
   HandleScope scope;
   v8::Handle<v8::Value> result;
   {
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 9d947e4..cef5481 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -204,6 +204,10 @@
                                                             InLoopFlag in_loop,
                                                             Code::Kind kind);
 
+  static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
+
+  static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
+
   MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic(
       int argc,
       InLoopFlag in_loop,
@@ -736,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/third_party/dtoa/COPYING b/src/third_party/dtoa/COPYING
deleted file mode 100644
index c991754..0000000
--- a/src/third_party/dtoa/COPYING
+++ /dev/null
@@ -1,15 +0,0 @@
-The author of this software is David M. Gay.
-
-Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose without fee is hereby granted, provided that this entire
-notice is included in all copies of any software which is or includes
-a copy or modification of this software and in all copies of the
-supporting documentation for such software.
-
-THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
-IMPLIED WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES
-ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
-MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
-PURPOSE.
diff --git a/src/third_party/dtoa/dtoa.c b/src/third_party/dtoa/dtoa.c
deleted file mode 100644
index 068ed94..0000000
--- a/src/third_party/dtoa/dtoa.c
+++ /dev/null
@@ -1,3331 +0,0 @@
-/****************************************************************
- *
- * The author of this software is David M. Gay.
- *
- * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- ***************************************************************/
-
-/* Please send bug reports to David M. Gay (dmg at acm dot org,
- * with " at " changed at "@" and " dot " changed to ".").	*/
-
-/* On a machine with IEEE extended-precision registers, it is
- * necessary to specify double-precision (53-bit) rounding precision
- * before invoking strtod or dtoa.  If the machine uses (the equivalent
- * of) Intel 80x87 arithmetic, the call
- *	_control87(PC_53, MCW_PC);
- * does this with many compilers.  Whether this or another call is
- * appropriate depends on the compiler; for this to work, it may be
- * necessary to #include "float.h" or another system-dependent header
- * file.
- */
-
-/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
- *
- * This strtod returns a nearest machine number to the input decimal
- * string (or sets errno to ERANGE).  With IEEE arithmetic, ties are
- * broken by the IEEE round-even rule.  Otherwise ties are broken by
- * biased rounding (add half and chop).
- *
- * Inspired loosely by William D. Clinger's paper "How to Read Floating
- * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- *
- *	1. We only require IEEE, IBM, or VAX double-precision
- *		arithmetic (not IEEE double-extended).
- *	2. We get by with floating-point arithmetic in a case that
- *		Clinger missed -- when we're computing d * 10^n
- *		for a small integer d and the integer n is not too
- *		much larger than 22 (the maximum integer k for which
- *		we can represent 10^k exactly), we may be able to
- *		compute (d*10^k) * 10^(e-k) with just one roundoff.
- *	3. Rather than a bit-at-a-time adjustment of the binary
- *		result in the hard case, we use floating-point
- *		arithmetic to determine the adjustment to within
- *		one bit; only in really hard cases do we need to
- *		compute a second residual.
- *	4. Because of 3., we don't need a large table of powers of 10
- *		for ten-to-e (just some small tables, e.g. of 10^k
- *		for 0 <= k <= 22).
- */
-
-/*
- * #define IEEE_8087 for IEEE-arithmetic machines where the least
- *	significant byte has the lowest address.
- * #define IEEE_MC68k for IEEE-arithmetic machines where the most
- *	significant byte has the lowest address.
- * #define Long int on machines with 32-bit ints and 64-bit longs.
- * #define IBM for IBM mainframe-style floating-point arithmetic.
- * #define VAX for VAX-style floating-point arithmetic (D_floating).
- * #define No_leftright to omit left-right logic in fast floating-point
- *	computation of dtoa.
- * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- *	and strtod and dtoa should round accordingly.
- * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- *	and Honor_FLT_ROUNDS is not #defined.
- * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
- *	that use extended-precision instructions to compute rounded
- *	products and quotients) with IBM.
- * #define ROUND_BIASED for IEEE-format with biased rounding.
- * #define Inaccurate_Divide for IEEE-format with correctly rounded
- *	products but inaccurate quotients, e.g., for Intel i860.
- * #define NO_LONG_LONG on machines that do not have a "long long"
- *	integer type (of >= 64 bits).  On such machines, you can
- *	#define Just_16 to store 16 bits per 32-bit Long when doing
- *	high-precision integer arithmetic.  Whether this speeds things
- *	up or slows things down depends on the machine and the number
- *	being converted.  If long long is available and the name is
- *	something other than "long long", #define Llong to be the name,
- *	and if "unsigned Llong" does not work as an unsigned version of
- *	Llong, #define #ULLong to be the corresponding unsigned type.
- * #define KR_headers for old-style C function headers.
- * #define Bad_float_h if your system lacks a float.h or if it does not
- *	define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
- *	FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
- * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
- *	if memory is available and otherwise does something you deem
- *	appropriate.  If MALLOC is undefined, malloc will be invoked
- *	directly -- and assumed always to succeed.
- * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
- *	memory allocations from a private pool of memory when possible.
- *	When used, the private pool is PRIVATE_MEM bytes long:  2304 bytes,
- *	unless #defined to be a different length.  This default length
- *	suffices to get rid of MALLOC calls except for unusual cases,
- *	such as decimal-to-binary conversion of a very long string of
- *	digits.  The longest string dtoa can return is about 751 bytes
- *	long.  For conversions by strtod of strings of 800 digits and
- *	all dtoa conversions in single-threaded executions with 8-byte
- *	pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
- *	pointers, PRIVATE_MEM >= 7112 appears adequate.
- * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
- *	Infinity and NaN (case insensitively).  On some systems (e.g.,
- *	some HP systems), it may be necessary to #define NAN_WORD0
- *	appropriately -- to the most significant word of a quiet NaN.
- *	(On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
- *	When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
- *	strtod also accepts (case insensitively) strings of the form
- *	NaN(x), where x is a string of hexadecimal digits and spaces;
- *	if there is only one string of hexadecimal digits, it is taken
- *	for the 52 fraction bits of the resulting NaN; if there are two
- *	or more strings of hex digits, the first is for the high 20 bits,
- *	the second and subsequent for the low 32 bits, with intervening
- *	white space ignored; but if this results in none of the 52
- *	fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
- *	and NAN_WORD1 are used instead.
- * #define MULTIPLE_THREADS if the system offers preemptively scheduled
- *	multiple threads.  In this case, you must provide (or suitably
- *	#define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
- *	by FREE_DTOA_LOCK(n) for n = 0 or 1.  (The second lock, accessed
- *	in pow5mult, ensures lazy evaluation of only one copy of high
- *	powers of 5; omitting this lock would introduce a small
- *	probability of wasting memory, but would otherwise be harmless.)
- *	You must also invoke freedtoa(s) to free the value s returned by
- *	dtoa.  You may do so whether or not MULTIPLE_THREADS is #defined.
- * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
- *	avoids underflows on inputs whose result does not underflow.
- *	If you #define NO_IEEE_Scale on a machine that uses IEEE-format
- *	floating-point numbers and flushes underflows to zero rather
- *	than implementing gradual underflow, then you must also #define
- *	Sudden_Underflow.
- * #define YES_ALIAS to permit aliasing certain double values with
- *	arrays of ULongs.  This leads to slightly better code with
- *	some compilers and was always used prior to 19990916, but it
- *	is not strictly legal and can cause trouble with aggressively
- *	optimizing compilers (e.g., gcc 2.95.1 under -O2).
- * #define USE_LOCALE to use the current locale's decimal_point value.
- * #define SET_INEXACT if IEEE arithmetic is being used and extra
- *	computation should be done to set the inexact flag when the
- *	result is inexact and avoid setting inexact when the result
- *	is exact.  In this case, dtoa.c must be compiled in
- *	an environment, perhaps provided by #include "dtoa.c" in a
- *	suitable wrapper, that defines two functions,
- *		int get_inexact(void);
- *		void clear_inexact(void);
- *	such that get_inexact() returns a nonzero value if the
- *	inexact bit is already set, and clear_inexact() sets the
- *	inexact bit to 0.  When SET_INEXACT is #defined, strtod
- *	also does extra computations to set the underflow and overflow
- *	flags when appropriate (i.e., when the result is tiny and
- *	inexact or when it is a numeric value rounded to +-infinity).
- * #define NO_ERRNO if strtod should not assign errno = ERANGE when
- *	the result overflows to +-Infinity or underflows to 0.
- */
-
-#ifndef Long
-#if __LP64__
-#define Long int
-#else
-#define Long long
-#endif
-#endif
-#ifndef ULong
-typedef unsigned Long ULong;
-#endif
-
-#ifdef DEBUG
-#include "stdio.h"
-#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
-#endif
-
-#include "stdlib.h"
-#include "string.h"
-
-#ifdef USE_LOCALE
-#include "locale.h"
-#endif
-
-#ifdef MALLOC
-#ifdef KR_headers
-extern char *MALLOC();
-#else
-extern void *MALLOC(size_t);
-#endif
-#else
-#define MALLOC malloc
-#endif
-
-#ifndef Omit_Private_Memory
-#ifndef PRIVATE_MEM
-#define PRIVATE_MEM 2304
-#endif
-#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
-static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
-#endif
-
-#undef IEEE_Arith
-#undef Avoid_Underflow
-#ifdef IEEE_MC68k
-#define IEEE_Arith
-#endif
-#ifdef IEEE_8087
-#define IEEE_Arith
-#endif
-
-#include "errno.h"
-
-#ifdef Bad_float_h
-
-#ifdef IEEE_Arith
-#define DBL_DIG 15
-#define DBL_MAX_10_EXP 308
-#define DBL_MAX_EXP 1024
-#define FLT_RADIX 2
-#endif /*IEEE_Arith*/
-
-#ifdef IBM
-#define DBL_DIG 16
-#define DBL_MAX_10_EXP 75
-#define DBL_MAX_EXP 63
-#define FLT_RADIX 16
-#define DBL_MAX 7.2370055773322621e+75
-#endif
-
-#ifdef VAX
-#define DBL_DIG 16
-#define DBL_MAX_10_EXP 38
-#define DBL_MAX_EXP 127
-#define FLT_RADIX 2
-#define DBL_MAX 1.7014118346046923e+38
-#endif
-
-#ifndef LONG_MAX
-#define LONG_MAX 2147483647
-#endif
-
-#else /* ifndef Bad_float_h */
-#include "float.h"
-#endif /* Bad_float_h */
-
-#ifndef __MATH_H__
-#include "math.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef CONST
-#ifdef KR_headers
-#define CONST /* blank */
-#else
-#define CONST const
-#endif
-#endif
-
-#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
-Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
-#endif
-
-typedef union { double d; ULong L[2]; } U;
-
-#ifdef IEEE_8087
-#define word0(x) (x).L[1]
-#define word1(x) (x).L[0]
-#else
-#define word0(x) (x).L[0]
-#define word1(x) (x).L[1]
-#endif
-#define dval(x) (x).d
-
-/* The following definition of Storeinc is appropriate for MIPS processors.
- * An alternative that might be better on some machines is
- * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
- */
-#if defined(IEEE_8087) + defined(VAX)
-#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
-((unsigned short *)a)[0] = (unsigned short)c, a++)
-#else
-#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
-((unsigned short *)a)[1] = (unsigned short)c, a++)
-#endif
-
-/* #define P DBL_MANT_DIG */
-/* Ten_pmax = floor(P*log(2)/log(5)) */
-/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
-/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
-/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
-
-#ifdef IEEE_Arith
-#define Exp_shift  20
-#define Exp_shift1 20
-#define Exp_msk1    0x100000
-#define Exp_msk11   0x100000
-#define Exp_mask  0x7ff00000
-#define P 53
-#define Bias 1023
-#define Emin (-1022)
-#define Exp_1  0x3ff00000
-#define Exp_11 0x3ff00000
-#define Ebits 11
-#define Frac_mask  0xfffff
-#define Frac_mask1 0xfffff
-#define Ten_pmax 22
-#define Bletch 0x10
-#define Bndry_mask  0xfffff
-#define Bndry_mask1 0xfffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 1
-#define Tiny0 0
-#define Tiny1 1
-#define Quick_max 14
-#define Int_max 14
-#ifndef NO_IEEE_Scale
-#define Avoid_Underflow
-#ifdef Flush_Denorm	/* debugging option */
-#undef Sudden_Underflow
-#endif
-#endif
-
-#ifndef Flt_Rounds
-#ifdef FLT_ROUNDS
-#define Flt_Rounds FLT_ROUNDS
-#else
-#define Flt_Rounds 1
-#endif
-#endif /*Flt_Rounds*/
-
-#ifdef Honor_FLT_ROUNDS
-#define Rounding rounding
-#undef Check_FLT_ROUNDS
-#define Check_FLT_ROUNDS
-#else
-#define Rounding Flt_Rounds
-#endif
-
-#else /* ifndef IEEE_Arith */
-#undef Check_FLT_ROUNDS
-#undef Honor_FLT_ROUNDS
-#undef SET_INEXACT
-#undef  Sudden_Underflow
-#define Sudden_Underflow
-#ifdef IBM
-#undef Flt_Rounds
-#define Flt_Rounds 0
-#define Exp_shift  24
-#define Exp_shift1 24
-#define Exp_msk1   0x1000000
-#define Exp_msk11  0x1000000
-#define Exp_mask  0x7f000000
-#define P 14
-#define Bias 65
-#define Exp_1  0x41000000
-#define Exp_11 0x41000000
-#define Ebits 8	/* exponent has 7 bits, but 8 is the right value in b2d */
-#define Frac_mask  0xffffff
-#define Frac_mask1 0xffffff
-#define Bletch 4
-#define Ten_pmax 22
-#define Bndry_mask  0xefffff
-#define Bndry_mask1 0xffffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 4
-#define Tiny0 0x100000
-#define Tiny1 0
-#define Quick_max 14
-#define Int_max 15
-#else /* VAX */
-#undef Flt_Rounds
-#define Flt_Rounds 1
-#define Exp_shift  23
-#define Exp_shift1 7
-#define Exp_msk1    0x80
-#define Exp_msk11   0x800000
-#define Exp_mask  0x7f80
-#define P 56
-#define Bias 129
-#define Exp_1  0x40800000
-#define Exp_11 0x4080
-#define Ebits 8
-#define Frac_mask  0x7fffff
-#define Frac_mask1 0xffff007f
-#define Ten_pmax 24
-#define Bletch 2
-#define Bndry_mask  0xffff007f
-#define Bndry_mask1 0xffff007f
-#define LSB 0x10000
-#define Sign_bit 0x8000
-#define Log2P 1
-#define Tiny0 0x80
-#define Tiny1 0
-#define Quick_max 15
-#define Int_max 15
-#endif /* IBM, VAX */
-#endif /* IEEE_Arith */
-
-#ifndef IEEE_Arith
-#define ROUND_BIASED
-#endif
-
-#ifdef RND_PRODQUOT
-#define rounded_product(a,b) a = rnd_prod(a, b)
-#define rounded_quotient(a,b) a = rnd_quot(a, b)
-#ifdef KR_headers
-extern double rnd_prod(), rnd_quot();
-#else
-extern double rnd_prod(double, double), rnd_quot(double, double);
-#endif
-#else
-#define rounded_product(a,b) a *= b
-#define rounded_quotient(a,b) a /= b
-#endif
-
-#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
-#define Big1 0xffffffff
-
-#ifndef Pack_32
-#define Pack_32
-#endif
-
-#ifdef KR_headers
-#define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff)
-#else
-#define FFFFFFFF 0xffffffffUL
-#endif
-
-#ifdef NO_LONG_LONG
-#undef ULLong
-#ifdef Just_16
-#undef Pack_32
-/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
- * This makes some inner loops simpler and sometimes saves work
- * during multiplications, but it often seems to make things slightly
- * slower.  Hence the default is now to store 32 bits per Long.
- */
-#endif
-#else	/* long long available */
-#ifndef Llong
-#define Llong long long
-#endif
-#ifndef ULLong
-#define ULLong unsigned Llong
-#endif
-#endif /* NO_LONG_LONG */
-
-#ifndef MULTIPLE_THREADS
-#define ACQUIRE_DTOA_LOCK(n)	/*nothing*/
-#define FREE_DTOA_LOCK(n)	/*nothing*/
-#endif
-
-#define Kmax 15
-
-#ifdef __cplusplus
-extern "C" double strtod(const char *s00, char **se);
-extern "C" char *dtoa(double d, int mode, int ndigits,
-			int *decpt, int *sign, char **rve);
-#endif
-
- struct
-Bigint {
-	struct Bigint *next;
-	int k, maxwds, sign, wds;
-	ULong x[1];
-	};
-
- typedef struct Bigint Bigint;
-
- static Bigint *freelist[Kmax+1];
-
- static Bigint *
-Balloc
-#ifdef KR_headers
-	(k) int k;
-#else
-	(int k)
-#endif
-{
-	int x;
-	Bigint *rv;
-#ifndef Omit_Private_Memory
-	unsigned int len;
-#endif
-
-	ACQUIRE_DTOA_LOCK(0);
-        /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0). */
-        /* but this case seems very unlikely. */
-	if (k <= Kmax && (rv = freelist[k])) {
-		freelist[k] = rv->next;
-		}
-	else {
-		x = 1 << k;
-#ifdef Omit_Private_Memory
-		rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
-#else
-		len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
-			/sizeof(double);
-		if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
-			rv = (Bigint*)pmem_next;
-			pmem_next += len;
-			}
-		else
-			rv = (Bigint*)MALLOC(len*sizeof(double));
-#endif
-		rv->k = k;
-		rv->maxwds = x;
-		}
-	FREE_DTOA_LOCK(0);
-	rv->sign = rv->wds = 0;
-	return rv;
-	}
-
- static void
-Bfree
-#ifdef KR_headers
-	(v) Bigint *v;
-#else
-	(Bigint *v)
-#endif
-{
-	if (v) {
-                if (v->k > Kmax)
-                        free((void*)v);
-                else {
-         		ACQUIRE_DTOA_LOCK(0);
-         		v->next = freelist[v->k];
-        		freelist[v->k] = v;
-        		FREE_DTOA_LOCK(0);
-                        }
-		}
-	}
-
-#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
-y->wds*sizeof(Long) + 2*sizeof(int))
-
- static Bigint *
-multadd
-#ifdef KR_headers
-	(b, m, a) Bigint *b; int m, a;
-#else
-	(Bigint *b, int m, int a)	/* multiply by m and add a */
-#endif
-{
-	int i, wds;
-#ifdef ULLong
-	ULong *x;
-	ULLong carry, y;
-#else
-	ULong carry, *x, y;
-#ifdef Pack_32
-	ULong xi, z;
-#endif
-#endif
-	Bigint *b1;
-
-	wds = b->wds;
-	x = b->x;
-	i = 0;
-	carry = a;
-	do {
-#ifdef ULLong
-		y = *x * (ULLong)m + carry;
-		carry = y >> 32;
-		*x++ = y & FFFFFFFF;
-#else
-#ifdef Pack_32
-		xi = *x;
-		y = (xi & 0xffff) * m + carry;
-		z = (xi >> 16) * m + (y >> 16);
-		carry = z >> 16;
-		*x++ = (z << 16) + (y & 0xffff);
-#else
-		y = *x * m + carry;
-		carry = y >> 16;
-		*x++ = y & 0xffff;
-#endif
-#endif
-		}
-		while(++i < wds);
-	if (carry) {
-		if (wds >= b->maxwds) {
-			b1 = Balloc(b->k+1);
-			Bcopy(b1, b);
-			Bfree(b);
-			b = b1;
-			}
-		b->x[wds++] = carry;
-		b->wds = wds;
-		}
-	return b;
-	}
-
- static Bigint *
-s2b
-#ifdef KR_headers
-	(s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
-#else
-	(CONST char *s, int nd0, int nd, ULong y9)
-#endif
-{
-	Bigint *b;
-	int i, k;
-	Long x, y;
-
-	x = (nd + 8) / 9;
-	for(k = 0, y = 1; x > y; y <<= 1, k++) ;
-#ifdef Pack_32
-	b = Balloc(k);
-	b->x[0] = y9;
-	b->wds = 1;
-#else
-	b = Balloc(k+1);
-	b->x[0] = y9 & 0xffff;
-	b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
-#endif
-
-	i = 9;
-	if (9 < nd0) {
-		s += 9;
-		do b = multadd(b, 10, *s++ - '0');
-			while(++i < nd0);
-		s++;
-		}
-	else
-		s += 10;
-	for(; i < nd; i++)
-		b = multadd(b, 10, *s++ - '0');
-	return b;
-	}
-
- static int
-hi0bits
-#ifdef KR_headers
-	(x) register ULong x;
-#else
-	(register ULong x)
-#endif
-{
-	register int k = 0;
-
-	if (!(x & 0xffff0000)) {
-		k = 16;
-		x <<= 16;
-		}
-	if (!(x & 0xff000000)) {
-		k += 8;
-		x <<= 8;
-		}
-	if (!(x & 0xf0000000)) {
-		k += 4;
-		x <<= 4;
-		}
-	if (!(x & 0xc0000000)) {
-		k += 2;
-		x <<= 2;
-		}
-	if (!(x & 0x80000000)) {
-		k++;
-		if (!(x & 0x40000000))
-			return 32;
-		}
-	return k;
-	}
-
- static int
-lo0bits
-#ifdef KR_headers
-	(y) ULong *y;
-#else
-	(ULong *y)
-#endif
-{
-	register int k;
-	register ULong x = *y;
-
-	if (x & 7) {
-		if (x & 1)
-			return 0;
-		if (x & 2) {
-			*y = x >> 1;
-			return 1;
-			}
-		*y = x >> 2;
-		return 2;
-		}
-	k = 0;
-	if (!(x & 0xffff)) {
-		k = 16;
-		x >>= 16;
-		}
-	if (!(x & 0xff)) {
-		k += 8;
-		x >>= 8;
-		}
-	if (!(x & 0xf)) {
-		k += 4;
-		x >>= 4;
-		}
-	if (!(x & 0x3)) {
-		k += 2;
-		x >>= 2;
-		}
-	if (!(x & 1)) {
-		k++;
-		x >>= 1;
-		if (!x)
-			return 32;
-		}
-	*y = x;
-	return k;
-	}
-
- static Bigint *
-i2b
-#ifdef KR_headers
-	(i) int i;
-#else
-	(int i)
-#endif
-{
-	Bigint *b;
-
-	b = Balloc(1);
-	b->x[0] = i;
-	b->wds = 1;
-	return b;
-	}
-
- static Bigint *
-mult
-#ifdef KR_headers
-	(a, b) Bigint *a, *b;
-#else
-	(Bigint *a, Bigint *b)
-#endif
-{
-	Bigint *c;
-	int k, wa, wb, wc;
-	ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
-	ULong y;
-#ifdef ULLong
-	ULLong carry, z;
-#else
-	ULong carry, z;
-#ifdef Pack_32
-	ULong z2;
-#endif
-#endif
-
-	if (a->wds < b->wds) {
-		c = a;
-		a = b;
-		b = c;
-		}
-	k = a->k;
-	wa = a->wds;
-	wb = b->wds;
-	wc = wa + wb;
-	if (wc > a->maxwds)
-		k++;
-	c = Balloc(k);
-	for(x = c->x, xa = x + wc; x < xa; x++)
-		*x = 0;
-	xa = a->x;
-	xae = xa + wa;
-	xb = b->x;
-	xbe = xb + wb;
-	xc0 = c->x;
-#ifdef ULLong
-	for(; xb < xbe; xc0++) {
-		if ((y = *xb++)) {
-			x = xa;
-			xc = xc0;
-			carry = 0;
-			do {
-				z = *x++ * (ULLong)y + *xc + carry;
-				carry = z >> 32;
-				*xc++ = z & FFFFFFFF;
-				}
-				while(x < xae);
-			*xc = carry;
-			}
-		}
-#else
-#ifdef Pack_32
-	for(; xb < xbe; xb++, xc0++) {
-		if (y = *xb & 0xffff) {
-			x = xa;
-			xc = xc0;
-			carry = 0;
-			do {
-				z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
-				carry = z >> 16;
-				z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
-				carry = z2 >> 16;
-				Storeinc(xc, z2, z);
-				}
-				while(x < xae);
-			*xc = carry;
-			}
-		if (y = *xb >> 16) {
-			x = xa;
-			xc = xc0;
-			carry = 0;
-			z2 = *xc;
-			do {
-				z = (*x & 0xffff) * y + (*xc >> 16) + carry;
-				carry = z >> 16;
-				Storeinc(xc, z, z2);
-				z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
-				carry = z2 >> 16;
-				}
-				while(x < xae);
-			*xc = z2;
-			}
-		}
-#else
-	for(; xb < xbe; xc0++) {
-		if (y = *xb++) {
-			x = xa;
-			xc = xc0;
-			carry = 0;
-			do {
-				z = *x++ * y + *xc + carry;
-				carry = z >> 16;
-				*xc++ = z & 0xffff;
-				}
-				while(x < xae);
-			*xc = carry;
-			}
-		}
-#endif
-#endif
-	for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
-	c->wds = wc;
-	return c;
-	}
-
- static Bigint *p5s;
-
- static Bigint *
-pow5mult
-#ifdef KR_headers
-	(b, k) Bigint *b; int k;
-#else
-	(Bigint *b, int k)
-#endif
-{
-	Bigint *b1, *p5, *p51;
-	int i;
-	static int p05[3] = { 5, 25, 125 };
-
-	if ((i = k & 3))
-		b = multadd(b, p05[i-1], 0);
-
-	if (!(k >>= 2))
-		return b;
-	if (!(p5 = p5s)) {
-		/* first time */
-#ifdef MULTIPLE_THREADS
-		ACQUIRE_DTOA_LOCK(1);
-		if (!(p5 = p5s)) {
-			p5 = p5s = i2b(625);
-			p5->next = 0;
-			}
-		FREE_DTOA_LOCK(1);
-#else
-		p5 = p5s = i2b(625);
-		p5->next = 0;
-#endif
-		}
-	for(;;) {
-		if (k & 1) {
-			b1 = mult(b, p5);
-			Bfree(b);
-			b = b1;
-			}
-		if (!(k >>= 1))
-			break;
-		if (!(p51 = p5->next)) {
-#ifdef MULTIPLE_THREADS
-			ACQUIRE_DTOA_LOCK(1);
-			if (!(p51 = p5->next)) {
-				p51 = p5->next = mult(p5,p5);
-				p51->next = 0;
-				}
-			FREE_DTOA_LOCK(1);
-#else
-			p51 = p5->next = mult(p5,p5);
-			p51->next = 0;
-#endif
-			}
-		p5 = p51;
-		}
-	return b;
-	}
-
- static Bigint *
-lshift
-#ifdef KR_headers
-	(b, k) Bigint *b; int k;
-#else
-	(Bigint *b, int k)
-#endif
-{
-	int i, k1, n, n1;
-	Bigint *b1;
-	ULong *x, *x1, *xe, z;
-
-#ifdef Pack_32
-	n = k >> 5;
-#else
-	n = k >> 4;
-#endif
-	k1 = b->k;
-	n1 = n + b->wds + 1;
-	for(i = b->maxwds; n1 > i; i <<= 1)
-		k1++;
-	b1 = Balloc(k1);
-	x1 = b1->x;
-	for(i = 0; i < n; i++)
-		*x1++ = 0;
-	x = b->x;
-	xe = x + b->wds;
-#ifdef Pack_32
-	if (k &= 0x1f) {
-		k1 = 32 - k;
-		z = 0;
-		do {
-			*x1++ = *x << k | z;
-			z = *x++ >> k1;
-			}
-			while(x < xe);
-		if ((*x1 = z))
-			++n1;
-		}
-#else
-	if (k &= 0xf) {
-		k1 = 16 - k;
-		z = 0;
-		do {
-			*x1++ = *x << k  & 0xffff | z;
-			z = *x++ >> k1;
-			}
-			while(x < xe);
-		if (*x1 = z)
-			++n1;
-		}
-#endif
-	else do
-		*x1++ = *x++;
-		while(x < xe);
-	b1->wds = n1 - 1;
-	Bfree(b);
-	return b1;
-	}
-
- static int
-cmp
-#ifdef KR_headers
-	(a, b) Bigint *a, *b;
-#else
-	(Bigint *a, Bigint *b)
-#endif
-{
-	ULong *xa, *xa0, *xb, *xb0;
-	int i, j;
-
-	i = a->wds;
-	j = b->wds;
-#ifdef DEBUG
-	if (i > 1 && !a->x[i-1])
-		Bug("cmp called with a->x[a->wds-1] == 0");
-	if (j > 1 && !b->x[j-1])
-		Bug("cmp called with b->x[b->wds-1] == 0");
-#endif
-	if (i -= j)
-		return i;
-	xa0 = a->x;
-	xa = xa0 + j;
-	xb0 = b->x;
-	xb = xb0 + j;
-	for(;;) {
-		if (*--xa != *--xb)
-			return *xa < *xb ? -1 : 1;
-		if (xa <= xa0)
-			break;
-		}
-	return 0;
-	}
-
- static Bigint *
-diff
-#ifdef KR_headers
-	(a, b) Bigint *a, *b;
-#else
-	(Bigint *a, Bigint *b)
-#endif
-{
-	Bigint *c;
-	int i, wa, wb;
-	ULong *xa, *xae, *xb, *xbe, *xc;
-#ifdef ULLong
-	ULLong borrow, y;
-#else
-	ULong borrow, y;
-#ifdef Pack_32
-	ULong z;
-#endif
-#endif
-
-	i = cmp(a,b);
-	if (!i) {
-		c = Balloc(0);
-		c->wds = 1;
-		c->x[0] = 0;
-		return c;
-		}
-	if (i < 0) {
-		c = a;
-		a = b;
-		b = c;
-		i = 1;
-		}
-	else
-		i = 0;
-	c = Balloc(a->k);
-	c->sign = i;
-	wa = a->wds;
-	xa = a->x;
-	xae = xa + wa;
-	wb = b->wds;
-	xb = b->x;
-	xbe = xb + wb;
-	xc = c->x;
-	borrow = 0;
-#ifdef ULLong
-	do {
-		y = (ULLong)*xa++ - *xb++ - borrow;
-		borrow = y >> 32 & (ULong)1;
-		*xc++ = y & FFFFFFFF;
-		}
-		while(xb < xbe);
-	while(xa < xae) {
-		y = *xa++ - borrow;
-		borrow = y >> 32 & (ULong)1;
-		*xc++ = y & FFFFFFFF;
-		}
-#else
-#ifdef Pack_32
-	do {
-		y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
-		borrow = (y & 0x10000) >> 16;
-		z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
-		borrow = (z & 0x10000) >> 16;
-		Storeinc(xc, z, y);
-		}
-		while(xb < xbe);
-	while(xa < xae) {
-		y = (*xa & 0xffff) - borrow;
-		borrow = (y & 0x10000) >> 16;
-		z = (*xa++ >> 16) - borrow;
-		borrow = (z & 0x10000) >> 16;
-		Storeinc(xc, z, y);
-		}
-#else
-	do {
-		y = *xa++ - *xb++ - borrow;
-		borrow = (y & 0x10000) >> 16;
-		*xc++ = y & 0xffff;
-		}
-		while(xb < xbe);
-	while(xa < xae) {
-		y = *xa++ - borrow;
-		borrow = (y & 0x10000) >> 16;
-		*xc++ = y & 0xffff;
-		}
-#endif
-#endif
-	while(!*--xc)
-		wa--;
-	c->wds = wa;
-	return c;
-	}
-
- static double
-ulp
-#ifdef KR_headers
-	(dx) double dx;
-#else
-	(double dx)
-#endif
-{
-	register Long L;
-        U x, a;
-
-        dval(x) = dx;
-
-	L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
-	if (L > 0) {
-#endif
-#endif
-#ifdef IBM
-		L |= Exp_msk1 >> 4;
-#endif
-		word0(a) = L;
-		word1(a) = 0;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
-		}
-	else {
-		L = -L >> Exp_shift;
-		if (L < Exp_shift) {
-			word0(a) = 0x80000 >> L;
-			word1(a) = 0;
-			}
-		else {
-			word0(a) = 0;
-			L -= Exp_shift;
-			word1(a) = L >= 31 ? 1 : 1 << 31 - L;
-			}
-		}
-#endif
-#endif
-	return dval(a);
-	}
-
- static double
-b2d
-#ifdef KR_headers
-	(a, e) Bigint *a; int *e;
-#else
-	(Bigint *a, int *e)
-#endif
-{
-	ULong *xa, *xa0, w, y, z;
-	int k;
-	U d;
-#ifdef VAX
-	ULong d0, d1;
-#else
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
-	xa0 = a->x;
-	xa = xa0 + a->wds;
-	y = *--xa;
-#ifdef DEBUG
-	if (!y) Bug("zero y in b2d");
-#endif
-	k = hi0bits(y);
-	*e = 32 - k;
-#ifdef Pack_32
-	if (k < Ebits) {
-		d0 = Exp_1 | (y >> (Ebits - k));
-		w = xa > xa0 ? *--xa : 0;
-		d1 = (y << ((32-Ebits) + k)) | (w >> (Ebits - k));
-		goto ret_d;
-		}
-	z = xa > xa0 ? *--xa : 0;
-	if (k -= Ebits) {
-		d0 = Exp_1 | (y << k) | (z >> (32 - k));
-		y = xa > xa0 ? *--xa : 0;
-		d1 = (z << k) | (y >> (32 - k));
-		}
-	else {
-		d0 = Exp_1 | y;
-		d1 = z;
-		}
-#else
-	if (k < Ebits + 16) {
-		z = xa > xa0 ? *--xa : 0;
-		d0 = Exp_1 | (y << (k - Ebits)) | (z >> (Ebits + 16 - k));
-		w = xa > xa0 ? *--xa : 0;
-		y = xa > xa0 ? *--xa : 0;
-		d1 = (z << (k + 16 - Ebits)) | (w << (k - Ebits)) | (y >> (16 + Ebits - k));
-		goto ret_d;
-		}
-	z = xa > xa0 ? *--xa : 0;
-	w = xa > xa0 ? *--xa : 0;
-	k -= Ebits + 16;
-	d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
-	y = xa > xa0 ? *--xa : 0;
-	d1 = w << k + 16 | y << k;
-#endif
- ret_d:
-#ifdef VAX
-	word0(d) = d0 >> 16 | d0 << 16;
-	word1(d) = d1 >> 16 | d1 << 16;
-#else
-#undef d0
-#undef d1
-#endif
-	return dval(d);
-	}
-
- static Bigint *
-d2b
-#ifdef KR_headers
-	(dd, e, bits) double dd; int *e, *bits;
-#else
-	(double dd, int *e, int *bits)
-#endif
-{
-	Bigint *b;
-	int de, k;
-	ULong *x, y, z;
-#ifndef Sudden_Underflow
-	int i;
-#endif
-#ifdef VAX
-	ULong d0, d1;
-	d0 = word0(d) >> 16 | word0(d) << 16;
-	d1 = word1(d) >> 16 | word1(d) << 16;
-#else
-        U d;
-        dval(d) = dd;
-#define d0 word0(d)
-#define d1 word1(d)
-#endif
-
-#ifdef Pack_32
-	b = Balloc(1);
-#else
-	b = Balloc(2);
-#endif
-	x = b->x;
-
-	z = d0 & Frac_mask;
-	d0 &= 0x7fffffff;	/* clear sign bit, which we ignore */
-#ifdef Sudden_Underflow
-	de = (int)(d0 >> Exp_shift);
-#ifndef IBM
-	z |= Exp_msk11;
-#endif
-#else
-	if ((de = (int)(d0 >> Exp_shift)))
-		z |= Exp_msk1;
-#endif
-#ifdef Pack_32
-	if ((y = d1)) {
-		if ((k = lo0bits(&y))) {
-			x[0] = y | (z << (32 - k));
-			z >>= k;
-			}
-		else
-			x[0] = y;
-#ifndef Sudden_Underflow
-		i =
-#endif
-		    b->wds = (x[1] = z) ? 2 : 1;
-		}
-	else {
-               /* This assertion fails for "1e-500" and other very 
-                * small numbers.  It provides the right result (0) 
-                * though. This assert has also been removed from KJS's
-                * version of dtoa.c.
-                *
-                * #ifdef DEBUG
-                *     if (!z) Bug("zero z in b2d");
-                * #endif
-                */
-		k = lo0bits(&z);
-		x[0] = z;
-#ifndef Sudden_Underflow
-		i =
-#endif
-		    b->wds = 1;
-		k += 32;
-		}
-#else
-	if (y = d1) {
-		if (k = lo0bits(&y))
-			if (k >= 16) {
-				x[0] = y | z << 32 - k & 0xffff;
-				x[1] = z >> k - 16 & 0xffff;
-				x[2] = z >> k;
-				i = 2;
-				}
-			else {
-				x[0] = y & 0xffff;
-				x[1] = y >> 16 | z << 16 - k & 0xffff;
-				x[2] = z >> k & 0xffff;
-				x[3] = z >> k+16;
-				i = 3;
-				}
-		else {
-			x[0] = y & 0xffff;
-			x[1] = y >> 16;
-			x[2] = z & 0xffff;
-			x[3] = z >> 16;
-			i = 3;
-			}
-		}
-	else {
-#ifdef DEBUG
-		if (!z)
-			Bug("Zero passed to d2b");
-#endif
-		k = lo0bits(&z);
-		if (k >= 16) {
-			x[0] = z;
-			i = 0;
-			}
-		else {
-			x[0] = z & 0xffff;
-			x[1] = z >> 16;
-			i = 1;
-			}
-		k += 32;
-		}
-	while(!x[i])
-		--i;
-	b->wds = i + 1;
-#endif
-#ifndef Sudden_Underflow
-	if (de) {
-#endif
-#ifdef IBM
-		*e = (de - Bias - (P-1) << 2) + k;
-		*bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
-#else
-		*e = de - Bias - (P-1) + k;
-		*bits = P - k;
-#endif
-#ifndef Sudden_Underflow
-		}
-	else {
-		*e = de - Bias - (P-1) + 1 + k;
-#ifdef Pack_32
-		*bits = 32*i - hi0bits(x[i-1]);
-#else
-		*bits = (i+2)*16 - hi0bits(x[i]);
-#endif
-		}
-#endif
-	return b;
-	}
-#undef d0
-#undef d1
-
- static double
-ratio
-#ifdef KR_headers
-	(a, b) Bigint *a, *b;
-#else
-	(Bigint *a, Bigint *b)
-#endif
-{
-	U da, db;
-	int k, ka, kb;
-
-	dval(da) = b2d(a, &ka);
-	dval(db) = b2d(b, &kb);
-#ifdef Pack_32
-	k = ka - kb + 32*(a->wds - b->wds);
-#else
-	k = ka - kb + 16*(a->wds - b->wds);
-#endif
-#ifdef IBM
-	if (k > 0) {
-		word0(da) += (k >> 2)*Exp_msk1;
-		if (k &= 3)
-			dval(da) *= 1 << k;
-		}
-	else {
-		k = -k;
-		word0(db) += (k >> 2)*Exp_msk1;
-		if (k &= 3)
-			dval(db) *= 1 << k;
-		}
-#else
-	if (k > 0)
-		word0(da) += k*Exp_msk1;
-	else {
-		k = -k;
-		word0(db) += k*Exp_msk1;
-		}
-#endif
-	return dval(da) / dval(db);
-	}
-
- static CONST double
-tens[] = {
-		1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
-		1e20, 1e21, 1e22
-#ifdef VAX
-		, 1e23, 1e24
-#endif
-		};
-
- static CONST double
-#ifdef IEEE_Arith
-bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
-static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
-#ifdef Avoid_Underflow
-		9007199254740992.*9007199254740992.e-256
-		/* = 2^106 * 1e-53 */
-#else
-		1e-256
-#endif
-		};
-/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
-/* flag unnecessarily.  It leads to a song and dance at the end of strtod. */
-#define Scale_Bit 0x10
-#define n_bigtens 5
-#else
-#ifdef IBM
-bigtens[] = { 1e16, 1e32, 1e64 };
-static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
-#define n_bigtens 3
-#else
-bigtens[] = { 1e16, 1e32 };
-static CONST double tinytens[] = { 1e-16, 1e-32 };
-#define n_bigtens 2
-#endif
-#endif
-
-#ifndef IEEE_Arith
-#undef INFNAN_CHECK
-#endif
-
-#ifdef INFNAN_CHECK
-
-#ifndef NAN_WORD0
-#define NAN_WORD0 0x7ff80000
-#endif
-
-#ifndef NAN_WORD1
-#define NAN_WORD1 0
-#endif
-
- static int
-match
-#ifdef KR_headers
-	(sp, t) char **sp, *t;
-#else
-	(CONST char **sp, char *t)
-#endif
-{
-	int c, d;
-	CONST char *s = *sp;
-
-	while(d = *t++) {
-		if ((c = *++s) >= 'A' && c <= 'Z')
-			c += 'a' - 'A';
-		if (c != d)
-			return 0;
-		}
-	*sp = s + 1;
-	return 1;
-	}
-
-#ifndef No_Hex_NaN
- static void
-hexnan
-#ifdef KR_headers
-	(rvp, sp) double *rvp; CONST char **sp;
-#else
-	(double *rvp, CONST char **sp)
-#endif
-{
-	ULong c, x[2];
-	CONST char *s;
-	int havedig, udx0, xshift;
-
-	x[0] = x[1] = 0;
-	havedig = xshift = 0;
-	udx0 = 1;
-	s = *sp;
-	while(c = *(CONST unsigned char*)++s) {
-		if (c >= '0' && c <= '9')
-			c -= '0';
-		else if (c >= 'a' && c <= 'f')
-			c += 10 - 'a';
-		else if (c >= 'A' && c <= 'F')
-			c += 10 - 'A';
-		else if (c <= ' ') {
-			if (udx0 && havedig) {
-				udx0 = 0;
-				xshift = 1;
-				}
-			continue;
-			}
-		else if (/*(*/ c == ')' && havedig) {
-			*sp = s + 1;
-			break;
-			}
-		else
-			return;	/* invalid form: don't change *sp */
-		havedig = 1;
-		if (xshift) {
-			xshift = 0;
-			x[0] = x[1];
-			x[1] = 0;
-			}
-		if (udx0)
-			x[0] = (x[0] << 4) | (x[1] >> 28);
-		x[1] = (x[1] << 4) | c;
-		}
-	if ((x[0] &= 0xfffff) || x[1]) {
-		word0(*rvp) = Exp_mask | x[0];
-		word1(*rvp) = x[1];
-		}
-	}
-#endif /*No_Hex_NaN*/
-#endif /* INFNAN_CHECK */
-
- double
-strtod
-#ifdef KR_headers
-	(s00, se) CONST char *s00; char **se;
-#else
-	(CONST char *s00, char **se)
-#endif
-{
-#ifdef Avoid_Underflow
-	int scale;
-#endif
-	int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
-		 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
-	CONST char *s, *s0, *s1;
-        double aadj;
-	U aadj1, adj, rv, rv0;
-	Long L;
-	ULong y, z;
-	Bigint *bb = NULL, *bb1, *bd = NULL, *bd0, *bs = NULL, *delta = NULL;
-#ifdef SET_INEXACT
-	int inexact, oldinexact;
-#endif
-#ifdef Honor_FLT_ROUNDS
-	int rounding;
-#endif
-#ifdef USE_LOCALE
-	CONST char *s2;
-#endif
-
-	sign = nz0 = nz = 0;
-	dval(rv) = 0.;
-	for(s = s00;;s++) switch(*s) {
-		case '-':
-			sign = 1;
-			/* no break */
-		case '+':
-			if (*++s)
-				goto break2;
-			/* no break */
-		case 0:
-			goto ret0;
-		case '\t':
-		case '\n':
-		case '\v':
-		case '\f':
-		case '\r':
-		case ' ':
-			continue;
-		default:
-			goto break2;
-		}
- break2:
-	if (*s == '0') {
-		nz0 = 1;
-		while(*++s == '0') ;
-		if (!*s)
-			goto ret;
-		}
-	s0 = s;
-	y = z = 0;
-	for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
-		if (nd < 9)
-			y = 10*y + c - '0';
-		else if (nd < 16)
-			z = 10*z + c - '0';
-	nd0 = nd;
-#ifdef USE_LOCALE
-	s1 = localeconv()->decimal_point;
-	if (c == *s1) {
-		c = '.';
-		if (*++s1) {
-			s2 = s;
-			for(;;) {
-				if (*++s2 != *s1) {
-					c = 0;
-					break;
-					}
-				if (!*++s1) {
-					s = s2;
-					break;
-					}
-				}
-			}
-		}
-#endif
-	if (c == '.') {
-		c = *++s;
-		if (!nd) {
-			for(; c == '0'; c = *++s)
-				nz++;
-			if (c > '0' && c <= '9') {
-				s0 = s;
-				nf += nz;
-				nz = 0;
-				goto have_dig;
-				}
-			goto dig_done;
-			}
-		for(; c >= '0' && c <= '9'; c = *++s) {
- have_dig:
-			nz++;
-			if (c -= '0') {
-				nf += nz;
-				for(i = 1; i < nz; i++)
-					if (nd++ < 9)
-						y *= 10;
-					else if (nd <= DBL_DIG + 1)
-						z *= 10;
-				if (nd++ < 9)
-					y = 10*y + c;
-				else if (nd <= DBL_DIG + 1)
-					z = 10*z + c;
-				nz = 0;
-				}
-			}
-		}
- dig_done:
-	e = 0;
-	if (c == 'e' || c == 'E') {
-		if (!nd && !nz && !nz0) {
-			goto ret0;
-			}
-		s00 = s;
-		esign = 0;
-		switch(c = *++s) {
-			case '-':
-				esign = 1;
-			case '+':
-				c = *++s;
-			}
-		if (c >= '0' && c <= '9') {
-			while(c == '0')
-				c = *++s;
-			if (c > '0' && c <= '9') {
-				L = c - '0';
-				s1 = s;
-				while((c = *++s) >= '0' && c <= '9')
-					L = 10*L + c - '0';
-				if (s - s1 > 8 || L > 19999)
-					/* Avoid confusion from exponents
-					 * so large that e might overflow.
-					 */
-					e = 19999; /* safe for 16 bit ints */
-				else
-					e = (int)L;
-				if (esign)
-					e = -e;
-				}
-			else
-				e = 0;
-			}
-		else
-			s = s00;
-		}
-	if (!nd) {
-		if (!nz && !nz0) {
-#ifdef INFNAN_CHECK
-			/* Check for Nan and Infinity */
-			switch(c) {
-			  case 'i':
-			  case 'I':
-				if (match(&s,"nf")) {
-					--s;
-					if (!match(&s,"inity"))
-						++s;
-					word0(rv) = 0x7ff00000;
-					word1(rv) = 0;
-					goto ret;
-					}
-				break;
-			  case 'n':
-			  case 'N':
-				if (match(&s, "an")) {
-					word0(rv) = NAN_WORD0;
-					word1(rv) = NAN_WORD1;
-#ifndef No_Hex_NaN
-					if (*s == '(') /*)*/
-						hexnan(&rv, &s);
-#endif
-					goto ret;
-					}
-			  }
-#endif /* INFNAN_CHECK */
- ret0:
-			s = s00;
-			sign = 0;
-			}
-		goto ret;
-		}
-	e1 = e -= nf;
-
-	/* Now we have nd0 digits, starting at s0, followed by a
-	 * decimal point, followed by nd-nd0 digits.  The number we're
-	 * after is the integer represented by those digits times
-	 * 10**e */
-
-	if (!nd0)
-		nd0 = nd;
-	k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
-	dval(rv) = y;
-	if (k > 9) {
-#ifdef SET_INEXACT
-		if (k > DBL_DIG)
-			oldinexact = get_inexact();
-#endif
-		dval(rv) = tens[k - 9] * dval(rv) + z;
-		}
-	bd0 = 0;
-	if (nd <= DBL_DIG
-#ifndef RND_PRODQUOT
-#ifndef Honor_FLT_ROUNDS
-		&& Flt_Rounds == 1
-#endif
-#endif
-			) {
-		if (!e)
-			goto ret;
-		if (e > 0) {
-			if (e <= Ten_pmax) {
-#ifdef VAX
-				goto vax_ovfl_check;
-#else
-#ifdef Honor_FLT_ROUNDS
-				/* round correctly FLT_ROUNDS = 2 or 3 */
-				if (sign) {
-					rv = -rv;
-					sign = 0;
-					}
-#endif
-				/* rv = */ rounded_product(dval(rv), tens[e]);
-				goto ret;
-#endif
-				}
-			i = DBL_DIG - nd;
-			if (e <= Ten_pmax + i) {
-				/* A fancier test would sometimes let us do
-				 * this for larger i values.
-				 */
-#ifdef Honor_FLT_ROUNDS
-				/* round correctly FLT_ROUNDS = 2 or 3 */
-				if (sign) {
-					rv = -rv;
-					sign = 0;
-					}
-#endif
-				e -= i;
-				dval(rv) *= tens[i];
-#ifdef VAX
-				/* VAX exponent range is so narrow we must
-				 * worry about overflow here...
-				 */
- vax_ovfl_check:
-				word0(rv) -= P*Exp_msk1;
-				/* rv = */ rounded_product(dval(rv), tens[e]);
-				if ((word0(rv) & Exp_mask)
-				 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
-					goto ovfl;
-				word0(rv) += P*Exp_msk1;
-#else
-				/* rv = */ rounded_product(dval(rv), tens[e]);
-#endif
-				goto ret;
-				}
-			}
-#ifndef Inaccurate_Divide
-		else if (e >= -Ten_pmax) {
-#ifdef Honor_FLT_ROUNDS
-			/* round correctly FLT_ROUNDS = 2 or 3 */
-			if (sign) {
-				rv = -rv;
-				sign = 0;
-				}
-#endif
-			/* rv = */ rounded_quotient(dval(rv), tens[-e]);
-			goto ret;
-			}
-#endif
-		}
-	e1 += nd - k;
-
-#ifdef IEEE_Arith
-#ifdef SET_INEXACT
-	inexact = 1;
-	if (k <= DBL_DIG)
-		oldinexact = get_inexact();
-#endif
-#ifdef Avoid_Underflow
-	scale = 0;
-#endif
-#ifdef Honor_FLT_ROUNDS
-	if ((rounding = Flt_Rounds) >= 2) {
-		if (sign)
-			rounding = rounding == 2 ? 0 : 2;
-		else
-			if (rounding != 2)
-				rounding = 0;
-		}
-#endif
-#endif /*IEEE_Arith*/
-
-	/* Get starting approximation = rv * 10**e1 */
-
-	if (e1 > 0) {
-		if ((i = e1 & 15))
-			dval(rv) *= tens[i];
-		if (e1 &= ~15) {
-			if (e1 > DBL_MAX_10_EXP) {
- ovfl:
-#ifndef NO_ERRNO
-				errno = ERANGE;
-#endif
-				/* Can't trust HUGE_VAL */
-#ifdef IEEE_Arith
-#ifdef Honor_FLT_ROUNDS
-				switch(rounding) {
-				  case 0: /* toward 0 */
-				  case 3: /* toward -infinity */
-					word0(rv) = Big0;
-					word1(rv) = Big1;
-					break;
-				  default:
-					word0(rv) = Exp_mask;
-					word1(rv) = 0;
-				  }
-#else /*Honor_FLT_ROUNDS*/
-				word0(rv) = Exp_mask;
-				word1(rv) = 0;
-#endif /*Honor_FLT_ROUNDS*/
-#ifdef SET_INEXACT
-				/* set overflow bit */
-				dval(rv0) = 1e300;
-				dval(rv0) *= dval(rv0);
-#endif
-#else /*IEEE_Arith*/
-				word0(rv) = Big0;
-				word1(rv) = Big1;
-#endif /*IEEE_Arith*/
-				if (bd0)
-					goto retfree;
-				goto ret;
-				}
-			e1 >>= 4;
-			for(j = 0; e1 > 1; j++, e1 >>= 1)
-				if (e1 & 1)
-					dval(rv) *= bigtens[j];
-		/* The last multiplication could overflow. */
-			word0(rv) -= P*Exp_msk1;
-			dval(rv) *= bigtens[j];
-			if ((z = word0(rv) & Exp_mask)
-			 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
-				goto ovfl;
-			if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
-				/* set to largest number */
-				/* (Can't trust DBL_MAX) */
-				word0(rv) = Big0;
-				word1(rv) = Big1;
-				}
-			else
-				word0(rv) += P*Exp_msk1;
-			}
-		}
-	else if (e1 < 0) {
-		e1 = -e1;
-		if ((i = e1 & 15))
-			dval(rv) /= tens[i];
-		if (e1 >>= 4) {
-			if (e1 >= 1 << n_bigtens)
-				goto undfl;
-#ifdef Avoid_Underflow
-			if (e1 & Scale_Bit)
-				scale = 2*P;
-			for(j = 0; e1 > 0; j++, e1 >>= 1)
-				if (e1 & 1)
-					dval(rv) *= tinytens[j];
-			if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
-						>> Exp_shift)) > 0) {
-				/* scaled rv is denormal; zap j low bits */
-				if (j >= 32) {
-					word1(rv) = 0;
-					if (j >= 53)
-					 word0(rv) = (P+2)*Exp_msk1;
-					else
-					 word0(rv) &= 0xffffffff << (j-32);
-					}
-				else
-					word1(rv) &= 0xffffffff << j;
-				}
-#else
-			for(j = 0; e1 > 1; j++, e1 >>= 1)
-				if (e1 & 1)
-					dval(rv) *= tinytens[j];
-			/* The last multiplication could underflow. */
-			dval(rv0) = dval(rv);
-			dval(rv) *= tinytens[j];
-			if (!dval(rv)) {
-				dval(rv) = 2.*dval(rv0);
-				dval(rv) *= tinytens[j];
-#endif
-				if (!dval(rv)) {
- undfl:
-					dval(rv) = 0.;
-#ifndef NO_ERRNO
-					errno = ERANGE;
-#endif
-					if (bd0)
-						goto retfree;
-					goto ret;
-					}
-#ifndef Avoid_Underflow
-				word0(rv) = Tiny0;
-				word1(rv) = Tiny1;
-				/* The refinement below will clean
-				 * this approximation up.
-				 */
-				}
-#endif
-			}
-		}
-
-	/* Now the hard part -- adjusting rv to the correct value.*/
-
-	/* Put digits into bd: true value = bd * 10^e */
-
-	bd0 = s2b(s0, nd0, nd, y);
-
-	for(;;) {
-		bd = Balloc(bd0->k);
-		Bcopy(bd, bd0);
-		bb = d2b(dval(rv), &bbe, &bbbits);	/* rv = bb * 2^bbe */
-		bs = i2b(1);
-
-		if (e >= 0) {
-			bb2 = bb5 = 0;
-			bd2 = bd5 = e;
-			}
-		else {
-			bb2 = bb5 = -e;
-			bd2 = bd5 = 0;
-			}
-		if (bbe >= 0)
-			bb2 += bbe;
-		else
-			bd2 -= bbe;
-		bs2 = bb2;
-#ifdef Honor_FLT_ROUNDS
-		if (rounding != 1)
-			bs2++;
-#endif
-#ifdef Avoid_Underflow
-		j = bbe - scale;
-		i = j + bbbits - 1;	/* logb(rv) */
-		if (i < Emin)	/* denormal */
-			j += P - Emin;
-		else
-			j = P + 1 - bbbits;
-#else /*Avoid_Underflow*/
-#ifdef Sudden_Underflow
-#ifdef IBM
-		j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
-#else
-		j = P + 1 - bbbits;
-#endif
-#else /*Sudden_Underflow*/
-		j = bbe;
-		i = j + bbbits - 1;	/* logb(rv) */
-		if (i < Emin)	/* denormal */
-			j += P - Emin;
-		else
-			j = P + 1 - bbbits;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
-		bb2 += j;
-		bd2 += j;
-#ifdef Avoid_Underflow
-		bd2 += scale;
-#endif
-		i = bb2 < bd2 ? bb2 : bd2;
-		if (i > bs2)
-			i = bs2;
-		if (i > 0) {
-			bb2 -= i;
-			bd2 -= i;
-			bs2 -= i;
-			}
-		if (bb5 > 0) {
-			bs = pow5mult(bs, bb5);
-			bb1 = mult(bs, bb);
-			Bfree(bb);
-			bb = bb1;
-			}
-		if (bb2 > 0)
-			bb = lshift(bb, bb2);
-		if (bd5 > 0)
-			bd = pow5mult(bd, bd5);
-		if (bd2 > 0)
-			bd = lshift(bd, bd2);
-		if (bs2 > 0)
-			bs = lshift(bs, bs2);
-		delta = diff(bb, bd);
-		dsign = delta->sign;
-		delta->sign = 0;
-		i = cmp(delta, bs);
-#ifdef Honor_FLT_ROUNDS
-		if (rounding != 1) {
-			if (i < 0) {
-				/* Error is less than an ulp */
-				if (!delta->x[0] && delta->wds <= 1) {
-					/* exact */
-#ifdef SET_INEXACT
-					inexact = 0;
-#endif
-					break;
-					}
-				if (rounding) {
-					if (dsign) {
-						dval(adj) = 1.;
-						goto apply_adj;
-						}
-					}
-				else if (!dsign) {
-					dval(adj) = -1.;
-					if (!word1(rv)
-					 && !(word0(rv) & Frac_mask)) {
-						y = word0(rv) & Exp_mask;
-#ifdef Avoid_Underflow
-						if (!scale || y > 2*P*Exp_msk1)
-#else
-						if (y)
-#endif
-						  {
-						  delta = lshift(delta,Log2P);
-						  if (cmp(delta, bs) <= 0)
-							dval(adj) = -0.5;
-						  }
-						}
- apply_adj:
-#ifdef Avoid_Underflow
-					if (scale && (y = word0(rv) & Exp_mask)
-						<= 2*P*Exp_msk1)
-					  word0(adj) += (2*P+1)*Exp_msk1 - y;
-#else
-#ifdef Sudden_Underflow
-					if ((word0(rv) & Exp_mask) <=
-							P*Exp_msk1) {
-						word0(rv) += P*Exp_msk1;
-						dval(rv) += dval(adj)*ulp(dval(rv));
-						word0(rv) -= P*Exp_msk1;
-						}
-					else
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
-					dval(rv) += dval(adj)*ulp(dval(rv));
-					}
-				break;
-				}
-			dval(adj) = ratio(delta, bs);
-			if (dval(adj) < 1.)
-				dval(adj) = 1.;
-			if (dval(adj) <= 0x7ffffffe) {
-				/* adj = rounding ? ceil(adj) : floor(adj); */
-				y = dval(adj);
-				if (y != dval(adj)) {
-					if (!((rounding>>1) ^ dsign))
-						y++;
-					dval(adj) = y;
-					}
-				}
-#ifdef Avoid_Underflow
-			if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
-				word0(adj) += (2*P+1)*Exp_msk1 - y;
-#else
-#ifdef Sudden_Underflow
-			if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
-				word0(rv) += P*Exp_msk1;
-				dval(adj) *= ulp(dval(rv));
-				if (dsign)
-					dval(rv) += dval(adj);
-				else
-					dval(rv) -= dval(adj);
-				word0(rv) -= P*Exp_msk1;
-				goto cont;
-				}
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
-			dval(adj) *= ulp(dval(rv));
-			if (dsign)
-				dval(rv) += dval(adj);
-			else
-				dval(rv) -= dval(adj);
-			goto cont;
-			}
-#endif /*Honor_FLT_ROUNDS*/
-
-		if (i < 0) {
-			/* Error is less than half an ulp -- check for
-			 * special case of mantissa a power of two.
-			 */
-			if (dsign || word1(rv) || word0(rv) & Bndry_mask
-#ifdef IEEE_Arith
-#ifdef Avoid_Underflow
-			 || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
-#else
-			 || (word0(rv) & Exp_mask) <= Exp_msk1
-#endif
-#endif
-				) {
-#ifdef SET_INEXACT
-				if (!delta->x[0] && delta->wds <= 1)
-					inexact = 0;
-#endif
-				break;
-				}
-			if (!delta->x[0] && delta->wds <= 1) {
-				/* exact result */
-#ifdef SET_INEXACT
-				inexact = 0;
-#endif
-				break;
-				}
-			delta = lshift(delta,Log2P);
-			if (cmp(delta, bs) > 0)
-				goto drop_down;
-			break;
-			}
-		if (i == 0) {
-			/* exactly half-way between */
-			if (dsign) {
-				if ((word0(rv) & Bndry_mask1) == Bndry_mask1
-				 &&  word1(rv) == (
-#ifdef Avoid_Underflow
-			(scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
-		? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
-#endif
-						   0xffffffff)) {
-					/*boundary case -- increment exponent*/
-					word0(rv) = (word0(rv) & Exp_mask)
-						+ Exp_msk1
-#ifdef IBM
-						| Exp_msk1 >> 4
-#endif
-						;
-					word1(rv) = 0;
-#ifdef Avoid_Underflow
-					dsign = 0;
-#endif
-					break;
-					}
-				}
-			else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
- drop_down:
-				/* boundary case -- decrement exponent */
-#ifdef Sudden_Underflow /*{{*/
-				L = word0(rv) & Exp_mask;
-#ifdef IBM
-				if (L <  Exp_msk1)
-#else
-#ifdef Avoid_Underflow
-				if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
-#else
-				if (L <= Exp_msk1)
-#endif /*Avoid_Underflow*/
-#endif /*IBM*/
-					goto undfl;
-				L -= Exp_msk1;
-#else /*Sudden_Underflow}{*/
-#ifdef Avoid_Underflow
-				if (scale) {
-					L = word0(rv) & Exp_mask;
-					if (L <= (2*P+1)*Exp_msk1) {
-						if (L > (P+2)*Exp_msk1)
-							/* round even ==> */
-							/* accept rv */
-							break;
-						/* rv = smallest denormal */
-						goto undfl;
-						}
-					}
-#endif /*Avoid_Underflow*/
-				L = (word0(rv) & Exp_mask) - Exp_msk1;
-#endif /*Sudden_Underflow}}*/
-				word0(rv) = L | Bndry_mask1;
-				word1(rv) = 0xffffffff;
-#ifdef IBM
-				goto cont;
-#else
-				break;
-#endif
-				}
-#ifndef ROUND_BIASED
-			if (!(word1(rv) & LSB))
-				break;
-#endif
-			if (dsign)
-				dval(rv) += ulp(dval(rv));
-#ifndef ROUND_BIASED
-			else {
-				dval(rv) -= ulp(dval(rv));
-#ifndef Sudden_Underflow
-				if (!dval(rv))
-					goto undfl;
-#endif
-				}
-#ifdef Avoid_Underflow
-			dsign = 1 - dsign;
-#endif
-#endif
-			break;
-			}
-		if ((aadj = ratio(delta, bs)) <= 2.) {
-			if (dsign)
-                                aadj = dval(aadj1) = 1.;
-			else if (word1(rv) || word0(rv) & Bndry_mask) {
-#ifndef Sudden_Underflow
-				if (word1(rv) == Tiny1 && !word0(rv))
-					goto undfl;
-#endif
-				aadj = 1.;
-				dval(aadj1) = -1.;
-				}
-			else {
-				/* special case -- power of FLT_RADIX to be */
-				/* rounded down... */
-
-				if (aadj < 2./FLT_RADIX)
-					aadj = 1./FLT_RADIX;
-				else
-					aadj *= 0.5;
-				dval(aadj1) = -aadj;
-				}
-			}
-		else {
-			aadj *= 0.5;
-			dval(aadj1) = dsign ? aadj : -aadj;
-#ifdef Check_FLT_ROUNDS
-			switch(Rounding) {
-				case 2: /* towards +infinity */
-					dval(aadj1) -= 0.5;
-					break;
-				case 0: /* towards 0 */
-				case 3: /* towards -infinity */
-					dval(aadj1) += 0.5;
-				}
-#else
-			if (Flt_Rounds == 0)
-				dval(aadj1) += 0.5;
-#endif /*Check_FLT_ROUNDS*/
-			}
-		y = word0(rv) & Exp_mask;
-
-		/* Check for overflow */
-
-		if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
-			dval(rv0) = dval(rv);
-			word0(rv) -= P*Exp_msk1;
-			dval(adj) = dval(aadj1) * ulp(dval(rv));
-			dval(rv) += dval(adj);
-			if ((word0(rv) & Exp_mask) >=
-					Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
-				if (word0(rv0) == Big0 && word1(rv0) == Big1)
-					goto ovfl;
-				word0(rv) = Big0;
-				word1(rv) = Big1;
-				goto cont;
-				}
-			else
-				word0(rv) += P*Exp_msk1;
-			}
-		else {
-#ifdef Avoid_Underflow
-			if (scale && y <= 2*P*Exp_msk1) {
-				if (aadj <= 0x7fffffff) {
-					if ((z = aadj) <= 0)
-						z = 1;
-					aadj = z;
-					dval(aadj1) = dsign ? aadj : -aadj;
-					}
-				word0(aadj1) += (2*P+1)*Exp_msk1 - y;
-				}
-			dval(adj) = dval(aadj1) * ulp(dval(rv));
-			dval(rv) += dval(adj);
-#else
-#ifdef Sudden_Underflow
-			if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
-				dval(rv0) = dval(rv);
-				word0(rv) += P*Exp_msk1;
-				dval(adj) = dval(aadj1) * ulp(dval(rv));
-				dval(rv) += dval(adj);
-#ifdef IBM
-				if ((word0(rv) & Exp_mask) <  P*Exp_msk1)
-#else
-				if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
-#endif
-					{
-					if (word0(rv0) == Tiny0
-					 && word1(rv0) == Tiny1)
-						goto undfl;
-					word0(rv) = Tiny0;
-					word1(rv) = Tiny1;
-					goto cont;
-					}
-				else
-					word0(rv) -= P*Exp_msk1;
-				}
-			else {
-				dval(adj) = dval(aadj1) * ulp(dval(rv));
-				dval(rv) += dval(adj);
-				}
-#else /*Sudden_Underflow*/
-			/* Compute adj so that the IEEE rounding rules will
-			 * correctly round rv + adj in some half-way cases.
-			 * If rv * ulp(rv) is denormalized (i.e.,
-			 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
-			 * trouble from bits lost to denormalization;
-			 * example: 1.2e-307 .
-			 */
-			if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
-				dval(aadj1) = (double)(int)(aadj + 0.5);
-				if (!dsign)
-					dval(aadj1) = -dval(aadj1);
-				}
-			dval(adj) = dval(aadj1) * ulp(dval(rv));
-			dval(rv) += dval(adj);
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
-			}
-		z = word0(rv) & Exp_mask;
-#ifndef SET_INEXACT
-#ifdef Avoid_Underflow
-		if (!scale)
-#endif
-		if (y == z) {
-			/* Can we stop now? */
-			L = (Long)aadj;
-			aadj -= L;
-			/* The tolerances below are conservative. */
-			if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
-				if (aadj < .4999999 || aadj > .5000001)
-					break;
-				}
-			else if (aadj < .4999999/FLT_RADIX)
-				break;
-			}
-#endif
- cont:
-		Bfree(bb);
-		Bfree(bd);
-		Bfree(bs);
-		Bfree(delta);
-		}
-#ifdef SET_INEXACT
-	if (inexact) {
-		if (!oldinexact) {
-			word0(rv0) = Exp_1 + (70 << Exp_shift);
-			word1(rv0) = 0;
-			dval(rv0) += 1.;
-			}
-		}
-	else if (!oldinexact)
-		clear_inexact();
-#endif
-#ifdef Avoid_Underflow
-	if (scale) {
-		word0(rv0) = Exp_1 - 2*P*Exp_msk1;
-		word1(rv0) = 0;
-		dval(rv) *= dval(rv0);
-#ifndef NO_ERRNO
-		/* try to avoid the bug of testing an 8087 register value */
-		if (word0(rv) == 0 && word1(rv) == 0)
-			errno = ERANGE;
-#endif
-		}
-#endif /* Avoid_Underflow */
-#ifdef SET_INEXACT
-	if (inexact && !(word0(rv) & Exp_mask)) {
-		/* set underflow bit */
-		dval(rv0) = 1e-300;
-		dval(rv0) *= dval(rv0);
-		}
-#endif
- retfree:
-	Bfree(bb);
-	Bfree(bd);
-	Bfree(bs);
-	Bfree(bd0);
-	Bfree(delta);
- ret:
-	if (se)
-		*se = (char *)s;
-	return sign ? -dval(rv) : dval(rv);
-	}
-
- static int
-quorem
-#ifdef KR_headers
-	(b, S) Bigint *b, *S;
-#else
-	(Bigint *b, Bigint *S)
-#endif
-{
-	int n;
-	ULong *bx, *bxe, q, *sx, *sxe;
-#ifdef ULLong
-	ULLong borrow, carry, y, ys;
-#else
-	ULong borrow, carry, y, ys;
-#ifdef Pack_32
-	ULong si, z, zs;
-#endif
-#endif
-
-	n = S->wds;
-#ifdef DEBUG
-	/*debug*/ if (b->wds > n)
-	/*debug*/	Bug("oversize b in quorem");
-#endif
-	if (b->wds < n)
-		return 0;
-	sx = S->x;
-	sxe = sx + --n;
-	bx = b->x;
-	bxe = bx + n;
-	q = *bxe / (*sxe + 1);	/* ensure q <= true quotient */
-#ifdef DEBUG
-	/*debug*/ if (q > 9)
-	/*debug*/	Bug("oversized quotient in quorem");
-#endif
-	if (q) {
-		borrow = 0;
-		carry = 0;
-		do {
-#ifdef ULLong
-			ys = *sx++ * (ULLong)q + carry;
-			carry = ys >> 32;
-			y = *bx - (ys & FFFFFFFF) - borrow;
-			borrow = y >> 32 & (ULong)1;
-			*bx++ = y & FFFFFFFF;
-#else
-#ifdef Pack_32
-			si = *sx++;
-			ys = (si & 0xffff) * q + carry;
-			zs = (si >> 16) * q + (ys >> 16);
-			carry = zs >> 16;
-			y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
-			borrow = (y & 0x10000) >> 16;
-			z = (*bx >> 16) - (zs & 0xffff) - borrow;
-			borrow = (z & 0x10000) >> 16;
-			Storeinc(bx, z, y);
-#else
-			ys = *sx++ * q + carry;
-			carry = ys >> 16;
-			y = *bx - (ys & 0xffff) - borrow;
-			borrow = (y & 0x10000) >> 16;
-			*bx++ = y & 0xffff;
-#endif
-#endif
-			}
-			while(sx <= sxe);
-		if (!*bxe) {
-			bx = b->x;
-			while(--bxe > bx && !*bxe)
-				--n;
-			b->wds = n;
-			}
-		}
-	if (cmp(b, S) >= 0) {
-		q++;
-		borrow = 0;
-		carry = 0;
-		bx = b->x;
-		sx = S->x;
-		do {
-#ifdef ULLong
-			ys = *sx++ + carry;
-			carry = ys >> 32;
-			y = *bx - (ys & FFFFFFFF) - borrow;
-			borrow = y >> 32 & (ULong)1;
-			*bx++ = y & FFFFFFFF;
-#else
-#ifdef Pack_32
-			si = *sx++;
-			ys = (si & 0xffff) + carry;
-			zs = (si >> 16) + (ys >> 16);
-			carry = zs >> 16;
-			y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
-			borrow = (y & 0x10000) >> 16;
-			z = (*bx >> 16) - (zs & 0xffff) - borrow;
-			borrow = (z & 0x10000) >> 16;
-			Storeinc(bx, z, y);
-#else
-			ys = *sx++ + carry;
-			carry = ys >> 16;
-			y = *bx - (ys & 0xffff) - borrow;
-			borrow = (y & 0x10000) >> 16;
-			*bx++ = y & 0xffff;
-#endif
-#endif
-			}
-			while(sx <= sxe);
-		bx = b->x;
-		bxe = bx + n;
-		if (!*bxe) {
-			while(--bxe > bx && !*bxe)
-				--n;
-			b->wds = n;
-			}
-		}
-	return q;
-	}
-
-#ifndef MULTIPLE_THREADS
- static char *dtoa_result;
-#endif
-
- static char *
-#ifdef KR_headers
-rv_alloc(i) int i;
-#else
-rv_alloc(int i)
-#endif
-{
-	int j, k, *r;
-
-	j = sizeof(ULong);
-	for(k = 0;
-		sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
-		j <<= 1)
-			k++;
-	r = (int*)Balloc(k);
-	*r = k;
-	return
-#ifndef MULTIPLE_THREADS
-	dtoa_result =
-#endif
-		(char *)(r+1);
-	}
-
- static char *
-#ifdef KR_headers
-nrv_alloc(s, rve, n) char *s, **rve; int n;
-#else
-nrv_alloc(const char *s, char **rve, int n)
-#endif
-{
-	char *rv, *t;
-
-	t = rv = rv_alloc(n);
-	while ((*t = *s++)) t++;
-	if (rve)
-		*rve = t;
-	return rv;
-	}
-
-/* freedtoa(s) must be used to free values s returned by dtoa
- * when MULTIPLE_THREADS is #defined.  It should be used in all cases,
- * but for consistency with earlier versions of dtoa, it is optional
- * when MULTIPLE_THREADS is not defined.
- */
-
- void
-#ifdef KR_headers
-freedtoa(s) char *s;
-#else
-freedtoa(char *s)
-#endif
-{
-	Bigint *b = (Bigint *)((int *)s - 1);
-	b->maxwds = 1 << (b->k = *(int*)b);
-	Bfree(b);
-#ifndef MULTIPLE_THREADS
-	if (s == dtoa_result)
-		dtoa_result = 0;
-#endif
-	}
-
-/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
- *
- * Inspired by "How to Print Floating-Point Numbers Accurately" by
- * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
- *
- * Modifications:
- *	1. Rather than iterating, we use a simple numeric overestimate
- *	   to determine k = floor(log10(d)).  We scale relevant
- *	   quantities using O(log2(k)) rather than O(k) multiplications.
- *	2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
- *	   try to generate digits strictly left to right.  Instead, we
- *	   compute with fewer bits and propagate the carry if necessary
- *	   when rounding the final digit up.  This is often faster.
- *	3. Under the assumption that input will be rounded nearest,
- *	   mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
- *	   That is, we allow equality in stopping tests when the
- *	   round-nearest rule will give the same floating-point value
- *	   as would satisfaction of the stopping test with strict
- *	   inequality.
- *	4. We remove common factors of powers of 2 from relevant
- *	   quantities.
- *	5. When converting floating-point integers less than 1e16,
- *	   we use floating-point arithmetic rather than resorting
- *	   to multiple-precision integers.
- *	6. When asked to produce fewer than 15 digits, we first try
- *	   to get by with floating-point arithmetic; we resort to
- *	   multiple-precision integer arithmetic only if we cannot
- *	   guarantee that the floating-point calculation has given
- *	   the correctly rounded result.  For k requested digits and
- *	   "uniformly" distributed input, the probability is
- *	   something like 10^(k-15) that we must resort to the Long
- *	   calculation.
- */
-
- char *
-dtoa
-#ifdef KR_headers
-	(dd, mode, ndigits, decpt, sign, rve)
-	double dd; int mode, ndigits, *decpt, *sign; char **rve;
-#else
-	(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve)
-#endif
-{
- /*	Arguments ndigits, decpt, sign are similar to those
-	of ecvt and fcvt; trailing zeros are suppressed from
-	the returned string.  If not null, *rve is set to point
-	to the end of the return value.  If d is +-Infinity or NaN,
-	then *decpt is set to 9999.
-
-	mode:
-		0 ==> shortest string that yields d when read in
-			and rounded to nearest.
-		1 ==> like 0, but with Steele & White stopping rule;
-			e.g. with IEEE P754 arithmetic , mode 0 gives
-			1e23 whereas mode 1 gives 9.999999999999999e22.
-		2 ==> max(1,ndigits) significant digits.  This gives a
-			return value similar to that of ecvt, except
-			that trailing zeros are suppressed.
-		3 ==> through ndigits past the decimal point.  This
-			gives a return value similar to that from fcvt,
-			except that trailing zeros are suppressed, and
-			ndigits can be negative.
-		4,5 ==> similar to 2 and 3, respectively, but (in
-			round-nearest mode) with the tests of mode 0 to
-			possibly return a shorter string that rounds to d.
-			With IEEE arithmetic and compilation with
-			-DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
-			as modes 2 and 3 when FLT_ROUNDS != 1.
-		6-9 ==> Debugging modes similar to mode - 4:  don't try
-			fast floating-point estimate (if applicable).
-
-		Values of mode other than 0-9 are treated as mode 0.
-
-		Sufficient space is allocated to the return value
-		to hold the suppressed trailing zeros.
-	*/
-
-	int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
-		j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
-		spec_case, try_quick, bias_round_up;
-	Long L;
-#ifndef Sudden_Underflow
-	int denorm;
-	ULong x;
-#endif
-	Bigint *b, *b1, *delta, *mlo, *mhi, *S;
-        double ds;
-	U d2, eps;
-	char *s, *s0;
-#ifdef Honor_FLT_ROUNDS
-	int rounding;
-#endif
-#ifdef SET_INEXACT
-	int inexact, oldinexact;
-#endif
-        U d;
-        dval(d) = dd;
-
-        /* In mode 2 and 3 we bias rounding up when there are ties. */
-        bias_round_up = mode == 2 || mode == 3;
-
-        ilim = ilim1 = 0; /* to avoid Google3 compiler warnings */
-
-#ifndef MULTIPLE_THREADS
-	if (dtoa_result) {
-		freedtoa(dtoa_result);
-		dtoa_result = 0;
-		}
-#endif
-
-	if (word0(d) & Sign_bit) {
-		/* set sign for everything, including 0's and NaNs */
-		*sign = 1;
-		word0(d) &= ~Sign_bit;	/* clear sign bit */
-		}
-	else
-		*sign = 0;
-
-#if defined(IEEE_Arith) + defined(VAX)
-#ifdef IEEE_Arith
-	if ((word0(d) & Exp_mask) == Exp_mask)
-#else
-	if (word0(d)  == 0x8000)
-#endif
-		{
-		/* Infinity or NaN */
-		*decpt = 9999;
-#ifdef IEEE_Arith
-		if (!word1(d) && !(word0(d) & 0xfffff))
-			return nrv_alloc("Infinity", rve, 8);
-#endif
-		return nrv_alloc("NaN", rve, 3);
-		}
-#endif
-#ifdef IBM
-	dval(d) += 0; /* normalize */
-#endif
-	if (!dval(d)) {
-		*decpt = 1;
-		return nrv_alloc("0", rve, 1);
-		}
-
-#ifdef SET_INEXACT
-	try_quick = oldinexact = get_inexact();
-	inexact = 1;
-#endif
-#ifdef Honor_FLT_ROUNDS
-	if ((rounding = Flt_Rounds) >= 2) {
-		if (*sign)
-			rounding = rounding == 2 ? 0 : 2;
-		else
-			if (rounding != 2)
-				rounding = 0;
-		}
-#endif
-
-	b = d2b(dval(d), &be, &bbits);
-#ifdef Sudden_Underflow
-	i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
-#else
-	if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) {
-#endif
-		dval(d2) = dval(d);
-		word0(d2) &= Frac_mask1;
-		word0(d2) |= Exp_11;
-#ifdef IBM
-		if (j = 11 - hi0bits(word0(d2) & Frac_mask))
-			dval(d2) /= 1 << j;
-#endif
-
-		/* log(x)	~=~ log(1.5) + (x-1.5)/1.5
-		 * log10(x)	 =  log(x) / log(10)
-		 *		~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
-		 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
-		 *
-		 * This suggests computing an approximation k to log10(d) by
-		 *
-		 * k = (i - Bias)*0.301029995663981
-		 *	+ ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
-		 *
-		 * We want k to be too large rather than too small.
-		 * The error in the first-order Taylor series approximation
-		 * is in our favor, so we just round up the constant enough
-		 * to compensate for any error in the multiplication of
-		 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
-		 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
-		 * adding 1e-13 to the constant term more than suffices.
-		 * Hence we adjust the constant term to 0.1760912590558.
-		 * (We could get a more accurate k by invoking log10,
-		 *  but this is probably not worthwhile.)
-		 */
-
-		i -= Bias;
-#ifdef IBM
-		i <<= 2;
-		i += j;
-#endif
-#ifndef Sudden_Underflow
-		denorm = 0;
-		}
-	else {
-		/* d is denormalized */
-
-		i = bbits + be + (Bias + (P-1) - 1);
-		x = i > 32  ? (word0(d) << (64 - i)) | (word1(d) >> (i - 32))
-			    : word1(d) << (32 - i);
-		dval(d2) = x;
-		word0(d2) -= 31*Exp_msk1; /* adjust exponent */
-		i -= (Bias + (P-1) - 1) + 1;
-		denorm = 1;
-		}
-#endif
-	ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
-	k = (int)ds;
-	if (ds < 0. && ds != k)
-		k--;	/* want k = floor(ds) */
-	k_check = 1;
-	if (k >= 0 && k <= Ten_pmax) {
-		if (dval(d) < tens[k])
-			k--;
-		k_check = 0;
-		}
-	j = bbits - i - 1;
-	if (j >= 0) {
-		b2 = 0;
-		s2 = j;
-		}
-	else {
-		b2 = -j;
-		s2 = 0;
-		}
-	if (k >= 0) {
-		b5 = 0;
-		s5 = k;
-		s2 += k;
-		}
-	else {
-		b2 -= k;
-		b5 = -k;
-		s5 = 0;
-		}
-	if (mode < 0 || mode > 9)
-		mode = 0;
-
-#ifndef SET_INEXACT
-#ifdef Check_FLT_ROUNDS
-	try_quick = Rounding == 1;
-#else
-	try_quick = 1;
-#endif
-#endif /*SET_INEXACT*/
-
-	if (mode > 5) {
-		mode -= 4;
-		try_quick = 0;
-		}
-	leftright = 1;
-	switch(mode) {
-		case 0:
-		case 1:
-			ilim = ilim1 = -1;
-			i = 18;
-			ndigits = 0;
-			break;
-		case 2:
-			leftright = 0;
-			/* no break */
-		case 4:
-			if (ndigits <= 0)
-				ndigits = 1;
-			ilim = ilim1 = i = ndigits;
-			break;
-		case 3:
-			leftright = 0;
-			/* no break */
-		case 5:
-			i = ndigits + k + 1;
-			ilim = i;
-			ilim1 = i - 1;
-			if (i <= 0)
-				i = 1;
-		}
-	s = s0 = rv_alloc(i);
-
-#ifdef Honor_FLT_ROUNDS
-	if (mode > 1 && rounding != 1)
-		leftright = 0;
-#endif
-
-	if (ilim >= 0 && ilim <= Quick_max && try_quick) {
-
-		/* Try to get by with floating-point arithmetic. */
-
-		i = 0;
-		dval(d2) = dval(d);
-		k0 = k;
-		ilim0 = ilim;
-		ieps = 2; /* conservative */
-		if (k > 0) {
-			ds = tens[k&0xf];
-			j = k >> 4;
-			if (j & Bletch) {
-				/* prevent overflows */
-				j &= Bletch - 1;
-				dval(d) /= bigtens[n_bigtens-1];
-				ieps++;
-				}
-			for(; j; j >>= 1, i++)
-				if (j & 1) {
-					ieps++;
-					ds *= bigtens[i];
-					}
-			dval(d) /= ds;
-			}
-		else if ((j1 = -k)) {
-			dval(d) *= tens[j1 & 0xf];
-			for(j = j1 >> 4; j; j >>= 1, i++)
-				if (j & 1) {
-					ieps++;
-					dval(d) *= bigtens[i];
-					}
-			}
-		if (k_check && dval(d) < 1. && ilim > 0) {
-			if (ilim1 <= 0)
-				goto fast_failed;
-			ilim = ilim1;
-			k--;
-			dval(d) *= 10.;
-			ieps++;
-			}
-		dval(eps) = ieps*dval(d) + 7.;
-		word0(eps) -= (P-1)*Exp_msk1;
-		if (ilim == 0) {
-			S = mhi = 0;
-			dval(d) -= 5.;
-			if (dval(d) > dval(eps))
-				goto one_digit;
-			if (dval(d) < -dval(eps))
-				goto no_digits;
-			goto fast_failed;
-			}
-#ifndef No_leftright
-		if (leftright) {
-			/* Use Steele & White method of only
-			 * generating digits needed.
-			 */
-			dval(eps) = 0.5/tens[ilim-1] - dval(eps);
-			for(i = 0;;) {
-				L = dval(d);
-				dval(d) -= L;
-				*s++ = '0' + (int)L;
-				if (dval(d) < dval(eps))
-					goto ret1;
-				if (1. - dval(d) < dval(eps))
-					goto bump_up;
-				if (++i >= ilim)
-					break;
-				dval(eps) *= 10.;
-				dval(d) *= 10.;
-				}
-			}
-		else {
-#endif
-			/* Generate ilim digits, then fix them up. */
-			dval(eps) *= tens[ilim-1];
-			for(i = 1;; i++, dval(d) *= 10.) {
-				L = (Long)(dval(d));
-				if (!(dval(d) -= L))
-					ilim = i;
-				*s++ = '0' + (int)L;
-				if (i == ilim) {
-					if (dval(d) > 0.5 + dval(eps))
-						goto bump_up;
-					else if (dval(d) < 0.5 - dval(eps)) {
-						while(*--s == '0');
-						s++;
-						goto ret1;
-						}
-					break;
-					}
-				}
-#ifndef No_leftright
-			}
-#endif
- fast_failed:
-		s = s0;
-		dval(d) = dval(d2);
-		k = k0;
-		ilim = ilim0;
-		}
-
-	/* Do we have a "small" integer? */
-
-	if (be >= 0 && k <= Int_max) {
-		/* Yes. */
-		ds = tens[k];
-		if (ndigits < 0 && ilim <= 0) {
-			S = mhi = 0;
-			if (ilim < 0 || dval(d) < 5*ds || ((dval(d) == 5*ds) && !bias_round_up))
-				goto no_digits;
-			goto one_digit;
-			}
-
-                /* Limit looping by the number of digits to produce.
-                 * Firefox had a crash bug because some plugins reduce
-                 * the precision of double arithmetic.  With reduced
-                 * precision "dval(d) -= L*ds" might be imprecise and
-                 * d might not become zero and the loop might not
-                 * terminate.
-                 *
-                 * See https://bugzilla.mozilla.org/show_bug.cgi?id=358569
-                 */
-		for(i = 1; i <= k+1; i++, dval(d) *= 10.) {
-			L = (Long)(dval(d) / ds);
-			dval(d) -= L*ds;
-#ifdef Check_FLT_ROUNDS
-			/* If FLT_ROUNDS == 2, L will usually be high by 1 */
-			if (dval(d) < 0) {
-				L--;
-				dval(d) += ds;
-				}
-#endif
-			*s++ = '0' + (int)L;
-			if (!dval(d)) {
-#ifdef SET_INEXACT
-				inexact = 0;
-#endif
-				break;
-				}
-			if (i == ilim) {
-#ifdef Honor_FLT_ROUNDS
-				if (mode > 1)
-				switch(rounding) {
-				  case 0: goto ret1;
-				  case 2: goto bump_up;
-				  }
-#endif
-				dval(d) += dval(d);
-				if (dval(d) > ds || (dval(d) == ds && ((L & 1) || bias_round_up))) {
- bump_up:
-					while(*--s == '9')
-						if (s == s0) {
-							k++;
-							*s = '0';
-							break;
-							}
-					++*s++;
-					}
-				break;
-				}
-			}
-		goto ret1;
-		}
-
-	m2 = b2;
-	m5 = b5;
-	mhi = mlo = 0;
-	if (leftright) {
-		i =
-#ifndef Sudden_Underflow
-			denorm ? be + (Bias + (P-1) - 1 + 1) :
-#endif
-#ifdef IBM
-			1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
-#else
-			1 + P - bbits;
-#endif
-		b2 += i;
-		s2 += i;
-		mhi = i2b(1);
-		}
-	if (m2 > 0 && s2 > 0) {
-		i = m2 < s2 ? m2 : s2;
-		b2 -= i;
-		m2 -= i;
-		s2 -= i;
-		}
-	if (b5 > 0) {
-		if (leftright) {
-			if (m5 > 0) {
-				mhi = pow5mult(mhi, m5);
-				b1 = mult(mhi, b);
-				Bfree(b);
-				b = b1;
-				}
-			if ((j = b5 - m5))
-				b = pow5mult(b, j);
-			}
-		else
-			b = pow5mult(b, b5);
-		}
-	S = i2b(1);
-	if (s5 > 0)
-		S = pow5mult(S, s5);
-
-	/* Check for special case that d is a normalized power of 2. */
-
-	spec_case = 0;
-	if ((mode < 2 || leftright)
-#ifdef Honor_FLT_ROUNDS
-			&& rounding == 1
-#endif
-				) {
-		if (!word1(d) && !(word0(d) & Bndry_mask)
-#ifndef Sudden_Underflow
-		 && word0(d) & (Exp_mask & ~Exp_msk1)
-#endif
-				) {
-			/* The special case */
-			b2 += Log2P;
-			s2 += Log2P;
-			spec_case = 1;
-			}
-		}
-
-	/* Arrange for convenient computation of quotients:
-	 * shift left if necessary so divisor has 4 leading 0 bits.
-	 *
-	 * Perhaps we should just compute leading 28 bits of S once
-	 * and for all and pass them and a shift to quorem, so it
-	 * can do shifts and ors to compute the numerator for q.
-	 */
-#ifdef Pack_32
-	if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f))
-		i = 32 - i;
-#else
-	if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf))
-		i = 16 - i;
-#endif
-	if (i > 4) {
-		i -= 4;
-		b2 += i;
-		m2 += i;
-		s2 += i;
-		}
-	else if (i < 4) {
-		i += 28;
-		b2 += i;
-		m2 += i;
-		s2 += i;
-		}
-	if (b2 > 0)
-		b = lshift(b, b2);
-	if (s2 > 0)
-		S = lshift(S, s2);
-	if (k_check) {
-		if (cmp(b,S) < 0) {
-			k--;
-			b = multadd(b, 10, 0);	/* we botched the k estimate */
-			if (leftright)
-				mhi = multadd(mhi, 10, 0);
-			ilim = ilim1;
-			}
-		}
-	if (ilim <= 0 && (mode == 3 || mode == 5)) {
-                S = multadd(S, 5, 0);
-		if (ilim < 0 || cmp(b, S) < 0 || ((cmp(b, S) == 0) && !bias_round_up)) {
-			/* no digits, fcvt style */
- no_digits:
-			k = -1 - ndigits;
-			goto ret;
-			}
- one_digit:
-		*s++ = '1';
-		k++;
-		goto ret;
-		}
-	if (leftright) {
-		if (m2 > 0)
-			mhi = lshift(mhi, m2);
-
-		/* Compute mlo -- check for special case
-		 * that d is a normalized power of 2.
-		 */
-
-		mlo = mhi;
-		if (spec_case) {
-			mhi = Balloc(mhi->k);
-			Bcopy(mhi, mlo);
-			mhi = lshift(mhi, Log2P);
-			}
-
-		for(i = 1;;i++) {
-			dig = quorem(b,S) + '0';
-			/* Do we yet have the shortest decimal string
-			 * that will round to d?
-			 */
-			j = cmp(b, mlo);
-			delta = diff(S, mhi);
-			j1 = delta->sign ? 1 : cmp(b, delta);
-			Bfree(delta);
-#ifndef ROUND_BIASED
-			if (j1 == 0 && mode != 1 && !(word1(d) & 1)
-#ifdef Honor_FLT_ROUNDS
-				&& rounding >= 1
-#endif
-								   ) {
-				if (dig == '9')
-					goto round_9_up;
-				if (j > 0)
-					dig++;
-#ifdef SET_INEXACT
-				else if (!b->x[0] && b->wds <= 1)
-					inexact = 0;
-#endif
-				*s++ = dig;
-				goto ret;
-				}
-#endif
-			if (j < 0 || (j == 0 && mode != 1
-#ifndef ROUND_BIASED
-							&& !(word1(d) & 1)
-#endif
-					)) {
-				if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
-					inexact = 0;
-#endif
-					goto accept_dig;
-					}
-#ifdef Honor_FLT_ROUNDS
-				if (mode > 1)
-				 switch(rounding) {
-				  case 0: goto accept_dig;
-				  case 2: goto keep_dig;
-				  }
-#endif /*Honor_FLT_ROUNDS*/
-				if (j1 > 0) {
-					b = lshift(b, 1);
-					j1 = cmp(b, S);
-					if ((j1 > 0 || (j1 == 0 && ((dig & 1) || bias_round_up)))
-                                            && dig++ == '9')
-						goto round_9_up;
-					}
- accept_dig:
-				*s++ = dig;
-				goto ret;
-				}
-			if (j1 > 0) {
-#ifdef Honor_FLT_ROUNDS
-				if (!rounding)
-					goto accept_dig;
-#endif
-				if (dig == '9') { /* possible if i == 1 */
- round_9_up:
-					*s++ = '9';
-					goto roundoff;
-					}
-				*s++ = dig + 1;
-				goto ret;
-				}
-#ifdef Honor_FLT_ROUNDS
- keep_dig:
-#endif
-			*s++ = dig;
-			if (i == ilim)
-				break;
-			b = multadd(b, 10, 0);
-			if (mlo == mhi)
-				mlo = mhi = multadd(mhi, 10, 0);
-			else {
-				mlo = multadd(mlo, 10, 0);
-				mhi = multadd(mhi, 10, 0);
-				}
-			}
-		}
-	else
-		for(i = 1;; i++) {
-			*s++ = dig = quorem(b,S) + '0';
-			if (!b->x[0] && b->wds <= 1) {
-#ifdef SET_INEXACT
-				inexact = 0;
-#endif
-				goto ret;
-				}
-			if (i >= ilim)
-				break;
-			b = multadd(b, 10, 0);
-			}
-
-	/* Round off last digit */
-
-#ifdef Honor_FLT_ROUNDS
-	switch(rounding) {
-	  case 0: goto trimzeros;
-	  case 2: goto roundoff;
-	  }
-#endif
-	b = lshift(b, 1);
-	j = cmp(b, S);
-	if (j > 0 || (j == 0 && ((dig & 1) || bias_round_up))) {
- roundoff:
-		while(*--s == '9')
-			if (s == s0) {
-				k++;
-				*s++ = '1';
-				goto ret;
-				}
-		++*s++;
-		}
-	else {
-/* trimzeros:  (never used) */
-		while(*--s == '0');
-		s++;
-		}
- ret:
-	Bfree(S);
-	if (mhi) {
-		if (mlo && mlo != mhi)
-			Bfree(mlo);
-		Bfree(mhi);
-		}
- ret1:
-#ifdef SET_INEXACT
-	if (inexact) {
-		if (!oldinexact) {
-			word0(d) = Exp_1 + (70 << Exp_shift);
-			word1(d) = 0;
-			dval(d) += 1.;
-			}
-		}
-	else if (!oldinexact)
-		clear_inexact();
-#endif
-	Bfree(b);
-	*s = 0;
-	*decpt = k + 1;
-	if (rve)
-		*rve = s;
-	return s0;
-	}
-#ifdef __cplusplus
-}
-#endif
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/utils.h b/src/utils.h
index 069be4f..69c062f 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -31,7 +31,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "globals.h"
 #include "checks.h"
+#include "allocation.h"
 
 namespace v8 {
 namespace internal {
@@ -324,6 +326,8 @@
     return start_[index];
   }
 
+  T& at(int i) const { return operator[](i); }
+
   T& first() { return start_[0]; }
 
   T& last() { return start_[length_ - 1]; }
diff --git a/src/v8.cc b/src/v8.cc
index 0623400..c8d719b 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -44,6 +44,7 @@
 bool V8::has_been_disposed_ = false;
 bool V8::has_fatal_error_ = false;
 
+
 bool V8::Initialize(Deserializer* des) {
   bool create_heap_objects = des == NULL;
   if (has_been_disposed_ || has_fatal_error_) return false;
@@ -176,22 +177,41 @@
 }
 
 
-uint32_t V8::Random() {
-  // Random number generator using George Marsaglia's MWC algorithm.
-  static uint32_t hi = 0;
-  static uint32_t lo = 0;
+typedef struct {
+  uint32_t hi;
+  uint32_t lo;
+} random_state;
 
+
+// Random number generator using George Marsaglia's MWC algorithm.
+static uint32_t random_base(random_state *state) {
   // Initialize seed using the system random(). If one of the seeds
   // should ever become zero again, or if random() returns zero, we
   // avoid getting stuck with zero bits in hi or lo by re-initializing
   // them on demand.
-  if (hi == 0) hi = random_seed();
-  if (lo == 0) lo = random_seed();
+  if (state->hi == 0) state->hi = random_seed();
+  if (state->lo == 0) state->lo = random_seed();
 
   // Mix the bits.
-  hi = 36969 * (hi & 0xFFFF) + (hi >> 16);
-  lo = 18273 * (lo & 0xFFFF) + (lo >> 16);
-  return (hi << 16) + (lo & 0xFFFF);
+  state->hi = 36969 * (state->hi & 0xFFFF) + (state->hi >> 16);
+  state->lo = 18273 * (state->lo & 0xFFFF) + (state->lo >> 16);
+  return (state->hi << 16) + (state->lo & 0xFFFF);
+}
+
+
+// Used by JavaScript APIs
+uint32_t V8::Random() {
+  static random_state state = {0, 0};
+  return random_base(&state);
+}
+
+
+// Used internally by the JIT and memory allocator for security
+// purposes. So, we keep a different state to prevent informations
+// leaks that could be used in an exploit.
+uint32_t V8::RandomPrivate() {
+  static random_state state = {0, 0};
+  return random_base(&state);
 }
 
 
diff --git a/src/v8.h b/src/v8.h
index 1cb8d2f..a2313b0 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -53,8 +53,8 @@
 
 // Basic includes
 #include "../include/v8.h"
-#include "globals.h"
-#include "checks.h"
+#include "v8globals.h"
+#include "v8checks.h"
 #include "allocation.h"
 #include "v8utils.h"
 #include "flags.h"
@@ -94,6 +94,11 @@
 
   // Random number generation support. Not cryptographically safe.
   static uint32_t Random();
+  // We use random numbers internally in memory allocation and in the
+  // compilers for security. In order to prevent information leaks we
+  // use a separate random state for internal random number
+  // generation.
+  static uint32_t RandomPrivate();
   static Object* FillHeapNumberWithRandom(Object* heap_number);
 
   // Idle notification directly from the API.
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/v8globals.h b/src/v8globals.h
new file mode 100644
index 0000000..2815771
--- /dev/null
+++ b/src/v8globals.h
@@ -0,0 +1,464 @@
+// 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_V8GLOBALS_H_
+#define V8_V8GLOBALS_H_
+
+#include "globals.h"
+
+namespace v8 {
+namespace internal {
+
+// This file contains constants and global declarations related to the
+// V8 system.
+
+// Mask for the sign bit in a smi.
+const intptr_t kSmiSignMask = kIntptrSignBit;
+
+const int kObjectAlignmentBits = kPointerSizeLog2;
+const intptr_t kObjectAlignment = 1 << kObjectAlignmentBits;
+const intptr_t kObjectAlignmentMask = kObjectAlignment - 1;
+
+// Desired alignment for pointers.
+const intptr_t kPointerAlignment = (1 << kPointerSizeLog2);
+const intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
+
+// Desired alignment for maps.
+#if V8_HOST_ARCH_64_BIT
+const intptr_t kMapAlignmentBits = kObjectAlignmentBits;
+#else
+const intptr_t kMapAlignmentBits = kObjectAlignmentBits + 3;
+#endif
+const intptr_t kMapAlignment = (1 << kMapAlignmentBits);
+const intptr_t kMapAlignmentMask = kMapAlignment - 1;
+
+// Desired alignment for generated code is 32 bytes (to improve cache line
+// utilization).
+const int kCodeAlignmentBits = 5;
+const intptr_t kCodeAlignment = 1 << kCodeAlignmentBits;
+const intptr_t kCodeAlignmentMask = kCodeAlignment - 1;
+
+// Tag information for Failure.
+const int kFailureTag = 3;
+const int kFailureTagSize = 2;
+const intptr_t kFailureTagMask = (1 << kFailureTagSize) - 1;
+
+
+// Zap-value: The value used for zapping dead objects.
+// Should be a recognizable hex value tagged as a heap object pointer.
+#ifdef V8_HOST_ARCH_64_BIT
+const Address kZapValue =
+    reinterpret_cast<Address>(V8_UINT64_C(0xdeadbeedbeadbeed));
+const Address kHandleZapValue =
+    reinterpret_cast<Address>(V8_UINT64_C(0x1baddead0baddead));
+const Address kFromSpaceZapValue =
+    reinterpret_cast<Address>(V8_UINT64_C(0x1beefdad0beefdad));
+const uint64_t kDebugZapValue = 0xbadbaddbbadbaddb;
+#else
+const Address kZapValue = reinterpret_cast<Address>(0xdeadbeed);
+const Address kHandleZapValue = reinterpret_cast<Address>(0xbaddead);
+const Address kFromSpaceZapValue = reinterpret_cast<Address>(0xbeefdad);
+const uint32_t kDebugZapValue = 0xbadbaddb;
+#endif
+
+
+// Number of bits to represent the page size for paged spaces. The value of 13
+// gives 8K bytes per page.
+const int kPageSizeBits = 13;
+
+// On Intel architecture, cache line size is 64 bytes.
+// On ARM it may be less (32 bytes), but as far this constant is
+// used for aligning data, it doesn't hurt to align on a greater value.
+const int kProcessorCacheLineSize = 64;
+
+// Constants relevant to double precision floating point numbers.
+
+// Quiet NaNs have bits 51 to 62 set, possibly the sign bit, and no
+// other bits set.
+const uint64_t kQuietNaNMask = static_cast<uint64_t>(0xfff) << 51;
+// If looking only at the top 32 bits, the QNaN mask is bits 19 to 30.
+const uint32_t kQuietNaNHighBitsMask = 0xfff << (51 - 32);
+
+
+// -----------------------------------------------------------------------------
+// Forward declarations for frequently used classes
+// (sorted alphabetically)
+
+class AccessorInfo;
+class Allocation;
+class Arguments;
+class Assembler;
+class AssertNoAllocation;
+class BreakableStatement;
+class Code;
+class CodeGenerator;
+class CodeStub;
+class Context;
+class Debug;
+class Debugger;
+class DebugInfo;
+class Descriptor;
+class DescriptorArray;
+class Expression;
+class ExternalReference;
+class FixedArray;
+class FunctionEntry;
+class FunctionLiteral;
+class FunctionTemplateInfo;
+class NumberDictionary;
+class StringDictionary;
+template <typename T> class Handle;
+class Heap;
+class HeapObject;
+class IC;
+class InterceptorInfo;
+class IterationStatement;
+class JSArray;
+class JSFunction;
+class JSObject;
+class LargeObjectSpace;
+class LookupResult;
+class MacroAssembler;
+class Map;
+class MapSpace;
+class MarkCompactCollector;
+class NewSpace;
+class NodeVisitor;
+class Object;
+class MaybeObject;
+class OldSpace;
+class Property;
+class Proxy;
+class RegExpNode;
+struct RegExpCompileData;
+class RegExpTree;
+class RegExpCompiler;
+class RegExpVisitor;
+class Scope;
+template<class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
+class SerializedScopeInfo;
+class Script;
+class Slot;
+class Smi;
+template <typename Config, class Allocator = FreeStoreAllocationPolicy>
+    class SplayTree;
+class Statement;
+class String;
+class Struct;
+class SwitchStatement;
+class AstVisitor;
+class Variable;
+class VariableProxy;
+class RelocInfo;
+class Deserializer;
+class MessageLocation;
+class ObjectGroup;
+class TickSample;
+class VirtualMemory;
+class Mutex;
+
+typedef bool (*WeakSlotCallback)(Object** pointer);
+
+// -----------------------------------------------------------------------------
+// Miscellaneous
+
+// NOTE: SpaceIterator depends on AllocationSpace enumeration values being
+// consecutive.
+enum AllocationSpace {
+  NEW_SPACE,            // Semispaces collected with copying collector.
+  OLD_POINTER_SPACE,    // May contain pointers to new space.
+  OLD_DATA_SPACE,       // Must not have pointers to new space.
+  CODE_SPACE,           // No pointers to new space, marked executable.
+  MAP_SPACE,            // Only and all map objects.
+  CELL_SPACE,           // Only and all cell objects.
+  LO_SPACE,             // Promoted large objects.
+
+  FIRST_SPACE = NEW_SPACE,
+  LAST_SPACE = LO_SPACE,
+  FIRST_PAGED_SPACE = OLD_POINTER_SPACE,
+  LAST_PAGED_SPACE = CELL_SPACE
+};
+const int kSpaceTagSize = 3;
+const int kSpaceTagMask = (1 << kSpaceTagSize) - 1;
+
+
+// A flag that indicates whether objects should be pretenured when
+// allocated (allocated directly into the old generation) or not
+// (allocated in the young generation if the object size and type
+// allows).
+enum PretenureFlag { NOT_TENURED, TENURED };
+
+enum GarbageCollector { SCAVENGER, MARK_COMPACTOR };
+
+enum Executability { NOT_EXECUTABLE, EXECUTABLE };
+
+enum VisitMode { VISIT_ALL, VISIT_ALL_IN_SCAVENGE, VISIT_ONLY_STRONG };
+
+// Flag indicating whether code is built into the VM (one of the natives files).
+enum NativesFlag { NOT_NATIVES_CODE, NATIVES_CODE };
+
+
+// A CodeDesc describes a buffer holding instructions and relocation
+// information. The instructions start at the beginning of the buffer
+// and grow forward, the relocation information starts at the end of
+// the buffer and grows backward.
+//
+//  |<--------------- buffer_size ---------------->|
+//  |<-- instr_size -->|        |<-- reloc_size -->|
+//  +==================+========+==================+
+//  |   instructions   |  free  |    reloc info    |
+//  +==================+========+==================+
+//  ^
+//  |
+//  buffer
+
+struct CodeDesc {
+  byte* buffer;
+  int buffer_size;
+  int instr_size;
+  int reloc_size;
+  Assembler* origin;
+};
+
+
+// Callback function on object slots, used for iterating heap object slots in
+// HeapObjects, global pointers to heap objects, etc. The callback allows the
+// callback function to change the value of the slot.
+typedef void (*ObjectSlotCallback)(HeapObject** pointer);
+
+
+// Callback function used for iterating objects in heap spaces,
+// for example, scanning heap objects.
+typedef int (*HeapObjectCallback)(HeapObject* obj);
+
+
+// Callback function used for checking constraints when copying/relocating
+// objects. Returns true if an object can be copied/relocated from its
+// old_addr to a new_addr.
+typedef bool (*ConstraintCallback)(Address new_addr, Address old_addr);
+
+
+// Callback function on inline caches, used for iterating over inline caches
+// in compiled code.
+typedef void (*InlineCacheCallback)(Code* code, Address ic);
+
+
+// State for inline cache call sites. Aliased as IC::State.
+enum InlineCacheState {
+  // Has never been executed.
+  UNINITIALIZED,
+  // Has been executed but monomorhic state has been delayed.
+  PREMONOMORPHIC,
+  // Has been executed and only one receiver type has been seen.
+  MONOMORPHIC,
+  // Like MONOMORPHIC but check failed due to prototype.
+  MONOMORPHIC_PROTOTYPE_FAILURE,
+  // Multiple receiver types have been seen.
+  MEGAMORPHIC,
+  // Special states for debug break or step in prepare stubs.
+  DEBUG_BREAK,
+  DEBUG_PREPARE_STEP_IN
+};
+
+
+enum InLoopFlag {
+  NOT_IN_LOOP,
+  IN_LOOP
+};
+
+
+enum CallFunctionFlags {
+  NO_CALL_FUNCTION_FLAGS = 0,
+  RECEIVER_MIGHT_BE_VALUE = 1 << 0  // Receiver might not be a JSObject.
+};
+
+
+enum InlineCacheHolderFlag {
+  OWN_MAP,  // For fast properties objects.
+  PROTOTYPE_MAP  // For slow properties objects (except GlobalObjects).
+};
+
+
+// Type of properties.
+// Order of properties is significant.
+// Must fit in the BitField PropertyDetails::TypeField.
+// A copy of this is in mirror-debugger.js.
+enum PropertyType {
+  NORMAL              = 0,  // only in slow mode
+  FIELD               = 1,  // only in fast mode
+  CONSTANT_FUNCTION   = 2,  // only in fast mode
+  CALLBACKS           = 3,
+  INTERCEPTOR         = 4,  // only in lookup results, not in descriptors.
+  MAP_TRANSITION      = 5,  // only in fast mode
+  CONSTANT_TRANSITION = 6,  // only in fast mode
+  NULL_DESCRIPTOR     = 7,  // only in fast mode
+  // All properties before MAP_TRANSITION are real.
+  FIRST_PHANTOM_PROPERTY_TYPE = MAP_TRANSITION,
+  // There are no IC stubs for NULL_DESCRIPTORS. Therefore,
+  // NULL_DESCRIPTOR can be used as the type flag for IC stubs for
+  // nonexistent properties.
+  NONEXISTENT = NULL_DESCRIPTOR
+};
+
+
+// Whether to remove map transitions and constant transitions from a
+// DescriptorArray.
+enum TransitionFlag {
+  REMOVE_TRANSITIONS,
+  KEEP_TRANSITIONS
+};
+
+
+// Union used for fast testing of specific double values.
+union DoubleRepresentation {
+  double  value;
+  int64_t bits;
+  DoubleRepresentation(double x) { value = x; }
+};
+
+
+// Union used for customized checking of the IEEE double types
+// inlined within v8 runtime, rather than going to the underlying
+// platform headers and libraries
+union IeeeDoubleLittleEndianArchType {
+  double d;
+  struct {
+    unsigned int man_low  :32;
+    unsigned int man_high :20;
+    unsigned int exp      :11;
+    unsigned int sign     :1;
+  } bits;
+};
+
+
+union IeeeDoubleBigEndianArchType {
+  double d;
+  struct {
+    unsigned int sign     :1;
+    unsigned int exp      :11;
+    unsigned int man_high :20;
+    unsigned int man_low  :32;
+  } bits;
+};
+
+
+// AccessorCallback
+struct AccessorDescriptor {
+  MaybeObject* (*getter)(Object* object, void* data);
+  MaybeObject* (*setter)(JSObject* object, Object* value, void* data);
+  void* data;
+};
+
+
+// Logging and profiling.
+// A StateTag represents a possible state of the VM.  When compiled with
+// ENABLE_VMSTATE_TRACKING, the logger maintains a stack of these.
+// Creating a VMState object enters a state by pushing on the stack, and
+// destroying a VMState object leaves a state by popping the current state
+// from the stack.
+
+#define STATE_TAG_LIST(V) \
+  V(JS)                   \
+  V(GC)                   \
+  V(COMPILER)             \
+  V(OTHER)                \
+  V(EXTERNAL)
+
+enum StateTag {
+#define DEF_STATE_TAG(name) name,
+  STATE_TAG_LIST(DEF_STATE_TAG)
+#undef DEF_STATE_TAG
+  // Pseudo-types.
+  state_tag_count
+};
+
+
+// -----------------------------------------------------------------------------
+// Macros
+
+// Testers for test.
+
+#define HAS_SMI_TAG(value) \
+  ((reinterpret_cast<intptr_t>(value) & kSmiTagMask) == kSmiTag)
+
+#define HAS_FAILURE_TAG(value) \
+  ((reinterpret_cast<intptr_t>(value) & kFailureTagMask) == kFailureTag)
+
+// OBJECT_POINTER_ALIGN returns the value aligned as a HeapObject pointer
+#define OBJECT_POINTER_ALIGN(value)                             \
+  (((value) + kObjectAlignmentMask) & ~kObjectAlignmentMask)
+
+// POINTER_SIZE_ALIGN returns the value aligned as a pointer.
+#define POINTER_SIZE_ALIGN(value)                               \
+  (((value) + kPointerAlignmentMask) & ~kPointerAlignmentMask)
+
+// MAP_POINTER_ALIGN returns the value aligned as a map pointer.
+#define MAP_POINTER_ALIGN(value)                                \
+  (((value) + kMapAlignmentMask) & ~kMapAlignmentMask)
+
+// CODE_POINTER_ALIGN returns the value aligned as a generated code segment.
+#define CODE_POINTER_ALIGN(value)                               \
+  (((value) + kCodeAlignmentMask) & ~kCodeAlignmentMask)
+
+// Support for tracking C++ memory allocation.  Insert TRACK_MEMORY("Fisk")
+// inside a C++ class and new and delete will be overloaded so logging is
+// performed.
+// This file (globals.h) is included before log.h, so we use direct calls to
+// the Logger rather than the LOG macro.
+#ifdef DEBUG
+#define TRACK_MEMORY(name) \
+  void* operator new(size_t size) { \
+    void* result = ::operator new(size); \
+    Logger::NewEvent(name, result, size); \
+    return result; \
+  } \
+  void operator delete(void* object) { \
+    Logger::DeleteEvent(name, object); \
+    ::operator delete(object); \
+  }
+#else
+#define TRACK_MEMORY(name)
+#endif
+
+
+// Feature flags bit positions. They are mostly based on the CPUID spec.
+// (We assign CPUID itself to one of the currently reserved bits --
+// feel free to change this if needed.)
+// On X86/X64, values below 32 are bits in EDX, values above 32 are bits in ECX.
+enum CpuFeature { SSE4_1 = 32 + 19,  // x86
+                  SSE3 = 32 + 0,     // x86
+                  SSE2 = 26,   // x86
+                  CMOV = 15,   // x86
+                  RDTSC = 4,   // x86
+                  CPUID = 10,  // x86
+                  VFP3 = 1,    // ARM
+                  ARMv7 = 2,   // ARM
+                  SAHF = 0};   // x86
+
+} }  // namespace v8::internal
+
+#endif  // V8_V8GLOBALS_H_
diff --git a/src/version.cc b/src/version.cc
index b45510c..6e5b68f 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     2
 #define MINOR_VERSION     5
-#define BUILD_NUMBER      6
-#define PATCH_LEVEL       0
+#define BUILD_NUMBER      9
+#define PATCH_LEVEL       1
 #define CANDIDATE_VERSION false
 
 // Define SONAME to have the SCons build the put a specific SONAME into the
diff --git a/src/virtual-frame.h b/src/virtual-frame.h
index 220823e..65d1009 100644
--- a/src/virtual-frame.h
+++ b/src/virtual-frame.h
@@ -31,6 +31,9 @@
 #include "frame-element.h"
 #include "macro-assembler.h"
 
+#include "list-inl.h"
+#include "utils.h"
+
 #if V8_TARGET_ARCH_IA32
 #include "ia32/virtual-frame-ia32.h"
 #elif V8_TARGET_ARCH_X64
@@ -43,4 +46,14 @@
 #error Unsupported target architecture.
 #endif
 
+namespace v8 {
+namespace internal {
+
+// Add() on List is inlined, ResizeAdd() called by Add() is inlined except for
+// Lists of FrameElements, and ResizeAddInternal() is inlined in ResizeAdd().
+template <>
+void List<FrameElement,
+          FreeStoreAllocationPolicy>::ResizeAdd(const FrameElement& element);
+} }  // namespace v8::internal
+
 #endif  // V8_VIRTUAL_FRAME_H_
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index c179769..14e3527 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -80,8 +80,9 @@
   __ pop(rdx);
   __ push(rsi);
   __ push(rdx);
+  __ Push(Factory::false_value());
   __ push(rcx);  // Restore return address.
-  __ TailCallRuntime(Runtime::kNewClosure, 2, 1);
+  __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
 }
 
 
@@ -2483,20 +2484,6 @@
 }
 
 
-void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
-  __ PrepareCallApiFunction(kStackSpace);
-#ifdef _WIN64
-  // All the parameters should be set up by a caller.
-#else
-  // Set 1st parameter register with property name.
-  __ movq(rsi, rdx);
-  // Second parameter register rdi should be set with pointer to AccessorInfo
-  // by a caller.
-#endif
-  __ CallApiFunctionAndReturn(fun());
-}
-
-
 void CEntryStub::GenerateCore(MacroAssembler* masm,
                               Label* throw_normal_exception,
                               Label* throw_termination_exception,
@@ -2549,18 +2536,18 @@
 #ifdef _WIN64
   // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9
   // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots.
-  __ movq(Operand(rsp, 4 * kPointerSize), r14);  // argc.
-  __ movq(Operand(rsp, 5 * kPointerSize), r12);  // argv.
+  __ movq(StackSpaceOperand(0), r14);  // argc.
+  __ movq(StackSpaceOperand(1), r12);  // argv.
   if (result_size_ < 2) {
     // Pass a pointer to the Arguments object as the first argument.
     // Return result in single register (rax).
-    __ lea(rcx, Operand(rsp, 4 * kPointerSize));
+    __ lea(rcx, StackSpaceOperand(0));
   } else {
     ASSERT_EQ(2, result_size_);
     // Pass a pointer to the result location as the first argument.
-    __ lea(rcx, Operand(rsp, 6 * kPointerSize));
+    __ lea(rcx, StackSpaceOperand(2));
     // Pass a pointer to the Arguments object as the second argument.
-    __ lea(rdx, Operand(rsp, 4 * kPointerSize));
+    __ lea(rdx, StackSpaceOperand(0));
   }
 
 #else  // _WIN64
@@ -2596,7 +2583,7 @@
   __ j(zero, &failure_returned);
 
   // Exit the JavaScript to C++ exit frame.
-  __ LeaveExitFrame(result_size_);
+  __ LeaveExitFrame();
   __ ret(0);
 
   // Handling of failure.
@@ -2700,7 +2687,12 @@
   // builtin once.
 
   // Enter the exit frame that transitions from JavaScript to C++.
-  __ EnterExitFrame(result_size_);
+#ifdef _WIN64
+  int arg_stack_space = (result_size_ < 2 ? 2 : 4);
+#else
+  int arg_stack_space = 0;
+#endif
+  __ EnterExitFrame(arg_stack_space);
 
   // rax: Holds the context at this point, but should not be used.
   //      On entry to code generated by GenerateCore, it must hold
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index e0e4095..5abf3c8 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -568,10 +568,10 @@
 
 void CodeGenerator::LoadGlobal() {
   if (in_spilled_code()) {
-    frame_->EmitPush(GlobalObject());
+    frame_->EmitPush(GlobalObjectOperand());
   } else {
     Result temp = allocator_->Allocate();
-    __ movq(temp.reg(), GlobalObject());
+    __ movq(temp.reg(), GlobalObjectOperand());
     frame_->Push(&temp);
   }
 }
@@ -580,7 +580,7 @@
 void CodeGenerator::LoadGlobalReceiver() {
   Result temp = allocator_->Allocate();
   Register reg = temp.reg();
-  __ movq(reg, GlobalObject());
+  __ movq(reg, GlobalObjectOperand());
   __ movq(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset));
   frame_->Push(&temp);
 }
@@ -4244,7 +4244,8 @@
 
 
 void CodeGenerator::InstantiateFunction(
-    Handle<SharedFunctionInfo> function_info) {
+    Handle<SharedFunctionInfo> function_info,
+    bool pretenure) {
   // The inevitable call will sync frame elements to memory anyway, so
   // we do it eagerly to allow us to push the arguments directly into
   // place.
@@ -4252,7 +4253,9 @@
 
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() && function_info->num_literals() == 0) {
+  if (scope()->is_function_scope() &&
+      function_info->num_literals() == 0 &&
+      !pretenure) {
     FastNewClosureStub stub;
     frame_->Push(function_info);
     Result answer = frame_->CallStub(&stub, 1);
@@ -4262,7 +4265,10 @@
     // shared function info.
     frame_->EmitPush(rsi);
     frame_->EmitPush(function_info);
-    Result result = frame_->CallRuntime(Runtime::kNewClosure, 2);
+    frame_->EmitPush(pretenure
+                     ? Factory::true_value()
+                     : Factory::false_value());
+    Result result = frame_->CallRuntime(Runtime::kNewClosure, 3);
     frame_->Push(&result);
   }
 }
@@ -4279,14 +4285,14 @@
     SetStackOverflow();
     return;
   }
-  InstantiateFunction(function_info);
+  InstantiateFunction(function_info, node->pretenure());
 }
 
 
 void CodeGenerator::VisitSharedFunctionInfoLiteral(
     SharedFunctionInfoLiteral* node) {
   Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
-  InstantiateFunction(node->shared_function_info());
+  InstantiateFunction(node->shared_function_info(), false);
 }
 
 
@@ -5592,6 +5598,18 @@
         // Push the receiver onto the frame.
         Load(property->obj());
 
+        // Load the name of the function.
+        Load(property->key());
+
+        // Swap the name of the function and the receiver on the stack to follow
+        // the calling convention for call ICs.
+        Result key = frame_->Pop();
+        Result receiver = frame_->Pop();
+        frame_->Push(&key);
+        frame_->Push(&receiver);
+        key.Unuse();
+        receiver.Unuse();
+
         // Load the arguments.
         int arg_count = args->length();
         for (int i = 0; i < arg_count; i++) {
@@ -5599,14 +5617,13 @@
           frame_->SpillTop();
         }
 
-        // Load the name of the function.
-        Load(property->key());
-
-        // Call the IC initialization code.
+        // Place the key on top of stack and call the IC initialization code.
+        frame_->PushElementAt(arg_count + 1);
         CodeForSourcePosition(node->position());
         Result result = frame_->CallKeyedCallIC(RelocInfo::CODE_TARGET,
                                                 arg_count,
                                                 loop_nesting());
+        frame_->Drop();  // Drop the key still on the stack.
         frame_->RestoreContextRegister();
         frame_->Push(&result);
       }
@@ -6062,7 +6079,7 @@
     __ movq(scratch2_,
             FieldOperand(scratch2_, GlobalObject::kGlobalContextOffset));
     __ cmpq(scratch1_,
-            CodeGenerator::ContextOperand(
+            ContextOperand(
                 scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
     __ j(not_equal, &false_result);
     // Set the bit in the map to indicate that it has been checked safe for
@@ -7206,6 +7223,11 @@
 }
 
 
+void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) {
+  frame_->Push(Factory::undefined_value());
+}
+
+
 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
   if (CheckForInlineRuntimeCall(node)) {
     return;
@@ -7219,7 +7241,7 @@
     // Push the builtins object found in the current global object.
     Result temp = allocator()->Allocate();
     ASSERT(temp.is_valid());
-    __ movq(temp.reg(), GlobalObject());
+    __ movq(temp.reg(), GlobalObjectOperand());
     __ movq(temp.reg(),
             FieldOperand(temp.reg(), GlobalObject::kBuiltinsOffset));
     frame_->Push(&temp);
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 1853c83..1a5e7df 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -341,10 +341,6 @@
   bool in_spilled_code() const { return in_spilled_code_; }
   void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
 
-  static Operand ContextOperand(Register context, int index) {
-    return Operand(context, Context::SlotOffset(index));
-  }
-
  private:
   // Type of a member function that generates inline code for a native function.
   typedef void (CodeGenerator::*InlineFunctionGenerator)
@@ -417,10 +413,6 @@
                                             JumpTarget* slow);
 
   // Expressions
-  static Operand GlobalObject() {
-    return ContextOperand(rsi, Context::GLOBAL_INDEX);
-  }
-
   void LoadCondition(Expression* x,
                      ControlDestination* destination,
                      bool force_control);
@@ -588,16 +580,13 @@
 
   void ProcessDeclarations(ZoneList<Declaration*>* declarations);
 
-  static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
-
-  static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
-
   // Declare global variables and functions in the given array of
   // name/value pairs.
   void DeclareGlobals(Handle<FixedArray> pairs);
 
   // Instantiate the function based on the shared function info.
-  void InstantiateFunction(Handle<SharedFunctionInfo> function_info);
+  void InstantiateFunction(Handle<SharedFunctionInfo> function_info,
+                           bool pretenure);
 
   // Support for type checks.
   void GenerateIsSmi(ZoneList<Expression*>* args);
@@ -680,6 +669,7 @@
 
   void GenerateHasCachedArrayIndex(ZoneList<Expression*>* args);
   void GenerateGetCachedArrayIndex(ZoneList<Expression*>* args);
+  void GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args);
 
 // Simple condition analysis.
   enum ConditionAnalysis {
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 00ea684..ee80169 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -36,6 +36,7 @@
 #include "full-codegen.h"
 #include "parser.h"
 #include "scopes.h"
+#include "stub-cache.h"
 
 namespace v8 {
 namespace internal {
@@ -836,17 +837,21 @@
 }
 
 
-void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
+void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
+                                       bool pretenure) {
   // Use the fast case closure allocation code that allocates in new
   // space for nested functions that don't need literals cloning.
-  if (scope()->is_function_scope() && info->num_literals() == 0) {
+  if (scope()->is_function_scope() &&
+      info->num_literals() == 0 &&
+      !pretenure) {
     FastNewClosureStub stub;
     __ Push(info);
     __ CallStub(&stub);
   } else {
     __ push(rsi);
     __ Push(info);
-    __ CallRuntime(Runtime::kNewClosure, 2);
+    __ Push(pretenure ? Factory::true_value() : Factory::false_value());
+    __ CallRuntime(Runtime::kNewClosure, 3);
   }
   context()->Plug(rax);
 }
@@ -912,7 +917,7 @@
 
   // All extension objects were empty and it is safe to use a global
   // load IC call.
-  __ movq(rax, CodeGenerator::GlobalObject());
+  __ movq(rax, GlobalObjectOperand());
   __ Move(rcx, slot->var()->name());
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
@@ -1016,7 +1021,7 @@
     // Use inline caching. Variable name is passed in rcx and the global
     // object on the stack.
     __ Move(rcx, var->name());
-    __ movq(rax, CodeGenerator::GlobalObject());
+    __ movq(rax, GlobalObjectOperand());
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
     context()->Plug(rax);
@@ -1555,7 +1560,7 @@
     // assignment.  Right-hand-side value is passed in rax, variable name in
     // rcx, and the global object on the stack.
     __ Move(rcx, var->name());
-    __ movq(rdx, CodeGenerator::GlobalObject());
+    __ movq(rdx, GlobalObjectOperand());
     Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
@@ -1727,8 +1732,7 @@
   SetSourcePosition(expr->position(), FORCED_POSITION);
   // Call the IC initialization code.
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
-                                                         in_loop);
+  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
   EmitCallIC(ic, mode);
   // Restore context register.
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
@@ -1739,26 +1743,33 @@
 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
                                             Expression* key,
                                             RelocInfo::Mode mode) {
-  // Code common for calls using the IC.
+  // Load the key.
+  VisitForAccumulatorValue(key);
+
+  // Swap the name of the function and the receiver on the stack to follow
+  // the calling convention for call ICs.
+  __ pop(rcx);
+  __ push(rax);
+  __ push(rcx);
+
+  // Load the arguments.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
   { PreserveStatementPositionScope scope(masm()->positions_recorder());
     for (int i = 0; i < arg_count; i++) {
       VisitForStackValue(args->at(i));
     }
-    VisitForAccumulatorValue(key);
-    __ movq(rcx, rax);
   }
   // Record source position for debugger.
   SetSourcePosition(expr->position(), FORCED_POSITION);
   // Call the IC initialization code.
   InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
-                                                              in_loop);
+  Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
+  __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize));  // Key.
   EmitCallIC(ic, mode);
   // Restore context register.
   __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
-  context()->Plug(rax);
+  context()->DropAndPlug(1, rax);  // Drop the key still on the stack.
 }
 
 
@@ -1834,7 +1845,7 @@
   } else if (var != NULL && !var->is_this() && var->is_global()) {
     // Call to a global variable.
     // Push global object as receiver for the call IC lookup.
-    __ push(CodeGenerator::GlobalObject());
+    __ push(GlobalObjectOperand());
     EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
   } else if (var != NULL && var->AsSlot() != NULL &&
              var->AsSlot()->type() == Slot::LOOKUP) {
@@ -1868,7 +1879,7 @@
         // Push function.
         __ push(rax);
         // Push global receiver.
-        __ movq(rbx, CodeGenerator::GlobalObject());
+        __ movq(rbx, GlobalObjectOperand());
         __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
         __ bind(&call);
       }
@@ -1907,7 +1918,7 @@
         // Push result (function).
         __ push(rax);
         // Push receiver object on stack.
-        __ movq(rcx, CodeGenerator::GlobalObject());
+        __ movq(rcx, GlobalObjectOperand());
         __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
         EmitCallWithStub(expr);
       } else {
@@ -1928,7 +1939,7 @@
       VisitForStackValue(fun);
     }
     // Load global receiver object.
-    __ movq(rbx, CodeGenerator::GlobalObject());
+    __ movq(rbx, GlobalObjectOperand());
     __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
     // Emit function call.
     EmitCallWithStub(expr);
@@ -2788,6 +2799,11 @@
 }
 
 
+void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
+  context()->Plug(Heap::kUndefinedValueRootIndex);
+}
+
+
 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   Handle<String> name = expr->name();
   if (name->length() > 0 && name->Get(0) == '_') {
@@ -2801,7 +2817,7 @@
 
   if (expr->is_jsruntime()) {
     // Prepare for calling JS runtime function.
-    __ movq(rax, CodeGenerator::GlobalObject());
+    __ movq(rax, GlobalObjectOperand());
     __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
   }
 
@@ -2815,7 +2831,7 @@
     // Call the JS runtime function using a call IC.
     __ Move(rcx, expr->name());
     InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
-    Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
+    Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
     EmitCallIC(ic, RelocInfo::CODE_TARGET);
     // Restore context register.
     __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
@@ -2851,7 +2867,7 @@
           VisitForStackValue(prop->obj());
           VisitForStackValue(prop->key());
         } else if (var->is_global()) {
-          __ push(CodeGenerator::GlobalObject());
+          __ push(GlobalObjectOperand());
           __ Push(var->name());
         } else {
           // Non-global variable.  Call the runtime to look up the context
@@ -3122,7 +3138,7 @@
   if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
     Comment cmnt(masm_, "Global variable");
     __ Move(rcx, proxy->name());
-    __ movq(rax, CodeGenerator::GlobalObject());
+    __ movq(rax, GlobalObjectOperand());
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     // Use a regular load, not a contextual load, to avoid a reference
     // error.
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 293d8a5..d919833 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -327,7 +327,7 @@
 
 
 void MacroAssembler::TailCallStub(CodeStub* stub) {
-  ASSERT(allow_stub_calls());  // calls are not allowed in some stubs
+  ASSERT(allow_stub_calls());  // Calls are not allowed in some stubs.
   Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
 }
 
@@ -456,6 +456,24 @@
 }
 
 
+MaybeObject* MacroAssembler::TryTailCallExternalReference(
+    const ExternalReference& ext, int num_arguments, int result_size) {
+  // ----------- S t a t e -------------
+  //  -- rsp[0] : return address
+  //  -- rsp[8] : argument num_arguments - 1
+  //  ...
+  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
+  // -----------------------------------
+
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // smarter.
+  Set(rax, num_arguments);
+  return TryJumpToExternalReference(ext, result_size);
+}
+
+
 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
                                      int num_arguments,
                                      int result_size) {
@@ -463,6 +481,15 @@
 }
 
 
+MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid,
+                                                int num_arguments,
+                                                int result_size) {
+  return TryTailCallExternalReference(ExternalReference(fid),
+                                      num_arguments,
+                                      result_size);
+}
+
+
 static int Offset(ExternalReference ref0, ExternalReference ref1) {
   int64_t offset = (ref0.address() - ref1.address());
   // Check that fits into int.
@@ -471,12 +498,22 @@
 }
 
 
-void MacroAssembler::PrepareCallApiFunction(int stack_space) {
-  EnterApiExitFrame(stack_space, 0);
+void MacroAssembler::PrepareCallApiFunction(int arg_stack_space) {
+#ifdef _WIN64
+  // We need to prepare a slot for result handle on stack and put
+  // a pointer to it into 1st arg register.
+  EnterApiExitFrame(arg_stack_space + 1);
+
+  // rcx must be used to pass the pointer to the return value slot.
+  lea(rcx, StackSpaceOperand(arg_stack_space));
+#else
+  EnterApiExitFrame(arg_stack_space);
+#endif
 }
 
 
-void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function) {
+MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
+    ApiFunction* function, int stack_space) {
   Label empty_result;
   Label prologue;
   Label promote_scheduled_exception;
@@ -499,7 +536,7 @@
   // Allocate HandleScope in callee-save registers.
   Register prev_next_address_reg = r14;
   Register prev_limit_reg = rbx;
-  Register base_reg = kSmiConstantRegister;
+  Register base_reg = r12;
   movq(base_reg, next_address);
   movq(prev_next_address_reg, Operand(base_reg, kNextOffset));
   movq(prev_limit_reg, Operand(base_reg, kLimitOffset));
@@ -528,18 +565,21 @@
   cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset));
   j(not_equal, &delete_allocated_handles);
   bind(&leave_exit_frame);
-  InitializeSmiConstantRegister();
 
   // Check if the function scheduled an exception.
   movq(rsi, scheduled_exception_address);
   Cmp(Operand(rsi, 0), Factory::the_hole_value());
   j(not_equal, &promote_scheduled_exception);
 
-  LeaveExitFrame();
-  ret(0);
+  LeaveApiExitFrame();
+  ret(stack_space * kPointerSize);
 
   bind(&promote_scheduled_exception);
-  TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
+  MaybeObject* result = TryTailCallRuntime(Runtime::kPromoteScheduledException,
+                                           0, 1);
+  if (result->IsFailure()) {
+    return result;
+  }
 
   bind(&empty_result);
   // It was zero; the result is undefined.
@@ -554,6 +594,8 @@
   call(rax);
   movq(rax, prev_limit_reg);
   jmp(&leave_exit_frame);
+
+  return result;
 }
 
 
@@ -566,6 +608,15 @@
 }
 
 
+MaybeObject* MacroAssembler::TryJumpToExternalReference(
+    const ExternalReference& ext, int result_size) {
+  // Set the entry point and jump to the C entry runtime stub.
+  movq(rbx, ext);
+  CEntryStub ces(result_size);
+  return TryTailCallStub(&ces);
+}
+
+
 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
   // Calls are not allowed in some stubs.
   ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
@@ -1690,22 +1741,15 @@
   store_rax(context_address);
 }
 
-void MacroAssembler::EnterExitFrameEpilogue(int result_size,
-                                            int argc) {
+
+void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space) {
 #ifdef _WIN64
-  // Reserve space on stack for result and argument structures, if necessary.
-  int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize;
-  // Reserve space for the Arguments object.  The Windows 64-bit ABI
-  // requires us to pass this structure as a pointer to its location on
-  // the stack.  The structure contains 2 values.
-  int argument_stack_space = argc * kPointerSize;
-  // We also need backing space for 4 parameters, even though
-  // we only pass one or two parameter, and it is in a register.
-  int argument_mirror_space = 4 * kPointerSize;
-  int total_stack_space =
-      argument_mirror_space + argument_stack_space + result_stack_space;
-  subq(rsp, Immediate(total_stack_space));
+  const int kShaddowSpace = 4;
+  arg_stack_space += kShaddowSpace;
 #endif
+  if (arg_stack_space > 0) {
+    subq(rsp, Immediate(arg_stack_space * kPointerSize));
+  }
 
   // Get the required frame alignment for the OS.
   static const int kFrameAlignment = OS::ActivationFrameAlignment();
@@ -1720,7 +1764,7 @@
 }
 
 
-void MacroAssembler::EnterExitFrame(int result_size) {
+void MacroAssembler::EnterExitFrame(int arg_stack_space) {
   EnterExitFramePrologue(true);
 
   // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
@@ -1728,25 +1772,17 @@
   int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
   lea(r12, Operand(rbp, r14, times_pointer_size, offset));
 
-  EnterExitFrameEpilogue(result_size, 2);
+  EnterExitFrameEpilogue(arg_stack_space);
 }
 
 
-void MacroAssembler::EnterApiExitFrame(int stack_space,
-                                       int argc,
-                                       int result_size) {
+void MacroAssembler::EnterApiExitFrame(int arg_stack_space) {
   EnterExitFramePrologue(false);
-
-  // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
-  // so it must be retained across the C-call.
-  int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
-  lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset));
-
-  EnterExitFrameEpilogue(result_size, argc);
+  EnterExitFrameEpilogue(arg_stack_space);
 }
 
 
-void MacroAssembler::LeaveExitFrame(int result_size) {
+void MacroAssembler::LeaveExitFrame() {
   // Registers:
   // r12 : argv
 
@@ -1758,6 +1794,22 @@
   // from the caller stack.
   lea(rsp, Operand(r12, 1 * kPointerSize));
 
+  // Push the return address to get ready to return.
+  push(rcx);
+
+  LeaveExitFrameEpilogue();
+}
+
+
+void MacroAssembler::LeaveApiExitFrame() {
+  movq(rsp, rbp);
+  pop(rbp);
+
+  LeaveExitFrameEpilogue();
+}
+
+
+void MacroAssembler::LeaveExitFrameEpilogue() {
   // Restore current context from top and clear it in debug mode.
   ExternalReference context_address(Top::k_context_address);
   movq(kScratchRegister, context_address);
@@ -1766,9 +1818,6 @@
   movq(Operand(kScratchRegister, 0), Immediate(0));
 #endif
 
-  // Push the return address to get ready to return.
-  push(rcx);
-
   // Clear the top frame.
   ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
   movq(kScratchRegister, c_entry_fp_address);
@@ -1840,7 +1889,6 @@
 
 
 void MacroAssembler::LoadAllocationTopHelper(Register result,
-                                             Register result_end,
                                              Register scratch,
                                              AllocationFlags flags) {
   ExternalReference new_space_allocation_top =
@@ -1862,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)) {
@@ -1923,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 =
@@ -1980,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 =
@@ -2022,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 2f6e956..0b7e601 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -155,17 +155,23 @@
   // debug mode. Expects the number of arguments in register rax and
   // sets up the number of arguments in register rdi and the pointer
   // to the first argument in register rsi.
-  void EnterExitFrame(int result_size = 1);
+  //
+  // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
+  // accessible via StackSpaceOperand.
+  void EnterExitFrame(int arg_stack_space = 0);
 
-  void EnterApiExitFrame(int stack_space,
-                         int argc,
-                         int result_size = 1);
+  // Enter specific kind of exit frame. Allocates arg_stack_space * kPointerSize
+  // memory (not GCed) on the stack accessible via StackSpaceOperand.
+  void EnterApiExitFrame(int arg_stack_space);
 
   // Leave the current exit frame. Expects/provides the return value in
   // register rax:rdx (untouched) and the pointer to the first
   // argument in register rsi.
-  void LeaveExitFrame(int result_size = 1);
+  void LeaveExitFrame();
 
+  // Leave the current exit frame. Expects/provides the return value in
+  // register rax (untouched).
+  void LeaveApiExitFrame();
 
   // ---------------------------------------------------------------------------
   // JavaScript invokes
@@ -813,22 +819,38 @@
                                  int num_arguments,
                                  int result_size);
 
+  MUST_USE_RESULT MaybeObject* TryTailCallExternalReference(
+      const ExternalReference& ext, int num_arguments, int result_size);
+
   // Convenience function: tail call a runtime routine (jump).
   void TailCallRuntime(Runtime::FunctionId fid,
                        int num_arguments,
                        int result_size);
 
+  MUST_USE_RESULT  MaybeObject* TryTailCallRuntime(Runtime::FunctionId fid,
+                                                   int num_arguments,
+                                                   int result_size);
+
   // Jump to a runtime routine.
   void JumpToExternalReference(const ExternalReference& ext, int result_size);
 
-  // Prepares stack to put arguments (aligns and so on).
-  // Uses calle-saved esi to restore stack state after call.
-  void PrepareCallApiFunction(int stack_space);
+  // Jump to a runtime routine.
+  MaybeObject* TryJumpToExternalReference(const ExternalReference& ext,
+                                          int result_size);
 
-  // Tail call an API function (jump). Allocates HandleScope, extracts
-  // returned value from handle and propogates exceptions.
-  // Clobbers ebx, edi and caller-save registers.
-  void CallApiFunctionAndReturn(ApiFunction* function);
+  // Prepares stack to put arguments (aligns and so on).
+  // WIN64 calling convention requires to put the pointer to the return value
+  // slot into rcx (rcx must be preserverd until TryCallApiFunctionAndReturn).
+  // Saves context (rsi). Clobbers rax. Allocates arg_stack_space * kPointerSize
+  // inside the exit frame (not GCed) accessible via StackSpaceOperand.
+  void PrepareCallApiFunction(int arg_stack_space);
+
+  // Calls an API function. Allocates HandleScope, extracts
+  // returned value from handle and propagates exceptions.
+  // Clobbers r12, r14, rbx and caller-save registers. Restores context.
+  // On return removes stack_space * kPointerSize (GCed).
+  MUST_USE_RESULT MaybeObject* TryCallApiFunctionAndReturn(
+      ApiFunction* function, int stack_space);
 
   // Before calling a C-function from generated code, align arguments on stack.
   // After aligning the frame, arguments must be stored in esp[0], esp[4],
@@ -919,16 +941,18 @@
   void LeaveFrame(StackFrame::Type type);
 
   void EnterExitFramePrologue(bool save_rax);
-  void EnterExitFrameEpilogue(int result_size, int argc);
+
+  // Allocates arg_stack_space * kPointerSize memory (not GCed) on the stack
+  // accessible via StackSpaceOperand.
+  void EnterExitFrameEpilogue(int arg_stack_space);
+
+  void LeaveExitFrameEpilogue();
 
   // 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.
@@ -982,6 +1006,28 @@
 }
 
 
+static inline Operand ContextOperand(Register context, int index) {
+  return Operand(context, Context::SlotOffset(index));
+}
+
+
+static inline Operand GlobalObjectOperand() {
+  return ContextOperand(rsi, Context::GLOBAL_INDEX);
+}
+
+
+// Provides access to exit frame stack space (not GCed).
+static inline Operand StackSpaceOperand(int index) {
+#ifdef _WIN64
+  const int kShaddowSpace = 4;
+  return Operand(rsp, (index + kShaddowSpace) * kPointerSize);
+#else
+  return Operand(rsp, index * kPointerSize);
+#endif
+}
+
+
+
 #ifdef GENERATED_CODE_COVERAGE
 extern void LogGeneratedCodeCoverage(const char* file_line);
 #define CODE_COVERAGE_STRINGIFY(x) #x
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 24609bf..7ba482c 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -497,8 +497,10 @@
   __ ret(0);
 }
 
+// Number of pointers to be reserved on stack for fast API call.
+static const int kFastApiCallArguments = 3;
 
-// Reserves space for the extra arguments to FastHandleApiCall in the
+// Reserves space for the extra arguments to API function in the
 // caller's frame.
 //
 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
@@ -508,48 +510,48 @@
   //  -- rsp[8] : last argument in the internal frame of the caller
   // -----------------------------------
   __ movq(scratch, Operand(rsp, 0));
-  __ subq(rsp, Immediate(4 * kPointerSize));
+  __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
   __ movq(Operand(rsp, 0), scratch);
   __ Move(scratch, Smi::FromInt(0));
-  __ movq(Operand(rsp, 1 * kPointerSize), scratch);
-  __ movq(Operand(rsp, 2 * kPointerSize), scratch);
-  __ movq(Operand(rsp, 3 * kPointerSize), scratch);
-  __ movq(Operand(rsp, 4 * kPointerSize), scratch);
+  for (int i = 1; i <= kFastApiCallArguments; i++) {
+     __ movq(Operand(rsp, i * kPointerSize), scratch);
+  }
 }
 
 
 // Undoes the effects of ReserveSpaceForFastApiCall.
 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
   // ----------- S t a t e -------------
-  //  -- rsp[0]  : return address
-  //  -- rsp[8]  : last fast api call extra argument
+  //  -- rsp[0]  : return address.
+  //  -- rsp[8]  : last fast api call extra argument.
   //  -- ...
-  //  -- rsp[32] : first fast api call extra argument
-  //  -- rsp[40] : last argument in the internal frame
+  //  -- rsp[kFastApiCallArguments * 8] : first fast api call extra argument.
+  //  -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
+  //                                          frame.
   // -----------------------------------
   __ movq(scratch, Operand(rsp, 0));
-  __ movq(Operand(rsp, 4 * kPointerSize), scratch);
-  __ addq(rsp, Immediate(kPointerSize * 4));
+  __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch);
+  __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
 }
 
 
-// Generates call to FastHandleApiCall builtin.
-static void GenerateFastApiCall(MacroAssembler* masm,
+// Generates call to API function.
+static bool GenerateFastApiCall(MacroAssembler* masm,
                                 const CallOptimization& optimization,
-                                int argc) {
+                                int argc,
+                                Failure** failure) {
   // ----------- S t a t e -------------
   //  -- rsp[0]              : return address
   //  -- rsp[8]              : object passing the type check
   //                           (last fast api call extra argument,
   //                            set by CheckPrototypes)
-  //  -- rsp[16]             : api call data
-  //  -- rsp[24]             : api callback
-  //  -- rsp[32]             : api function
+  //  -- rsp[16]             : api function
   //                           (first fast api call extra argument)
-  //  -- rsp[40]             : last argument
+  //  -- rsp[24]             : api call data
+  //  -- rsp[32]             : last argument
   //  -- ...
-  //  -- rsp[(argc + 5) * 8] : first argument
-  //  -- rsp[(argc + 6) * 8] : receiver
+  //  -- rsp[(argc + 3) * 8] : first argument
+  //  -- rsp[(argc + 4) * 8] : receiver
   // -----------------------------------
 
   // Get the function and setup the context.
@@ -557,38 +559,58 @@
   __ Move(rdi, Handle<JSFunction>(function));
   __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
 
-  // Pass the additional arguments FastHandleApiCall expects.
-  __ movq(Operand(rsp, 4 * kPointerSize), rdi);
-  bool info_loaded = false;
-  Object* callback = optimization.api_call_info()->callback();
-  if (Heap::InNewSpace(callback)) {
-    info_loaded = true;
-    __ Move(rcx, Handle<CallHandlerInfo>(optimization.api_call_info()));
-    __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kCallbackOffset));
+  // Pass the additional arguments.
+  __ movq(Operand(rsp, 2 * kPointerSize), rdi);
+  Object* call_data = optimization.api_call_info()->data();
+  Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
+  if (Heap::InNewSpace(call_data)) {
+    __ Move(rcx, api_call_info_handle);
+    __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
     __ movq(Operand(rsp, 3 * kPointerSize), rbx);
   } else {
-    __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(callback));
-  }
-  Object* call_data = optimization.api_call_info()->data();
-  if (Heap::InNewSpace(call_data)) {
-    if (!info_loaded) {
-      __ Move(rcx, Handle<CallHandlerInfo>(optimization.api_call_info()));
-    }
-    __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
-    __ movq(Operand(rsp, 2 * kPointerSize), rbx);
-  } else {
-    __ Move(Operand(rsp, 2 * kPointerSize), Handle<Object>(call_data));
+    __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(call_data));
   }
 
-  // Set the number of arguments.
-  __ movq(rax, Immediate(argc + 4));
+  // Prepare arguments.
+  __ lea(rbx, Operand(rsp, 3 * kPointerSize));
 
-  // Jump to the fast api call builtin (tail call).
-  Handle<Code> code = Handle<Code>(
-      Builtins::builtin(Builtins::FastHandleApiCall));
-  ParameterCount expected(0);
-  __ InvokeCode(code, expected, expected,
-                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
+  Object* callback = optimization.api_call_info()->callback();
+  Address api_function_address = v8::ToCData<Address>(callback);
+  ApiFunction fun(api_function_address);
+
+#ifdef _WIN64
+  // Win64 uses first register--rcx--for returned value.
+  Register arguments_arg = rdx;
+#else
+  Register arguments_arg = rdi;
+#endif
+
+  // Allocate the v8::Arguments structure in the arguments' space since
+  // it's not controlled by GC.
+  const int kApiStackSpace = 4;
+
+  __ PrepareCallApiFunction(kApiStackSpace);
+
+  __ movq(StackSpaceOperand(0), rbx);  // v8::Arguments::implicit_args_.
+  __ addq(rbx, Immediate(argc * kPointerSize));
+  __ movq(StackSpaceOperand(1), rbx);  // v8::Arguments::values_.
+  __ Set(StackSpaceOperand(2), argc);  // v8::Arguments::length_.
+  // v8::Arguments::is_construct_call_.
+  __ Set(StackSpaceOperand(3), 0);
+
+  // v8::InvocationCallback's argument.
+  __ lea(arguments_arg, StackSpaceOperand(0));
+  // Emitting a stub call may try to allocate (if the code is not
+  // already generated).  Do not allow the assembler to perform a
+  // garbage collection but instead return the allocation failure
+  // object.
+  MaybeObject* result =
+      masm->TryCallApiFunctionAndReturn(&fun, argc + kFastApiCallArguments + 1);
+  if (result->IsFailure()) {
+    *failure = Failure::cast(result);
+    return false;
+  }
+  return true;
 }
 
 
@@ -601,7 +623,7 @@
         arguments_(arguments),
         name_(name) {}
 
-  void Compile(MacroAssembler* masm,
+  bool Compile(MacroAssembler* masm,
                JSObject* object,
                JSObject* holder,
                String* name,
@@ -610,7 +632,8 @@
                Register scratch1,
                Register scratch2,
                Register scratch3,
-               Label* miss) {
+               Label* miss,
+               Failure** failure) {
     ASSERT(holder->HasNamedInterceptor());
     ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
 
@@ -620,17 +643,18 @@
     CallOptimization optimization(lookup);
 
     if (optimization.is_constant_call()) {
-      CompileCacheable(masm,
-                       object,
-                       receiver,
-                       scratch1,
-                       scratch2,
-                       scratch3,
-                       holder,
-                       lookup,
-                       name,
-                       optimization,
-                       miss);
+      return CompileCacheable(masm,
+                              object,
+                              receiver,
+                              scratch1,
+                              scratch2,
+                              scratch3,
+                              holder,
+                              lookup,
+                              name,
+                              optimization,
+                              miss,
+                              failure);
     } else {
       CompileRegular(masm,
                      object,
@@ -641,11 +665,12 @@
                      name,
                      holder,
                      miss);
+      return true;
     }
   }
 
  private:
-  void CompileCacheable(MacroAssembler* masm,
+  bool CompileCacheable(MacroAssembler* masm,
                         JSObject* object,
                         Register receiver,
                         Register scratch1,
@@ -655,7 +680,8 @@
                         LookupResult* lookup,
                         String* name,
                         const CallOptimization& optimization,
-                        Label* miss_label) {
+                        Label* miss_label,
+                        Failure** failure) {
     ASSERT(optimization.is_constant_call());
     ASSERT(!lookup->holder()->IsGlobalObject());
 
@@ -717,7 +743,13 @@
 
     // Invoke function.
     if (can_do_fast_api_call) {
-      GenerateFastApiCall(masm, optimization, arguments_.immediate());
+      bool success = GenerateFastApiCall(masm,
+                                         optimization,
+                                         arguments_.immediate(),
+                                         failure);
+      if (!success) {
+        return false;
+      }
     } else {
       __ InvokeFunction(optimization.constant_function(), arguments_,
                         JUMP_FUNCTION);
@@ -735,6 +767,8 @@
     if (can_do_fast_api_call) {
       FreeSpaceForFastApiCall(masm, scratch1);
     }
+
+    return true;
   }
 
   void CompileRegular(MacroAssembler* masm,
@@ -958,7 +992,9 @@
 
       if (depth != kInvalidProtoDepth) {
         __ IncrementCounter(&Counters::call_const_fast_api, 1);
-        ReserveSpaceForFastApiCall(masm(), rax);
+        // Allocate space for v8::Arguments implicit values. Must be initialized
+        // before to call any runtime function.
+        __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
       }
 
       // Check that the maps haven't changed.
@@ -1036,7 +1072,17 @@
   }
 
   if (depth != kInvalidProtoDepth) {
-    GenerateFastApiCall(masm(), optimization, argc);
+    Failure* failure;
+    // Move the return address on top of the stack.
+    __ movq(rax, Operand(rsp, 3 * kPointerSize));
+    __ movq(Operand(rsp, 0 * kPointerSize), rax);
+
+    // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains
+    // duplicate of return address and will be overwritten.
+    bool success = GenerateFastApiCall(masm(), optimization, argc, &failure);
+    if (!success) {
+      return failure;
+    }
   } else {
     __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
   }
@@ -1044,7 +1090,7 @@
   // Handle call cache miss.
   __ bind(&miss);
   if (depth != kInvalidProtoDepth) {
-    FreeSpaceForFastApiCall(masm(), rax);
+    __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
   }
 
   // Handle call cache miss.
@@ -1723,16 +1769,21 @@
   __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
 
   CallInterceptorCompiler compiler(this, arguments(), rcx);
-  compiler.Compile(masm(),
-                   object,
-                   holder,
-                   name,
-                   &lookup,
-                   rdx,
-                   rbx,
-                   rdi,
-                   rax,
-                   &miss);
+  Failure* failure;
+  bool success = compiler.Compile(masm(),
+                                  object,
+                                  holder,
+                                  name,
+                                  &lookup,
+                                  rdx,
+                                  rbx,
+                                  rdi,
+                                  rax,
+                                  &miss,
+                                  &failure);
+  if (!success) {
+    return failure;
+  }
 
   // Restore receiver.
   __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
@@ -1844,7 +1895,7 @@
   Label miss;
 
   Failure* failure = Failure::InternalError();
-  bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx, rdi,
+  bool success = GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi,
                                       callback, name, &miss, &failure);
   if (!success) {
     miss.Unuse();
@@ -2537,8 +2588,8 @@
       __ push(receiver);
       __ push(holder_reg);
       __ Move(holder_reg, Handle<AccessorInfo>(callback));
-      __ push(holder_reg);
       __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset));
+      __ push(holder_reg);
       __ push(name_reg);
       __ push(scratch2);  // restore return address
 
@@ -2585,16 +2636,15 @@
 
   Handle<AccessorInfo> callback_handle(callback);
 
-  __ EnterInternalFrame();
-  // Push the stack address where the list of arguments ends.
-  __ movq(scratch2, rsp);
-  __ subq(scratch2, Immediate(2 * kPointerSize));
-  __ push(scratch2);
+  // Insert additional parameters into the stack frame above return address.
+  ASSERT(!scratch2.is(reg));
+  __ pop(scratch2);  // Get return address to place it below.
+
   __ push(receiver);  // receiver
   __ push(reg);  // holder
   if (Heap::InNewSpace(callback_handle->data())) {
-    __ Move(scratch2, callback_handle);
-    __ push(FieldOperand(scratch2, AccessorInfo::kDataOffset));  // data
+    __ Move(scratch1, callback_handle);
+    __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));  // data
   } else {
     __ Push(Handle<Object>(callback_handle->data()));
   }
@@ -2607,42 +2657,43 @@
   Register accessor_info_arg = r8;
   Register name_arg = rdx;
 #else
-  Register accessor_info_arg = rdx;  // temporary, copied to rsi by the stub.
+  Register accessor_info_arg = rsi;
   Register name_arg = rdi;
 #endif
 
-  __ movq(accessor_info_arg, rsp);
-  __ addq(accessor_info_arg, Immediate(4 * kPointerSize));
+  ASSERT(!name_arg.is(scratch2));
   __ movq(name_arg, rsp);
+  __ push(scratch2);  // Restore return address.
 
   // Do call through the api.
-  ASSERT_EQ(5, ApiGetterEntryStub::kStackSpace);
   Address getter_address = v8::ToCData<Address>(callback->getter());
   ApiFunction fun(getter_address);
-  ApiGetterEntryStub stub(callback_handle, &fun);
-#ifdef _WIN64
-  // We need to prepare a slot for result handle on stack and put
-  // a pointer to it into 1st arg register.
-  __ push(Immediate(0));
-  __ movq(rcx, rsp);
-#endif
+
+  // 3 elements array for v8::Agruments::values_ and handler for name.
+  const int kStackSpace = 4;
+
+  // Allocate v8::AccessorInfo in non-GCed stack space.
+  const int kArgStackSpace = 1;
+
+  __ PrepareCallApiFunction(kArgStackSpace);
+  __ lea(rax, Operand(name_arg, 3 * kPointerSize));
+
+  // v8::AccessorInfo::args_.
+  __ movq(StackSpaceOperand(0), rax);
+
+  // The context register (rsi) has been saved in PrepareCallApiFunction and
+  // could be used to pass arguments.
+  __ lea(accessor_info_arg, StackSpaceOperand(0));
+
   // Emitting a stub call may try to allocate (if the code is not
   // already generated).  Do not allow the assembler to perform a
   // garbage collection but instead return the allocation failure
   // object.
-  MaybeObject* result = masm()->TryCallStub(&stub);
+  MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
   if (result->IsFailure()) {
     *failure = Failure::cast(result);
     return false;
   }
-#ifdef _WIN64
-  // Discard allocated slot.
-  __ addq(rsp, Immediate(kPointerSize));
-#endif
-  __ LeaveInternalFrame();
-
-  __ ret(0);
-
   return true;
 }
 
@@ -2839,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
@@ -2913,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.
@@ -2932,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/src/x64/virtual-frame-x64.cc b/src/x64/virtual-frame-x64.cc
index e88a993..3f7b1db 100644
--- a/src/x64/virtual-frame-x64.cc
+++ b/src/x64/virtual-frame-x64.cc
@@ -32,6 +32,7 @@
 #include "codegen-inl.h"
 #include "register-allocator-inl.h"
 #include "scopes.h"
+#include "stub-cache.h"
 #include "virtual-frame-inl.h"
 
 namespace v8 {
@@ -1194,7 +1195,7 @@
   // and dropped by the call.  The IC expects the name in rcx and the rest
   // on the stack, and drops them all.
   InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
-  Handle<Code> ic = cgen()->ComputeCallInitialize(arg_count, in_loop);
+  Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
   Result name = Pop();
   // Spill args, receiver, and function.  The call will drop args and
   // receiver.
@@ -1213,7 +1214,7 @@
   // on the stack, and drops them all.
   InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
   Handle<Code> ic =
-      cgen()->ComputeKeyedCallInitialize(arg_count, in_loop);
+      StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
   Result name = Pop();
   // Spill args, receiver, and function.  The call will drop args and
   // receiver.
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index 620cd82..ba3466d 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -42,6 +42,7 @@
     'test-api.cc',
     'test-ast.cc',
     'test-bignum.cc',
+    'test-bignum-dtoa.cc',
     'test-circular-queue.cc',
     'test-compiler.cc',
     'test-conversions.cc',
@@ -51,6 +52,7 @@
     'test-decls.cc',
     'test-diy-fp.cc',
     'test-double.cc',
+    'test-dtoa.cc',
     'test-fast-dtoa.cc',
     'test-fixed-dtoa.cc',
     'test-flags.cc',
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 6eb15d8..8ce7a79 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -38,6 +38,7 @@
 #include "utils.h"
 #include "cctest.h"
 #include "parser.h"
+#include "unicode-inl.h"
 
 static const bool kLogThreading = true;
 
@@ -6323,7 +6324,7 @@
                                    int expected) {
   v8::HandleScope scope;
   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
-  templ->SetNamedPropertyHandler(getter);
+  templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
   LocalContext context;
   context->Global()->Set(v8_str("o"), templ->NewInstance());
   v8::Handle<Value> value = CompileRun(source);
@@ -6334,7 +6335,8 @@
 static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
                                                  const AccessorInfo& info) {
   ApiTestFuzzer::Fuzz();
-  CHECK(v8_str("x")->Equals(name));
+  CHECK_EQ(v8_str("data"), info.Data());
+  CHECK_EQ(v8_str("x"), name);
   return v8::Integer::New(42);
 }
 
@@ -6732,7 +6734,8 @@
   v8::HandleScope scope;
   v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
   templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
-                                 InterceptorStoreICSetter);
+                                 InterceptorStoreICSetter,
+                                 0, 0, 0, v8_str("data"));
   LocalContext context;
   context->Global()->Set(v8_str("o"), templ->NewInstance());
   v8::Handle<Value> value = CompileRun(
@@ -7816,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);
@@ -8731,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;
@@ -10629,7 +10657,7 @@
 static uint32_t* stack_limit;
 
 static v8::Handle<Value> GetStackLimitCallback(const v8::Arguments& args) {
-  stack_limit = reinterpret_cast<uint32_t*>(i::StackGuard::climit());
+  stack_limit = reinterpret_cast<uint32_t*>(i::StackGuard::real_climit());
   return v8::Undefined();
 }
 
diff --git a/test/cctest/test-bignum-dtoa.cc b/test/cctest/test-bignum-dtoa.cc
new file mode 100644
index 0000000..51a9057
--- /dev/null
+++ b/test/cctest/test-bignum-dtoa.cc
@@ -0,0 +1,315 @@
+// 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 <stdlib.h>
+
+#include "v8.h"
+
+#include "bignum-dtoa.h"
+
+#include "cctest.h"
+#include "double.h"
+#include "gay-fixed.h"
+#include "gay-precision.h"
+#include "gay-shortest.h"
+#include "platform.h"
+
+using namespace v8::internal;
+
+
+// Removes trailing '0' digits.
+// Can return the empty string if all digits are 0.
+static void TrimRepresentation(Vector<char> representation) {
+  int len = strlen(representation.start());
+  int i;
+  for (i = len - 1; i >= 0; --i) {
+    if (representation[i] != '0') break;
+  }
+  representation[i + 1] = '\0';
+}
+
+
+static const int kBufferSize = 100;
+
+
+TEST(BignumDtoaVariousDoubles) {
+  char buffer_container[kBufferSize];
+  Vector<char> buffer(buffer_container, kBufferSize);
+  int length;
+  int point;
+
+  BignumDtoa(1.0, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
+  CHECK_EQ("1", buffer.start());
+  CHECK_EQ(1, point);
+
+  BignumDtoa(1.0, BIGNUM_DTOA_FIXED, 3, buffer, &length, &point);
+  CHECK_GE(3, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("1", buffer.start());
+  CHECK_EQ(1, point);
+
+  BignumDtoa(1.0, BIGNUM_DTOA_PRECISION, 3, buffer, &length, &point);
+  CHECK_GE(3, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("1", buffer.start());
+  CHECK_EQ(1, point);
+
+  BignumDtoa(1.5, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
+  CHECK_EQ("15", buffer.start());
+  CHECK_EQ(1, point);
+
+  BignumDtoa(1.5, BIGNUM_DTOA_FIXED, 10, buffer, &length, &point);
+  CHECK_GE(10, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("15", buffer.start());
+  CHECK_EQ(1, point);
+
+  BignumDtoa(1.5, BIGNUM_DTOA_PRECISION, 10, buffer, &length, &point);
+  CHECK_GE(10, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("15", buffer.start());
+  CHECK_EQ(1, point);
+
+  double min_double = 5e-324;
+  BignumDtoa(min_double, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
+  CHECK_EQ("5", buffer.start());
+  CHECK_EQ(-323, point);
+
+  BignumDtoa(min_double, BIGNUM_DTOA_FIXED, 5, buffer, &length, &point);
+  CHECK_GE(5, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("", buffer.start());
+
+  BignumDtoa(min_double, BIGNUM_DTOA_PRECISION, 5, buffer, &length, &point);
+  CHECK_GE(5, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("49407", buffer.start());
+  CHECK_EQ(-323, point);
+
+  double max_double = 1.7976931348623157e308;
+  BignumDtoa(max_double, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
+  CHECK_EQ("17976931348623157", buffer.start());
+  CHECK_EQ(309, point);
+
+  BignumDtoa(max_double, BIGNUM_DTOA_PRECISION, 7, buffer, &length, &point);
+  CHECK_GE(7, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("1797693", buffer.start());
+  CHECK_EQ(309, point);
+
+  BignumDtoa(4294967272.0, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
+  CHECK_EQ("4294967272", buffer.start());
+  CHECK_EQ(10, point);
+
+  BignumDtoa(4294967272.0, BIGNUM_DTOA_FIXED, 5, buffer, &length, &point);
+  CHECK_EQ("429496727200000", buffer.start());
+  CHECK_EQ(10, point);
+
+
+  BignumDtoa(4294967272.0, BIGNUM_DTOA_PRECISION, 14, buffer, &length, &point);
+  CHECK_GE(14, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("4294967272", buffer.start());
+  CHECK_EQ(10, point);
+
+  BignumDtoa(4.1855804968213567e298, BIGNUM_DTOA_SHORTEST, 0,
+             buffer, &length, &point);
+  CHECK_EQ("4185580496821357", buffer.start());
+  CHECK_EQ(299, point);
+
+  BignumDtoa(4.1855804968213567e298, BIGNUM_DTOA_PRECISION, 20,
+             buffer, &length, &point);
+  CHECK_GE(20, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("41855804968213567225", buffer.start());
+  CHECK_EQ(299, point);
+
+  BignumDtoa(5.5626846462680035e-309, BIGNUM_DTOA_SHORTEST, 0,
+             buffer, &length, &point);
+  CHECK_EQ("5562684646268003", buffer.start());
+  CHECK_EQ(-308, point);
+
+  BignumDtoa(5.5626846462680035e-309, BIGNUM_DTOA_PRECISION, 1,
+             buffer, &length, &point);
+  CHECK_GE(1, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("6", buffer.start());
+  CHECK_EQ(-308, point);
+
+  BignumDtoa(2147483648.0, BIGNUM_DTOA_SHORTEST, 0,
+             buffer, &length, &point);
+  CHECK_EQ("2147483648", buffer.start());
+  CHECK_EQ(10, point);
+
+
+  BignumDtoa(2147483648.0, BIGNUM_DTOA_FIXED, 2,
+             buffer, &length, &point);
+  CHECK_GE(2, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("2147483648", buffer.start());
+  CHECK_EQ(10, point);
+
+  BignumDtoa(2147483648.0, BIGNUM_DTOA_PRECISION, 5,
+             buffer, &length, &point);
+  CHECK_GE(5, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("21475", buffer.start());
+  CHECK_EQ(10, point);
+
+  BignumDtoa(3.5844466002796428e+298, BIGNUM_DTOA_SHORTEST, 0,
+             buffer, &length, &point);
+  CHECK_EQ("35844466002796428", buffer.start());
+  CHECK_EQ(299, point);
+
+  BignumDtoa(3.5844466002796428e+298, BIGNUM_DTOA_PRECISION, 10,
+             buffer, &length, &point);
+  CHECK_GE(10, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("35844466", buffer.start());
+  CHECK_EQ(299, point);
+
+  uint64_t smallest_normal64 = V8_2PART_UINT64_C(0x00100000, 00000000);
+  double v = Double(smallest_normal64).value();
+  BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
+  CHECK_EQ("22250738585072014", buffer.start());
+  CHECK_EQ(-307, point);
+
+  BignumDtoa(v, BIGNUM_DTOA_PRECISION, 20, buffer, &length, &point);
+  CHECK_GE(20, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("22250738585072013831", buffer.start());
+  CHECK_EQ(-307, point);
+
+  uint64_t largest_denormal64 = V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
+  v = Double(largest_denormal64).value();
+  BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
+  CHECK_EQ("2225073858507201", buffer.start());
+  CHECK_EQ(-307, point);
+
+  BignumDtoa(v, BIGNUM_DTOA_PRECISION, 20, buffer, &length, &point);
+  CHECK_GE(20, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("2225073858507200889", buffer.start());
+  CHECK_EQ(-307, point);
+
+  BignumDtoa(4128420500802942e-24, BIGNUM_DTOA_SHORTEST, 0,
+             buffer, &length, &point);
+  CHECK_EQ("4128420500802942", buffer.start());
+  CHECK_EQ(-8, point);
+
+  v = 3.9292015898194142585311918e-10;
+  BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
+  CHECK_EQ("39292015898194143", buffer.start());
+
+  v = 4194304.0;
+  BignumDtoa(v, BIGNUM_DTOA_FIXED, 5, buffer, &length, &point);
+  CHECK_GE(5, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("4194304", buffer.start());
+
+  v = 3.3161339052167390562200598e-237;
+  BignumDtoa(v, BIGNUM_DTOA_PRECISION, 19, buffer, &length, &point);
+  CHECK_GE(19, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("3316133905216739056", buffer.start());
+  CHECK_EQ(-236, point);
+
+  v = 7.9885183916008099497815232e+191;
+  BignumDtoa(v, BIGNUM_DTOA_PRECISION, 4, buffer, &length, &point);
+  CHECK_GE(4, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("7989", buffer.start());
+  CHECK_EQ(192, point);
+
+  v = 1.0000000000000012800000000e+17;
+  BignumDtoa(v, BIGNUM_DTOA_FIXED, 1, buffer, &length, &point);
+  CHECK_GE(1, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("100000000000000128", buffer.start());
+  CHECK_EQ(18, point);
+}
+
+
+TEST(BignumDtoaGayShortest) {
+  char buffer_container[kBufferSize];
+  Vector<char> buffer(buffer_container, kBufferSize);
+  int length;
+  int point;
+
+  Vector<const PrecomputedShortest> precomputed =
+      PrecomputedShortestRepresentations();
+  for (int i = 0; i < precomputed.length(); ++i) {
+    const PrecomputedShortest current_test = precomputed[i];
+    double v = current_test.v;
+    BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
+    CHECK_EQ(current_test.decimal_point, point);
+    CHECK_EQ(current_test.representation, buffer.start());
+  }
+}
+
+
+TEST(BignumDtoaGayFixed) {
+  char buffer_container[kBufferSize];
+  Vector<char> buffer(buffer_container, kBufferSize);
+  int length;
+  int point;
+
+  Vector<const PrecomputedFixed> precomputed =
+      PrecomputedFixedRepresentations();
+  for (int i = 0; i < precomputed.length(); ++i) {
+    const PrecomputedFixed current_test = precomputed[i];
+    double v = current_test.v;
+    int number_digits = current_test.number_digits;
+    BignumDtoa(v, BIGNUM_DTOA_FIXED, number_digits, buffer, &length, &point);
+    CHECK_EQ(current_test.decimal_point, point);
+    CHECK_GE(number_digits, length - point);
+    TrimRepresentation(buffer);
+    CHECK_EQ(current_test.representation, buffer.start());
+  }
+}
+
+
+TEST(BignumDtoaGayPrecision) {
+  char buffer_container[kBufferSize];
+  Vector<char> buffer(buffer_container, kBufferSize);
+  int length;
+  int point;
+
+  Vector<const PrecomputedPrecision> precomputed =
+      PrecomputedPrecisionRepresentations();
+  for (int i = 0; i < precomputed.length(); ++i) {
+    const PrecomputedPrecision current_test = precomputed[i];
+    double v = current_test.v;
+    int number_digits = current_test.number_digits;
+    BignumDtoa(v, BIGNUM_DTOA_PRECISION, number_digits,
+               buffer, &length, &point);
+    CHECK_EQ(current_test.decimal_point, point);
+    CHECK_GE(number_digits, length);
+    TrimRepresentation(buffer);
+    CHECK_EQ(current_test.representation, buffer.start());
+  }
+}
diff --git a/test/cctest/test-conversions.cc b/test/cctest/test-conversions.cc
index c62bbaa..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));
@@ -141,9 +143,6 @@
 }
 
 
-extern "C" double gay_strtod(const char* s00, const char** se);
-
-
 TEST(MaximumSignificantDigits) {
   char num[] =
       "4.4501477170144020250819966727949918635852426585926051135169509"
@@ -160,12 +159,12 @@
       "847003580761626016356864581135848683152156368691976240370422601"
       "6998291015625000000000000000000000000000000000e-308";
 
-  CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS));
+  CHECK_EQ(4.4501477170144017780491e-308, StringToDouble(num, NO_FLAGS));
 
   // Changes the result of strtod (at least in glibc implementation).
   num[sizeof(num) - 8] = '1';
 
-  CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS));
+  CHECK_EQ(4.4501477170144022721148e-308, StringToDouble(num, NO_FLAGS));
 }
 
 TEST(MinimumExponent) {
@@ -185,19 +184,19 @@
   "470035807616260163568645811358486831521563686919762403704226016"
   "998291015625000000000000000000000000000000000e-1108";
 
-  CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS));
+  CHECK_EQ(4.4501477170144017780491e-308, StringToDouble(num, NO_FLAGS));
 
   // Changes the result of strtod (at least in glibc implementation).
   num[sizeof(num) - 8] = '1';
 
-  CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS));
+  CHECK_EQ(4.4501477170144022721148e-308, StringToDouble(num, NO_FLAGS));
 }
 
 
 TEST(MaximumExponent) {
   char num[] = "0.16e309";
 
-  CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS));
+  CHECK_EQ(1.59999999999999997765e+308, StringToDouble(num, NO_FLAGS));
 }
 
 
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 748e3e8..7791185 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -6900,26 +6900,71 @@
 
 
 // Test that setting the terminate execution flag during debug break processing.
+static void TestDebugBreakInLoop(const char* loop_head,
+                                 const char** loop_bodies,
+                                 const char* loop_tail) {
+  // Receive 100 breaks for each test and then terminate JavaScript execution.
+  static int count = 0;
+
+  for (int i = 0; loop_bodies[i] != NULL; i++) {
+    count++;
+    max_break_point_hit_count = count * 100;
+    terminate_after_max_break_point_hit = true;
+
+    EmbeddedVector<char, 1024> buffer;
+    OS::SNPrintF(buffer,
+                 "function f() {%s%s%s}",
+                 loop_head, loop_bodies[i], loop_tail);
+
+    // Function with infinite loop.
+    CompileRun(buffer.start());
+
+    // Set the debug break to enter the debugger as soon as possible.
+    v8::Debug::DebugBreak();
+
+    // Call function with infinite loop.
+    CompileRun("f();");
+    CHECK_EQ(count * 100, break_point_hit_count);
+
+    CHECK(!v8::V8::IsExecutionTerminating());
+  }
+}
+
+
 TEST(DebugBreakLoop) {
   v8::HandleScope scope;
   DebugLocalContext env;
 
-  // Receive 100 breaks and terminate.
-  max_break_point_hit_count = 100;
-  terminate_after_max_break_point_hit = true;
-
   // Register a debug event listener which sets the break flag and counts.
   v8::Debug::SetDebugEventListener(DebugEventBreakMax);
 
-  // Function with infinite loop.
-  CompileRun("function f() { while (true) { } }");
+  CompileRun("var a = 1;");
+  CompileRun("function g() { }");
+  CompileRun("function h() { }");
 
-  // Set the debug break to enter the debugger as soon as possible.
-  v8::Debug::DebugBreak();
+  const char* loop_bodies[] = {
+      "",
+      "g()",
+      "if (a == 0) { g() }",
+      "if (a == 1) { g() }",
+      "if (a == 0) { g() } else { h() }",
+      "if (a == 0) { continue }",
+      "if (a == 1) { continue }",
+      "switch (a) { case 1: g(); }",
+      "switch (a) { case 1: continue; }",
+      "switch (a) { case 1: g(); break; default: h() }",
+      "switch (a) { case 1: continue; break; default: h() }",
+      NULL
+  };
 
-  // Call function with infinite loop.
-  CompileRun("f();");
-  CHECK_EQ(100, break_point_hit_count);
+  TestDebugBreakInLoop("while (true) {", loop_bodies, "}");
+  TestDebugBreakInLoop("while (a == 1) {", loop_bodies, "}");
+
+  TestDebugBreakInLoop("do {", loop_bodies, "} while (true)");
+  TestDebugBreakInLoop("do {", loop_bodies, "} while (a == 1)");
+
+  TestDebugBreakInLoop("for (;;) {", loop_bodies, "}");
+  TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}");
 
   // Get rid of the debug event listener.
   v8::Debug::SetDebugEventListener(NULL);
diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc
index 61f5ffc..c375831 100644
--- a/test/cctest/test-disasm-arm.cc
+++ b/test/cctest/test-disasm-arm.cc
@@ -87,9 +87,9 @@
 #define COMPARE(asm_, compare_string) \
   { \
     int pc_offset = assm.pc_offset(); \
-    byte *pc = &buffer[pc_offset]; \
+    byte *progcounter = &buffer[pc_offset]; \
     assm.asm_; \
-    if (!DisassembleAndCompare(pc, compare_string)) failure = true; \
+    if (!DisassembleAndCompare(progcounter, compare_string)) failure = true; \
   }
 
 
@@ -499,6 +499,19 @@
             "ed811b01       vstr d1, [r1 + 4*1]");
     COMPARE(vstr(d15, r10, 1020),
             "ed8afbff       vstr d15, [r10 + 4*255]");
+
+    COMPARE(vmsr(r5),
+            "eee15a10       vmsr FPSCR, r5");
+    COMPARE(vmsr(r10, pl),
+            "5ee1aa10       vmsrpl FPSCR, r10");
+    COMPARE(vmsr(pc),
+            "eee1fa10       vmsr FPSCR, APSR");
+    COMPARE(vmrs(r5),
+            "eef15a10       vmrs r5, FPSCR");
+    COMPARE(vmrs(r10, ge),
+            "aef1aa10       vmrsge r10, FPSCR");
+    COMPARE(vmrs(pc),
+            "eef1fa10       vmrs APSR, FPSCR");
   }
 
   VERIFY_RUN();
diff --git a/test/cctest/test-dtoa.cc b/test/cctest/test-dtoa.cc
new file mode 100644
index 0000000..ff0b660
--- /dev/null
+++ b/test/cctest/test-dtoa.cc
@@ -0,0 +1,331 @@
+// 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 <stdlib.h>
+
+#include "v8.h"
+
+#include "dtoa.h"
+
+#include "cctest.h"
+#include "double.h"
+#include "gay-fixed.h"
+#include "gay-precision.h"
+#include "gay-shortest.h"
+#include "platform.h"
+
+
+using namespace v8::internal;
+
+
+// Removes trailing '0' digits.
+static void TrimRepresentation(Vector<char> representation) {
+  int len = strlen(representation.start());
+  int i;
+  for (i = len - 1; i >= 0; --i) {
+    if (representation[i] != '0') break;
+  }
+  representation[i + 1] = '\0';
+}
+
+
+static const int kBufferSize = 100;
+
+
+TEST(DtoaVariousDoubles) {
+  char buffer_container[kBufferSize];
+  Vector<char> buffer(buffer_container, kBufferSize);
+  int length;
+  int point;
+  int sign;
+
+  DoubleToAscii(0.0, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+  CHECK_EQ("0", buffer.start());
+  CHECK_EQ(1, point);
+
+  DoubleToAscii(0.0, DTOA_FIXED, 2, buffer, &sign, &length, &point);
+  CHECK_EQ(1, length);
+  CHECK_EQ("0", buffer.start());
+  CHECK_EQ(1, point);
+
+  DoubleToAscii(0.0, DTOA_PRECISION, 3, buffer, &sign, &length, &point);
+  CHECK_EQ(1, length);
+  CHECK_EQ("0", buffer.start());
+  CHECK_EQ(1, point);
+
+  DoubleToAscii(1.0, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+  CHECK_EQ("1", buffer.start());
+  CHECK_EQ(1, point);
+
+  DoubleToAscii(1.0, DTOA_FIXED, 3, buffer, &sign, &length, &point);
+  CHECK_GE(3, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("1", buffer.start());
+  CHECK_EQ(1, point);
+
+  DoubleToAscii(1.0, DTOA_PRECISION, 3, buffer, &sign, &length, &point);
+  CHECK_GE(3, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("1", buffer.start());
+  CHECK_EQ(1, point);
+
+  DoubleToAscii(1.5, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+  CHECK_EQ("15", buffer.start());
+  CHECK_EQ(1, point);
+
+  DoubleToAscii(1.5, DTOA_FIXED, 10, buffer, &sign, &length, &point);
+  CHECK_GE(10, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("15", buffer.start());
+  CHECK_EQ(1, point);
+
+  DoubleToAscii(1.5, DTOA_PRECISION, 10, buffer, &sign, &length, &point);
+  CHECK_GE(10, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("15", buffer.start());
+  CHECK_EQ(1, point);
+
+  double min_double = 5e-324;
+  DoubleToAscii(min_double, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+  CHECK_EQ("5", buffer.start());
+  CHECK_EQ(-323, point);
+
+  DoubleToAscii(min_double, DTOA_FIXED, 5, buffer, &sign, &length, &point);
+  CHECK_GE(5, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("", buffer.start());
+  CHECK_GE(-5, point);
+
+  DoubleToAscii(min_double, DTOA_PRECISION, 5, buffer, &sign, &length, &point);
+  CHECK_GE(5, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("49407", buffer.start());
+  CHECK_EQ(-323, point);
+
+  double max_double = 1.7976931348623157e308;
+  DoubleToAscii(max_double, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+  CHECK_EQ("17976931348623157", buffer.start());
+  CHECK_EQ(309, point);
+
+  DoubleToAscii(max_double, DTOA_PRECISION, 7, buffer, &sign, &length, &point);
+  CHECK_GE(7, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("1797693", buffer.start());
+  CHECK_EQ(309, point);
+
+  DoubleToAscii(4294967272.0, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+  CHECK_EQ("4294967272", buffer.start());
+  CHECK_EQ(10, point);
+
+  DoubleToAscii(4294967272.0, DTOA_FIXED, 5, buffer, &sign, &length, &point);
+  CHECK_GE(5, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("4294967272", buffer.start());
+  CHECK_EQ(10, point);
+
+
+  DoubleToAscii(4294967272.0, DTOA_PRECISION, 14,
+                buffer, &sign, &length, &point);
+  CHECK_GE(14, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("4294967272", buffer.start());
+  CHECK_EQ(10, point);
+
+  DoubleToAscii(4.1855804968213567e298, DTOA_SHORTEST, 0,
+                buffer, &sign, &length, &point);
+  CHECK_EQ("4185580496821357", buffer.start());
+  CHECK_EQ(299, point);
+
+  DoubleToAscii(4.1855804968213567e298, DTOA_PRECISION, 20,
+                buffer, &sign, &length, &point);
+  CHECK_GE(20, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("41855804968213567225", buffer.start());
+  CHECK_EQ(299, point);
+
+  DoubleToAscii(5.5626846462680035e-309, DTOA_SHORTEST, 0,
+                buffer, &sign, &length, &point);
+  CHECK_EQ("5562684646268003", buffer.start());
+  CHECK_EQ(-308, point);
+
+  DoubleToAscii(5.5626846462680035e-309, DTOA_PRECISION, 1,
+                buffer, &sign, &length, &point);
+  CHECK_GE(1, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("6", buffer.start());
+  CHECK_EQ(-308, point);
+
+  DoubleToAscii(-2147483648.0, DTOA_SHORTEST, 0,
+                buffer, &sign, &length, &point);
+  CHECK_EQ(1, sign);
+  CHECK_EQ("2147483648", buffer.start());
+  CHECK_EQ(10, point);
+
+
+  DoubleToAscii(-2147483648.0, DTOA_FIXED, 2, buffer, &sign, &length, &point);
+  CHECK_GE(2, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ(1, sign);
+  CHECK_EQ("2147483648", buffer.start());
+  CHECK_EQ(10, point);
+
+  DoubleToAscii(-2147483648.0, DTOA_PRECISION, 5,
+                buffer, &sign, &length, &point);
+  CHECK_GE(5, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ(1, sign);
+  CHECK_EQ("21475", buffer.start());
+  CHECK_EQ(10, point);
+
+  DoubleToAscii(-3.5844466002796428e+298, DTOA_SHORTEST, 0,
+                buffer, &sign, &length, &point);
+  CHECK_EQ(1, sign);
+  CHECK_EQ("35844466002796428", buffer.start());
+  CHECK_EQ(299, point);
+
+  DoubleToAscii(-3.5844466002796428e+298, DTOA_PRECISION, 10,
+                buffer, &sign, &length, &point);
+  CHECK_EQ(1, sign);
+  CHECK_GE(10, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("35844466", buffer.start());
+  CHECK_EQ(299, point);
+
+  uint64_t smallest_normal64 = V8_2PART_UINT64_C(0x00100000, 00000000);
+  double v = Double(smallest_normal64).value();
+  DoubleToAscii(v, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+  CHECK_EQ("22250738585072014", buffer.start());
+  CHECK_EQ(-307, point);
+
+  DoubleToAscii(v, DTOA_PRECISION, 20, buffer, &sign, &length, &point);
+  CHECK_GE(20, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("22250738585072013831", buffer.start());
+  CHECK_EQ(-307, point);
+
+  uint64_t largest_denormal64 = V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
+  v = Double(largest_denormal64).value();
+  DoubleToAscii(v, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+  CHECK_EQ("2225073858507201", buffer.start());
+  CHECK_EQ(-307, point);
+
+  DoubleToAscii(v, DTOA_PRECISION, 20, buffer, &sign, &length, &point);
+  CHECK_GE(20, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("2225073858507200889", buffer.start());
+  CHECK_EQ(-307, point);
+
+  DoubleToAscii(4128420500802942e-24, DTOA_SHORTEST, 0,
+                buffer, &sign, &length, &point);
+  CHECK_EQ(0, sign);
+  CHECK_EQ("4128420500802942", buffer.start());
+  CHECK_EQ(-8, point);
+
+  v = -3.9292015898194142585311918e-10;
+  DoubleToAscii(v, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+  CHECK_EQ("39292015898194143", buffer.start());
+
+  v = 4194304.0;
+  DoubleToAscii(v, DTOA_FIXED, 5, buffer, &sign, &length, &point);
+  CHECK_GE(5, length - point);
+  TrimRepresentation(buffer);
+  CHECK_EQ("4194304", buffer.start());
+
+  v = 3.3161339052167390562200598e-237;
+  DoubleToAscii(v, DTOA_PRECISION, 19, buffer, &sign, &length, &point);
+  CHECK_GE(19, length);
+  TrimRepresentation(buffer);
+  CHECK_EQ("3316133905216739056", buffer.start());
+  CHECK_EQ(-236, point);
+}
+
+
+TEST(DtoaGayShortest) {
+  char buffer_container[kBufferSize];
+  Vector<char> buffer(buffer_container, kBufferSize);
+  int sign;
+  int length;
+  int point;
+
+  Vector<const PrecomputedShortest> precomputed =
+      PrecomputedShortestRepresentations();
+  for (int i = 0; i < precomputed.length(); ++i) {
+    const PrecomputedShortest current_test = precomputed[i];
+    double v = current_test.v;
+    DoubleToAscii(v, DTOA_SHORTEST, 0, buffer, &sign, &length, &point);
+    CHECK_EQ(0, sign);  // All precomputed numbers are positive.
+    CHECK_EQ(current_test.decimal_point, point);
+    CHECK_EQ(current_test.representation, buffer.start());
+  }
+}
+
+
+TEST(DtoaGayFixed) {
+  char buffer_container[kBufferSize];
+  Vector<char> buffer(buffer_container, kBufferSize);
+  int sign;
+  int length;
+  int point;
+
+  Vector<const PrecomputedFixed> precomputed =
+      PrecomputedFixedRepresentations();
+  for (int i = 0; i < precomputed.length(); ++i) {
+    const PrecomputedFixed current_test = precomputed[i];
+    double v = current_test.v;
+    int number_digits = current_test.number_digits;
+    DoubleToAscii(v, DTOA_FIXED, number_digits, buffer, &sign, &length, &point);
+    CHECK_EQ(0, sign);  // All precomputed numbers are positive.
+    CHECK_EQ(current_test.decimal_point, point);
+    CHECK_GE(number_digits, length - point);
+    TrimRepresentation(buffer);
+    CHECK_EQ(current_test.representation, buffer.start());
+  }
+}
+
+
+TEST(DtoaGayPrecision) {
+  char buffer_container[kBufferSize];
+  Vector<char> buffer(buffer_container, kBufferSize);
+  int sign;
+  int length;
+  int point;
+
+  Vector<const PrecomputedPrecision> precomputed =
+      PrecomputedPrecisionRepresentations();
+  for (int i = 0; i < precomputed.length(); ++i) {
+    const PrecomputedPrecision current_test = precomputed[i];
+    double v = current_test.v;
+    int number_digits = current_test.number_digits;
+    DoubleToAscii(v, DTOA_PRECISION, number_digits,
+                  buffer, &sign, &length, &point);
+    CHECK_EQ(0, sign);  // All precomputed numbers are positive.
+    CHECK_EQ(current_test.decimal_point, point);
+    CHECK_GE(number_digits, length);
+    TrimRepresentation(buffer);
+    CHECK_EQ(current_test.representation, buffer.start());
+  }
+}
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index b165190..95314d7 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -411,8 +411,12 @@
 
 static const v8::HeapGraphNode* GetGlobalObject(
     const v8::HeapSnapshot* snapshot) {
-  CHECK_EQ(1, snapshot->GetRoot()->GetChildrenCount());
-  return snapshot->GetRoot()->GetChild(0)->GetToNode();
+  CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount());
+  const v8::HeapGraphNode* global_obj =
+      snapshot->GetRoot()->GetChild(0)->GetToNode();
+  CHECK_EQ("Object", const_cast<i::HeapEntry*>(
+      reinterpret_cast<const i::HeapEntry*>(global_obj))->name());
+  return global_obj;
 }
 
 
@@ -479,21 +483,24 @@
 
   // Verify, that JS global object of env2 has '..2' properties.
   const v8::HeapGraphNode* a2_node =
-      GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2");
+      GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2");
   CHECK_NE(NULL, a2_node);
   CHECK_NE(
-      NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_1"));
+      NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1"));
   CHECK_NE(
-      NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_2"));
-  CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c2"));
+      NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2"));
+  CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2"));
 
-  // Verify that anything related to '[ABC]1' is not reachable.
   NamedEntriesDetector det;
   i_snapshot_env2->IterateEntries(&det);
   CHECK(det.has_A2);
   CHECK(det.has_B2);
   CHECK(det.has_C2);
 
+  /*
+    // Currently disabled. Too many retaining paths emerge, need to
+    // reduce the amount.
+
   // Verify 'a2' object retainers. They are:
   //  - (global object).a2
   //  - c2.x1, c2.x2, c2[1]
@@ -538,6 +545,7 @@
   CHECK(has_c2_1_ref);
   CHECK(has_b2_1_x_ref);
   CHECK(has_b2_2_x_ref);
+  */
 }
 
 
@@ -550,37 +558,28 @@
   CompileRun(
       "function X(a, b) { this.a = a; this.b = b; }\n"
       "x = new X(new X(), new X());\n"
-      "x.a.a = x.b;");
+      "(function() { x.a.a = x.b; })();");
   const v8::HeapSnapshot* snapshot =
       v8::HeapProfiler::TakeSnapshot(v8::String::New("sizes"));
   const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
   const v8::HeapGraphNode* x =
-      GetProperty(global, v8::HeapGraphEdge::kProperty, "x");
+      GetProperty(global, v8::HeapGraphEdge::kShortcut, "x");
   CHECK_NE(NULL, x);
-  const v8::HeapGraphNode* x_prototype =
-      GetProperty(x, v8::HeapGraphEdge::kProperty, "__proto__");
-  CHECK_NE(NULL, x_prototype);
   const v8::HeapGraphNode* x1 =
       GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
   CHECK_NE(NULL, x1);
   const v8::HeapGraphNode* x2 =
       GetProperty(x, v8::HeapGraphEdge::kProperty, "b");
   CHECK_NE(NULL, x2);
-  CHECK_EQ(
-      x->GetSelfSize() * 3,
-      x->GetReachableSize() - x_prototype->GetReachableSize());
-  CHECK_EQ(
-      x->GetSelfSize() * 3, x->GetRetainedSize());
-  CHECK_EQ(
-      x1->GetSelfSize() * 2,
-      x1->GetReachableSize() - x_prototype->GetReachableSize());
-  CHECK_EQ(
-      x1->GetSelfSize(), x1->GetRetainedSize());
-  CHECK_EQ(
-      x2->GetSelfSize(),
-      x2->GetReachableSize() - x_prototype->GetReachableSize());
-  CHECK_EQ(
-      x2->GetSelfSize(), x2->GetRetainedSize());
+
+  // Test approximate sizes.
+  CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(false));
+  CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(false));
+  CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(false));
+  // Test exact sizes.
+  CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(true));
+  CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(true));
+  CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(true));
 }
 
 
@@ -622,15 +621,15 @@
 
   const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
   const v8::HeapGraphNode* compiled =
-      GetProperty(global, v8::HeapGraphEdge::kProperty, "compiled");
+      GetProperty(global, v8::HeapGraphEdge::kShortcut, "compiled");
   CHECK_NE(NULL, compiled);
   CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType());
   const v8::HeapGraphNode* lazy =
-      GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy");
+      GetProperty(global, v8::HeapGraphEdge::kShortcut, "lazy");
   CHECK_NE(NULL, lazy);
   CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType());
   const v8::HeapGraphNode* anonymous =
-      GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous");
+      GetProperty(global, v8::HeapGraphEdge::kShortcut, "anonymous");
   CHECK_NE(NULL, anonymous);
   CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
   v8::String::AsciiValue anonymous_name(anonymous->GetName());
@@ -682,9 +681,9 @@
   const v8::HeapSnapshot* snapshot =
       v8::HeapProfiler::TakeSnapshot(v8::String::New("numbers"));
   const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
-  CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kProperty, "a"));
+  CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kShortcut, "a"));
   const v8::HeapGraphNode* b =
-      GetProperty(global, v8::HeapGraphEdge::kProperty, "b");
+      GetProperty(global, v8::HeapGraphEdge::kShortcut, "b");
   CHECK_NE(NULL, b);
   CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType());
 }
@@ -808,12 +807,12 @@
     if (node->GetType() == v8::HeapGraphNode::kObject) {
       v8::String::AsciiValue node_name(node->GetName());
       if (strcmp(*node_name, "A2") == 0) {
-        CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kProperty, "a"));
+        CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a"));
         CHECK(!found_A);
         found_A = true;
         s1_A_id = node->GetId();
       } else if (strcmp(*node_name, "B") == 0) {
-        CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kProperty, "b2"));
+        CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "b2"));
         CHECK(!found_B);
         found_B = true;
       }
@@ -832,7 +831,7 @@
     if (node->GetType() == v8::HeapGraphNode::kObject) {
       v8::String::AsciiValue node_name(node->GetName());
       if (strcmp(*node_name, "A") == 0) {
-        CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kProperty, "a"));
+        CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a"));
         CHECK(!found_A_del);
         found_A_del = true;
         s2_A_id = node->GetId();
@@ -858,37 +857,6 @@
 }
 
 
-namespace v8 {
-namespace internal {
-
-class HeapSnapshotTester {
- public:
-  static int CalculateNetworkSize(JSObject* obj) {
-    return HeapSnapshot::CalculateNetworkSize(obj);
-  }
-};
-
-} }  // namespace v8::internal
-
-// http://code.google.com/p/v8/issues/detail?id=822
-// Trying to call CalculateNetworkSize on an object with elements set
-// to non-FixedArray may cause an assertion error in debug builds.
-TEST(Issue822) {
-  v8::HandleScope scope;
-  LocalContext context;
-  const int kElementCount = 260;
-  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
-  i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(kElementCount,
-                                                              pixel_data);
-  v8::Handle<v8::Object> obj = v8::Object::New();
-  // Set the elements to be the pixels.
-  obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
-  i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
-  // This call must not cause an assertion error in debug builds.
-  i::HeapSnapshotTester::CalculateNetworkSize(*jsobj);
-}
-
-
 static const v8::HeapGraphNode* GetChild(
     const v8::HeapGraphNode* node,
     v8::HeapGraphNode::Type type,
@@ -932,13 +900,13 @@
       v8::HeapProfiler::TakeSnapshot(
           v8::String::New("agg"), v8::HeapSnapshot::kAggregated);
   const v8::HeapGraphNode* strings = GetChild(snapshot->GetRoot(),
-                                              v8::HeapGraphNode::kInternal,
+                                              v8::HeapGraphNode::kHidden,
                                               "STRING_TYPE");
   CHECK_NE(NULL, strings);
   CHECK_NE(0, strings->GetSelfSize());
   CHECK_NE(0, strings->GetInstancesCount());
   const v8::HeapGraphNode* maps = GetChild(snapshot->GetRoot(),
-                                           v8::HeapGraphNode::kInternal,
+                                           v8::HeapGraphNode::kHidden,
                                            "MAP_TYPE");
   CHECK_NE(NULL, maps);
   CHECK_NE(0, maps->GetSelfSize());
@@ -998,6 +966,67 @@
   CHECK(IsNodeRetainedAs(a_from_b, 1));  // B has 1 ref to A.
 }
 
+
+TEST(HeapEntryDominator) {
+  // The graph looks like this:
+  //
+  //                   -> node1
+  //                  a    |^
+  //          -> node5     ba
+  //         a             v|
+  //   node6           -> node2
+  //         b        a    |^
+  //          -> node4     ba
+  //                  b    v|
+  //                   -> node3
+  //
+  // The dominator for all nodes is node6.
+
+  v8::HandleScope scope;
+  LocalContext env;
+
+  CompileRun(
+      "function X(a, b) { this.a = a; this.b = b; }\n"
+      "node6 = new X(new X(new X()), new X(new X(),new X()));\n"
+      "(function(){\n"
+      "node6.a.a.b = node6.b.a;  // node1 -> node2\n"
+      "node6.b.a.a = node6.a.a;  // node2 -> node1\n"
+      "node6.b.a.b = node6.b.b;  // node2 -> node3\n"
+      "node6.b.b.a = node6.b.a;  // node3 -> node2\n"
+      "})();");
+
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("dominators"));
+
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  CHECK_NE(NULL, global);
+  const v8::HeapGraphNode* node6 =
+      GetProperty(global, v8::HeapGraphEdge::kShortcut, "node6");
+  CHECK_NE(NULL, node6);
+  const v8::HeapGraphNode* node5 =
+      GetProperty(node6, v8::HeapGraphEdge::kProperty, "a");
+  CHECK_NE(NULL, node5);
+  const v8::HeapGraphNode* node4 =
+      GetProperty(node6, v8::HeapGraphEdge::kProperty, "b");
+  CHECK_NE(NULL, node4);
+  const v8::HeapGraphNode* node3 =
+      GetProperty(node4, v8::HeapGraphEdge::kProperty, "b");
+  CHECK_NE(NULL, node3);
+  const v8::HeapGraphNode* node2 =
+      GetProperty(node4, v8::HeapGraphEdge::kProperty, "a");
+  CHECK_NE(NULL, node2);
+  const v8::HeapGraphNode* node1 =
+      GetProperty(node5, v8::HeapGraphEdge::kProperty, "a");
+  CHECK_NE(NULL, node1);
+
+  CHECK_EQ(node6, node1->GetDominatorNode());
+  CHECK_EQ(node6, node2->GetDominatorNode());
+  CHECK_EQ(node6, node3->GetDominatorNode());
+  CHECK_EQ(node6, node4->GetDominatorNode());
+  CHECK_EQ(node6, node5->GetDominatorNode());
+}
+
+
 namespace {
 
 class TestJSONStream : public v8::OutputStream {
@@ -1073,13 +1102,9 @@
   CHECK(parsed_snapshot->Has(v8::String::New("nodes")));
   CHECK(parsed_snapshot->Has(v8::String::New("strings")));
 
-  // Verify that nodes meta-info is valid JSON.
-  v8::Local<v8::Value> nodes_meta_parse_result = CompileRun(
-      "var parsed_meta = JSON.parse(parsed.nodes[0]); true;");
-  CHECK(!nodes_meta_parse_result.IsEmpty());
-
   // Get node and edge "member" offsets.
   v8::Local<v8::Value> meta_analysis_result = CompileRun(
+      "var parsed_meta = parsed.nodes[0];\n"
       "var children_count_offset ="
       "    parsed_meta.fields.indexOf('children_count');\n"
       "var children_offset ="
@@ -1094,19 +1119,21 @@
       "var child_to_node_offset ="
       "    children_meta.fields.indexOf('to_node');\n"
       "var property_type ="
-      "    children_meta.types[child_type_offset].indexOf('property');");
+      "    children_meta.types[child_type_offset].indexOf('property');\n"
+      "var shortcut_type ="
+      "    children_meta.types[child_type_offset].indexOf('shortcut');");
   CHECK(!meta_analysis_result.IsEmpty());
 
   // A helper function for processing encoded nodes.
   CompileRun(
-      "function GetChildPosByProperty(pos, prop_name) {\n"
+      "function GetChildPosByProperty(pos, prop_name, prop_type) {\n"
       "  var nodes = parsed.nodes;\n"
       "  var strings = parsed.strings;\n"
       "  for (var i = 0,\n"
       "      count = nodes[pos + children_count_offset] * child_fields_count;\n"
       "      i < count; i += child_fields_count) {\n"
       "    var child_pos = pos + children_offset + i;\n"
-      "    if (nodes[child_pos + child_type_offset] === property_type\n"
+      "    if (nodes[child_pos + child_type_offset] === prop_type\n"
       "       && strings[nodes[child_pos + child_name_offset]] === prop_name)\n"
       "        return nodes[child_pos + child_to_node_offset];\n"
       "  }\n"
@@ -1117,9 +1144,10 @@
       "GetChildPosByProperty(\n"
       "  GetChildPosByProperty(\n"
       "    GetChildPosByProperty("
-      "      parsed.nodes[1 + children_offset + child_to_node_offset],\"b\"),\n"
-      "    \"x\"),"
-      "  \"s\")");
+      "      parsed.nodes[1 + children_offset + child_to_node_offset],"
+      "      \"b\",shortcut_type),\n"
+      "    \"x\", property_type),"
+      "  \"s\", property_type)");
   CHECK(!string_obj_pos_val.IsEmpty());
   int string_obj_pos =
       static_cast<int>(string_obj_pos_val->ToNumber()->Value());
@@ -1150,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-heap.cc b/test/cctest/test-heap.cc
index 94d0555..fbe66ec 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -1095,3 +1095,32 @@
     ctx[i]->Exit();
   }
 }
+
+
+TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
+  InitializeVM();
+  intptr_t size_of_objects_1 = Heap::SizeOfObjects();
+  HeapIterator iterator(HeapIterator::kPreciseFiltering);
+  intptr_t size_of_objects_2 = 0;
+  for (HeapObject* obj = iterator.next();
+       obj != NULL;
+       obj = iterator.next()) {
+    size_of_objects_2 += obj->Size();
+  }
+  // Delta must be within 1% of the larger result.
+  if (size_of_objects_1 > size_of_objects_2) {
+    intptr_t delta = size_of_objects_1 - size_of_objects_2;
+    PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
+           "Iterator: %" V8_PTR_PREFIX "d, "
+           "delta: %" V8_PTR_PREFIX "d\n",
+           size_of_objects_1, size_of_objects_2, delta);
+    CHECK_GT(size_of_objects_1 / 100, delta);
+  } else {
+    intptr_t delta = size_of_objects_2 - size_of_objects_1;
+    PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, "
+           "Iterator: %" V8_PTR_PREFIX "d, "
+           "delta: %" V8_PTR_PREFIX "d\n",
+           size_of_objects_1, size_of_objects_2, delta);
+    CHECK_GT(size_of_objects_2 / 100, delta);
+  }
+}
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 7ae8dcf..a93fc27 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -27,6 +27,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "v8.h"
 
@@ -35,7 +36,6 @@
 #include "parser.h"
 #include "utils.h"
 #include "execution.h"
-#include "scanner.h"
 #include "preparser.h"
 #include "cctest.h"
 
@@ -261,12 +261,69 @@
     const char* program = programs[i];
     unibrow::Utf8InputBuffer<256> stream(program, strlen(program));
     i::CompleteParserRecorder log;
-    i::Scanner scanner;
-    scanner.Initialize(i::Handle<i::String>::null(), &stream, i::JAVASCRIPT);
-    v8::preparser::PreParser<i::Scanner, i::CompleteParserRecorder> preparser;
+    i::V8JavaScriptScanner scanner;
+    scanner.Initialize(i::Handle<i::String>::null(), &stream);
+    v8::preparser::PreParser preparser;
     bool result = preparser.PreParseProgram(&scanner, &log, true);
     CHECK(result);
     i::ScriptDataImpl data(log.ExtractData());
     CHECK(!data.has_error());
   }
 }
+
+
+TEST(RegressChromium62639) {
+  int marker;
+  i::StackGuard::SetStackLimit(
+      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+
+  const char* program = "var x = 'something';\n"
+                        "escape: function() {}";
+  // Fails parsing expecting an identifier after "function".
+  // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
+  // and then used the invalid currently scanned literal. This always
+  // failed in debug mode, and sometimes crashed in release mode.
+
+  unibrow::Utf8InputBuffer<256> stream(program, strlen(program));
+  i::ScriptDataImpl* data =
+      i::ParserApi::PreParse(i::Handle<i::String>::null(), &stream, NULL);
+  CHECK(data->HasError());
+  delete data;
+}
+
+
+TEST(Regress928) {
+  // Preparsing didn't consider the catch clause of a try statement
+  // as with-content, which made it assume that a function inside
+  // the block could be lazily compiled, and an extra, unexpected,
+  // entry was added to the data.
+  int marker;
+  i::StackGuard::SetStackLimit(
+      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
+
+  const char* program =
+      "try { } catch (e) { var foo = function () { /* first */ } }"
+      "var bar = function () { /* second */ }";
+
+  unibrow::Utf8InputBuffer<256> stream(program, strlen(program));
+  i::ScriptDataImpl* data =
+      i::ParserApi::PartialPreParse(i::Handle<i::String>::null(),
+                                    &stream, NULL);
+  CHECK(!data->HasError());
+
+  data->Initialize();
+
+  int first_function = strstr(program, "function") - program;
+  int first_lbrace = first_function + strlen("function () ");
+  CHECK_EQ('{', program[first_lbrace]);
+  i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace);
+  CHECK(!entry1.is_valid());
+
+  int second_function = strstr(program + first_lbrace, "function") - program;
+  int second_lbrace = second_function + strlen("function () ");
+  CHECK_EQ('{', program[second_lbrace]);
+  i::FunctionEntry entry2 = data->GetFunctionEntry(second_lbrace);
+  CHECK(entry2.is_valid());
+  CHECK_EQ('}', program[entry2.end_pos() - 1]);
+  delete data;
+}
diff --git a/test/cctest/test-strtod.cc b/test/cctest/test-strtod.cc
index d71d126..f5547db 100644
--- a/test/cctest/test-strtod.cc
+++ b/test/cctest/test-strtod.cc
@@ -259,6 +259,23 @@
   CHECK_EQ(1234567890123456789052345e115,
            StrtodChar("1234567890123456789052345", 115));
 
+  CHECK_EQ(5.445618932859895e-255,
+           StrtodChar("5445618932859895362967233318697132813618813095743952975"
+                      "4392982234069699615600475529427176366709107287468930197"
+                      "8628345413991790019316974825934906752493984055268219809"
+                      "5012176093045431437495773903922425632551857520884625114"
+                      "6241265881735209066709685420744388526014389929047617597"
+                      "0302268848374508109029268898695825171158085457567481507"
+                      "4162979705098246243690189880319928315307816832576838178"
+                      "2563074014542859888710209237525873301724479666744537857"
+                      "9026553346649664045621387124193095870305991178772256504"
+                      "4368663670643970181259143319016472430928902201239474588"
+                      "1392338901353291306607057623202353588698746085415097902"
+                      "6640064319118728664842287477491068264828851624402189317"
+                      "2769161449825765517353755844373640588822904791244190695"
+                      "2998382932630754670573838138825217065450843010498555058"
+                      "88186560731", -1035));
+
   // Boundary cases. Boundaries themselves should round to even.
   //
   // 0x1FFFFFFFFFFFF * 2^3 = 72057594037927928
diff --git a/test/mjsunit/compiler/literals.js b/test/mjsunit/compiler/literals.js
index 6775401..d846cf5 100644
--- a/test/mjsunit/compiler/literals.js
+++ b/test/mjsunit/compiler/literals.js
@@ -34,6 +34,43 @@
 
 assertEquals(8, eval("6;'abc';8"));
 
+// Characters just outside the ranges of hex-escapes.
+// "/" comes just before "0".
+assertEquals("x1/", "\x1/");
+assertEquals("u111/", "\u111/");
+assertEquals("\\x1/", RegExp("\\x1/").source);
+assertEquals("\\u111/", RegExp("\\u111/").source);
+
+// ":" comes just after "9".
+assertEquals("x1:", "\x1:");
+assertEquals("u111:", "\u111:");
+assertEquals("\\x1:", /\x1:/.source);
+assertEquals("\\u111:", /\u111:/.source);
+
+// "`" comes just before "a".
+assertEquals("x1`", "\x1`");
+assertEquals("u111`", "\u111`");
+assertEquals("\\x1`", /\x1`/.source);
+assertEquals("\\u111`", /\u111`/.source);
+
+// "g" comes just before "f".
+assertEquals("x1g", "\x1g");
+assertEquals("u111g", "\u111g");
+assertEquals("\\x1g", /\x1g/.source);
+assertEquals("\\u111g", /\u111g/.source);
+
+// "@" comes just before "A".
+assertEquals("x1@", "\x1@");
+assertEquals("u111@", "\u111@");
+assertEquals("\\x1@", /\x1@/.source);
+assertEquals("\\u111@", /\u111@/.source);
+
+// "G" comes just after "F".
+assertEquals("x1G", "\x1G");
+assertEquals("u111G", "\u111G");
+assertEquals("\\x1G", /\x1G/.source);
+assertEquals("\\u111G", /\u111G/.source);
+
 // Test some materialized array literals.
 assertEquals([1,2,3,4], eval('[1,2,3,4]'));
 assertEquals([[1,2],3,4], eval('[[1,2],3,4]'));
@@ -50,3 +87,4 @@
 assertEquals(17, eval('[1,2,3,4]; 17'));
 assertEquals(19, eval('var a=1, b=2; [a,b,3,4]; 19'));
 assertEquals(23, eval('var a=1, b=2; c=23; [a,b,3,4]; c'));
+
diff --git a/test/mjsunit/regress/regress-918.js b/test/mjsunit/regress/regress-918.js
new file mode 100644
index 0000000..4b6ddba
--- /dev/null
+++ b/test/mjsunit/regress/regress-918.js
@@ -0,0 +1,33 @@
+// 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.
+
+// Parser should not accept parentheses around labels.
+// See http://code.google.com/p/v8/issues/detail?id=918
+
+// The label was parsed as an expression and then tested for being a 
+// single identifier. This threw away the parentheses.
+assertThrows("(label):42;");
diff --git a/test/mjsunit/regress/regress-931.js b/test/mjsunit/regress/regress-931.js
new file mode 100644
index 0000000..d2fb8cc
--- /dev/null
+++ b/test/mjsunit/regress/regress-931.js
@@ -0,0 +1,48 @@
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// See http://code.google.com/p/v8/issues/detail?id=931.
+
+var sequence = '';
+
+var o = { f: function (x, y) { return x + y; },
+          2: function (x, y) { return x - y} };
+
+function first() { sequence += "1"; return o; }
+function second() { sequence += "2"; return "f"; }
+function third() { sequence += "3"; return 3; }
+function fourth() { sequence += "4"; return 4; }
+
+var result = (first()[second()](third(), fourth()))
+assertEquals(7, result);
+assertEquals("1234", sequence);
+
+function second_prime() { sequence += "2'"; return 2; }
+
+var result = (first()[second_prime()](third(), fourth()))
+assertEquals(-1, result);
+assertEquals("123412'34", sequence);
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 65b8620..c1a5aab 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -282,6 +282,8 @@
         '../../src/ast.h',
         '../../src/bignum.cc',
         '../../src/bignum.h',
+        '../../src/bignum-dtoa.cc',
+        '../../src/bignum-dtoa.h',
         '../../src/bootstrapper.cc',
         '../../src/bootstrapper.h',
         '../../src/builtins.cc',
@@ -331,7 +333,6 @@
         '../../src/disassembler.h',
         '../../src/dtoa.cc',
         '../../src/dtoa.h',
-        '../../src/dtoa-config.c',
         '../../src/diy-fp.cc',
         '../../src/diy-fp.h',
         '../../src/double.h',
@@ -405,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',
@@ -470,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',
@@ -484,6 +492,10 @@
         '../../src/zone-inl.h',
         '../../src/zone.cc',
         '../../src/zone.h',
+	'../../src/extensions/externalize-string-extension.cc',
+	'../../src/extensions/externalize-string-extension.h',
+	'../../src/extensions/gc-extension.cc',
+	'../../src/extensions/gc-extension.h',
       ],
       'conditions': [
         ['v8_target_arch=="arm"', {
@@ -651,11 +663,7 @@
             '../../src/platform-win32.cc',
           ],
           # 4355, 4800 came from common.vsprops
-          # 4018, 4244 were a per file config on dtoa-config.c
-          # TODO: It's probably possible and desirable to stop disabling the
-          # dtoa-specific warnings by modifying dtoa as was done in Chromium
-          # r9255.  Refer to that revision for details.
-          'msvs_disabled_warnings': [4355, 4800, 4018, 4244],
+          'msvs_disabled_warnings': [4355, 4800],
           'link_settings':  {
             'libraries': [ '-lwinmm.lib' ],
           },
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/v8.xcodeproj/project.pbxproj b/tools/v8.xcodeproj/project.pbxproj
index 5f93c78..08558cc 100644
--- a/tools/v8.xcodeproj/project.pbxproj
+++ b/tools/v8.xcodeproj/project.pbxproj
@@ -115,7 +115,6 @@
 		89A88E180E71A6960043BA31 /* property.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16D0E719B8F00D62E90 /* property.cc */; };
 		89A88E190E71A6970043BA31 /* rewriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16F0E719B8F00D62E90 /* rewriter.cc */; };
 		89A88E1A0E71A69B0043BA31 /* runtime.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1710E719B8F00D62E90 /* runtime.cc */; };
-		89A88E1B0E71A69D0043BA31 /* scanner-base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner-base.cc */; };
 		89A88E1B0E71A69D0043BA31 /* scanner.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner.cc */; };
 		89A88E1C0E71A69E0043BA31 /* scopeinfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1760E719B8F00D62E90 /* scopeinfo.cc */; };
 		89A88E1D0E71A6A00043BA31 /* scopes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1780E719B8F00D62E90 /* scopes.cc */; };
@@ -178,7 +177,6 @@
 		89F23C6C0E78D5B2006B2466 /* property.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16D0E719B8F00D62E90 /* property.cc */; };
 		89F23C6D0E78D5B2006B2466 /* rewriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF16F0E719B8F00D62E90 /* rewriter.cc */; };
 		89F23C6E0E78D5B2006B2466 /* runtime.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1710E719B8F00D62E90 /* runtime.cc */; };
-		89F23C6F0E78D5B2006B2466 /* scanner-base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner-base.cc */; };
 		89F23C6F0E78D5B2006B2466 /* scanner.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1730E719B8F00D62E90 /* scanner.cc */; };
 		89F23C700E78D5B2006B2466 /* scopeinfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1760E719B8F00D62E90 /* scopeinfo.cc */; };
 		89F23C710E78D5B2006B2466 /* scopes.cc in Sources */ = {isa = PBXBuildFile; fileRef = 897FF1780E719B8F00D62E90 /* scopes.cc */; };
@@ -483,8 +481,6 @@
 		897FF1700E719B8F00D62E90 /* rewriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rewriter.h; sourceTree = "<group>"; };
 		897FF1710E719B8F00D62E90 /* runtime.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = runtime.cc; sourceTree = "<group>"; };
 		897FF1720E719B8F00D62E90 /* runtime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = runtime.h; sourceTree = "<group>"; };
-		897FF1730E719B8F00D62E90 /* scanner-base.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scanner-base.cc; sourceTree = "<group>"; };
-		897FF1740E719B8F00D62E90 /* scanner-base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanner-base.h; sourceTree = "<group>"; };
 		897FF1730E719B8F00D62E90 /* scanner.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scanner.cc; sourceTree = "<group>"; };
 		897FF1740E719B8F00D62E90 /* scanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanner.h; sourceTree = "<group>"; };
 		897FF1750E719B8F00D62E90 /* SConscript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SConscript; sourceTree = "<group>"; };
@@ -947,8 +943,6 @@
 				897FF1700E719B8F00D62E90 /* rewriter.h */,
 				897FF1710E719B8F00D62E90 /* runtime.cc */,
 				897FF1720E719B8F00D62E90 /* runtime.h */,
-				897FF1730E719B8F00D62E90 /* scanner-base.cc */,
-				897FF1740E719B8F00D62E90 /* scanner-base.h */,
 				897FF1730E719B8F00D62E90 /* scanner.cc */,
 				897FF1740E719B8F00D62E90 /* scanner.h */,
 				897FF1760E719B8F00D62E90 /* scopeinfo.cc */,
@@ -1354,7 +1348,6 @@
 				58950D630F5551AF00F3E8BA /* register-allocator.cc in Sources */,
 				89A88E190E71A6970043BA31 /* rewriter.cc in Sources */,
 				89A88E1A0E71A69B0043BA31 /* runtime.cc in Sources */,
-				89A88E1B0E71A69D0043BA31 /* scanner-base.cc in Sources */,
 				89A88E1B0E71A69D0043BA31 /* scanner.cc in Sources */,
 				89A88E1C0E71A69E0043BA31 /* scopeinfo.cc in Sources */,
 				89A88E1D0E71A6A00043BA31 /* scopes.cc in Sources */,
@@ -1479,7 +1472,6 @@
 				58950D640F5551B500F3E8BA /* register-allocator.cc in Sources */,
 				89F23C6D0E78D5B2006B2466 /* rewriter.cc in Sources */,
 				89F23C6E0E78D5B2006B2466 /* runtime.cc in Sources */,
-				89F23C6F0E78D5B2006B2466 /* scanner-base.cc in Sources */,
 				89F23C6F0E78D5B2006B2466 /* scanner.cc in Sources */,
 				89F23C700E78D5B2006B2466 /* scopeinfo.cc in Sources */,
 				89F23C710E78D5B2006B2466 /* scopes.cc in Sources */,
diff --git a/tools/visual_studio/README.txt b/tools/visual_studio/README.txt
index dd9802b..c46aa37 100644
--- a/tools/visual_studio/README.txt
+++ b/tools/visual_studio/README.txt
@@ -7,8 +7,7 @@
 
 v8_base.vcproj
 --------------
-Base V8 library containing all the V8 code but no JavaScript library code. This
-includes third party code for string/number convertions (dtoa).
+Base V8 library containing all the V8 code but no JavaScript library code.
 
 v8.vcproj
 ---------
diff --git a/tools/visual_studio/v8_base.vcproj b/tools/visual_studio/v8_base.vcproj
index d1ee48d..902faff 100644
--- a/tools/visual_studio/v8_base.vcproj
+++ b/tools/visual_studio/v8_base.vcproj
@@ -122,70 +122,6 @@
 	</References>
 	<Files>
 		<Filter
-			Name="dtoa"
-			>
-			<File
-				RelativePath="..\..\src\dtoa-config.c"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						DisableSpecificWarnings="4018;4244"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						DisableSpecificWarnings="4018;4244"
-					/>
-				</FileConfiguration>
-			</File>
-    		<File
-				RelativePath="..\..\src\bignum.cc"
-				>
-			</File>
-    		<File
-				RelativePath="..\..\src\bignum.h"
-				>
-			</File>
-    		<File
-				RelativePath="..\..\src\bignum-dtoa.cc"
-				>
-			</File>
-    		<File
-				RelativePath="..\..\src\bignum-dtoa.h"
-				>
-			</File>
-    		<File
-				RelativePath="..\..\src\dtoa.cc"
-				>
-			</File>
-    		<File
-				RelativePath="..\..\src\dtoa.h"
-				>
-			</File>
-    		<File
-				RelativePath="..\..\src\fast-dtoa.cc"
-				>
-			</File>
-    		<File
-				RelativePath="..\..\src\fast-dtoa.h"
-				>
-			</File>
-			<File
-				RelativePath="..\..\src\fixed-dtoa.cc"
-				>
-			</File>
-    		<File
-				RelativePath="..\..\src\fixed-dtoa.h"
-				>
-			</File>
-		</Filter>
-		<Filter
 			Name="src"
 			>
 			<File
@@ -297,6 +233,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\cached-powers.cc"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\cached-powers.h"
 				>
 			</File>
@@ -489,6 +429,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dtoa.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\execution.cc"
 				>
 			</File>
@@ -513,6 +461,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\fixed-dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\fixed-dtoa.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\flags.cc"
 				>
 			</File>
@@ -806,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>
@@ -994,6 +966,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\strtod.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\strtod.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\ia32\stub-cache-ia32.cc"
 				>
 			</File>
@@ -1070,6 +1050,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\v8checks.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\v8globals.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\v8threads.cc"
 				>
 			</File>
@@ -1078,6 +1066,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\v8utils.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\variables.cc"
 				>
 			</File>
@@ -1141,6 +1133,22 @@
 				RelativePath="..\..\src\zone.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\src\extensions\externalize-string-extension.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\extensions\externalize-string-extension.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\extensions\gc-extension.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\extensions\gc-extension.h"
+				>
+			</File>
 			<Filter
 				Name="third party"
 				>
@@ -1177,6 +1185,10 @@
 				RelativePath="..\..\include\v8.h"
 				>
 			</File>
+			<File
+				RelativePath="..\..\include\v8stdint.h"
+				>
+			</File>
 		</Filter>
 	</Files>
 	<Globals>
diff --git a/tools/visual_studio/v8_base_arm.vcproj b/tools/visual_studio/v8_base_arm.vcproj
index 4f9ff4c..b87fdf8 100644
--- a/tools/visual_studio/v8_base_arm.vcproj
+++ b/tools/visual_studio/v8_base_arm.vcproj
@@ -122,30 +122,6 @@
 	</References>
 	<Files>
 		<Filter
-			Name="dtoa"
-			>
-			<File
-				RelativePath="..\..\src\dtoa-config.c"
-				>
-				<FileConfiguration
-					Name="Debug|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						DisableSpecificWarnings="4018;4244"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|Win32"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						DisableSpecificWarnings="4018;4244"
-					/>
-				</FileConfiguration>
-			</File>
-		</Filter>
-		<Filter
 			Name="src"
 			>
 			<File
@@ -229,6 +205,22 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\bignum.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bignum.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bignum-dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bignum-dtoa.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\builtins.cc"
 				>
 			</File>
@@ -241,6 +233,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\cached-powers.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\cached-powers.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\char-predicates-inl.h"
 				>
 			</File>
@@ -425,6 +425,26 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\diy-fp.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\diy-fp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\double.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dtoa.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\execution.cc"
 				>
 			</File>
@@ -441,6 +461,22 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\fast-dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\fast-dtoa.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\fixed-dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\fixed-dtoa.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\flags.cc"
 				>
 			</File>
@@ -928,6 +964,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\strtod.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\strtod.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\arm\stub-cache-arm.cc"
 				>
 			</File>
diff --git a/tools/visual_studio/v8_base_x64.vcproj b/tools/visual_studio/v8_base_x64.vcproj
index c84bce2..6d27472 100644
--- a/tools/visual_studio/v8_base_x64.vcproj
+++ b/tools/visual_studio/v8_base_x64.vcproj
@@ -122,30 +122,6 @@
 	</References>
 	<Files>
 		<Filter
-			Name="dtoa"
-			>
-			<File
-				RelativePath="..\..\src\dtoa-config.c"
-				>
-				<FileConfiguration
-					Name="Debug|x64"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						DisableSpecificWarnings="4018;4244"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|x64"
-					>
-					<Tool
-						Name="VCCLCompilerTool"
-						DisableSpecificWarnings="4018;4244"
-					/>
-				</FileConfiguration>
-			</File>
-		</Filter>
-		<Filter
 			Name="src"
 			>
 			<File
@@ -217,6 +193,22 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\bignum.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bignum.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bignum-dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\bignum-dtoa.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\bootstrapper.cc"
 				>
 			</File>
@@ -241,6 +233,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\cached-powers.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\cached-powers.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\char-predicates-inl.h"
 				>
 			</File>
@@ -417,6 +417,26 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\diy-fp.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\diy-fp.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\double.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\dtoa.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\execution.cc"
 				>
 			</File>
@@ -433,6 +453,22 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\fast-dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\fast-dtoa.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\fixed-dtoa.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\fixed-dtoa.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\flags.cc"
 				>
 			</File>
@@ -914,6 +950,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\src\strtod.cc"
+				>
+			</File>
+			<File
+				RelativePath="..\..\src\strtod.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\src\x64\stub-cache-x64.cc"
 				>
 			</File>